From 67b6e6bb47b162eceaf9cdbb737e20da4f418d2c Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Mon, 16 Oct 2023 15:18:25 +0200 Subject: [PATCH 001/315] advanced parameters - MaintenancePlanning --- src/libs/antares/study/fwd.cpp | 14 +++++++ src/libs/antares/study/fwd.h | 20 ++++++++++ src/libs/antares/study/parameters.cpp | 55 +++++++++++++++++++++++++++ src/libs/antares/study/parameters.h | 13 +++++++ src/libs/antares/study/study.cpp | 2 + 5 files changed, 104 insertions(+) diff --git a/src/libs/antares/study/fwd.cpp b/src/libs/antares/study/fwd.cpp index 5988b26e7e..ad418c8ef4 100644 --- a/src/libs/antares/study/fwd.cpp +++ b/src/libs/antares/study/fwd.cpp @@ -341,6 +341,20 @@ const char* RenewableGenerationModellingToCString(RenewableGenerationModelling r return ""; } +const char* MaintenancePlanningModellingToCString(MaintenancePlanningModelling mtcPlanning) +{ + switch (mtcPlanning) + { + case mpRandomized: + return "randomized"; + case mpOptimized: + return "optimized"; + case mpUnknown: + return ""; + } + return ""; +} + std::string mpsExportStatusToString(const mpsExportStatus& mps_export_status) { switch (mps_export_status) diff --git a/src/libs/antares/study/fwd.h b/src/libs/antares/study/fwd.h index 6db7c2ee57..4cab02f9ca 100644 --- a/src/libs/antares/study/fwd.h +++ b/src/libs/antares/study/fwd.h @@ -519,6 +519,26 @@ const char* RenewableGenerationModellingToCString(RenewableGenerationModelling r */ RenewableGenerationModelling StringToRenewableGenerationModelling(const AnyString& text); +/* + * Maintenance Planning + */ +enum MaintenancePlanningModelling +{ + mpRandomized = 0, // Default + mpOptimized, // Using Maintenance Planning algorithm + mpUnknown, +}; + +/*! +** \brief Convert a Maintenance-Planning into a text +*/ +const char* MaintenancePlanningModellingToCString(MaintenancePlanningModelling mtcPlanning); + +/*! +** \brief Convert a text into a MaintenancePlanningModelling +*/ +MaintenancePlanningModelling StringToMaintenancePlanningModelling(const AnyString& text); + // ------------------------ // MPS export status // ------------------------ diff --git a/src/libs/antares/study/parameters.cpp b/src/libs/antares/study/parameters.cpp index c10519942f..aec3aa684f 100644 --- a/src/libs/antares/study/parameters.cpp +++ b/src/libs/antares/study/parameters.cpp @@ -102,6 +102,28 @@ static bool ConvertStringToRenewableGenerationModelling(const AnyString& text, return false; } +static bool ConvertStringToMaintenancePlanningModelling(const AnyString& text, MaintenancePlanningModelling& out) +{ + CString<24, false> s = text; + s.trim(); + s.toLower(); + if (s == "randomized") + { + out = mpRandomized; + return true; + } + if (s == "optimized") + { + out = mpOptimized; + return true; + } + + logs.warning() << "parameters: invalid maintenance planning. Got '" << text << "'"; + out = mpUnknown; + + return false; +} + static bool ConvertCStrToResultFormat(const AnyString& text, ResultFormat& out) { CString<24, false> s = text; @@ -305,6 +327,7 @@ void Parameters::reset() unitCommitment.ucMode = ucHeuristic; nbCores.ncMode = ncAvg; renewableGeneration.rgModelling = rgAggregated; + maintenancePlanning.mpModelling = mpRandomized; // Misc improveUnitsStartup = false; @@ -738,6 +761,11 @@ static bool SGDIntLoadFamily_OtherPreferences(Parameters& d, return ConvertStringToRenewableGenerationModelling(value, d.renewableGeneration.rgModelling); + // Maintenance planning modelling + if (key == "maintenance-planning-modelling") + return ConvertStringToMaintenancePlanningModelling(value, + d.maintenancePlanning.mpModelling); + return false; } static bool SGDIntLoadFamily_AdvancedParameters(Parameters& d, @@ -1612,6 +1640,8 @@ void Parameters::saveToINI(IniFile& ini) const section->add("number-of-cores-mode", NumberOfCoresModeToCString(nbCores.ncMode)); section->add("renewable-generation-modelling", RenewableGenerationModellingToCString(renewableGeneration())); + section->add("maintenance-planning-modelling", + MaintenancePlanningModellingToCString(maintenancePlanning())); } // Advanced parameters @@ -1792,4 +1822,29 @@ bool Parameters::RenewableGeneration::isClusters() const { return rgModelling == Antares::Data::rgClusters; } + +MaintenancePlanningModelling Parameters::MaintenancePlanning::operator()() const +{ + return mpModelling; +} + +void Parameters::MaintenancePlanning::toRandomized() +{ + mpModelling = Antares::Data::mpRandomized; +} + +void Parameters::MaintenancePlanning::toOptimized() +{ + mpModelling = Antares::Data::mpOptimized; +} + +bool Parameters::MaintenancePlanning::isRandomized() const +{ + return mpModelling == Antares::Data::mpRandomized; +} + +bool Parameters::MaintenancePlanning::isOptimized() const +{ + return mpModelling == Antares::Data::mpOptimized; +} } // namespace Antares::Data diff --git a/src/libs/antares/study/parameters.h b/src/libs/antares/study/parameters.h index ffb5f1d643..19b0fa654b 100644 --- a/src/libs/antares/study/parameters.h +++ b/src/libs/antares/study/parameters.h @@ -459,6 +459,19 @@ class Parameters final RenewableGeneration renewableGeneration; + struct MaintenancePlanning + { + //! Maintenance Planning mode + MaintenancePlanningModelling mpModelling; + MaintenancePlanningModelling operator()() const; + void toRandomized(); + void toOptimized(); + bool isRandomized() const; + bool isOptimized() const; + }; + + MaintenancePlanning maintenancePlanning; + struct { //! Initial reservoir levels diff --git a/src/libs/antares/study/study.cpp b/src/libs/antares/study/study.cpp index d46123f8dd..48bd428696 100644 --- a/src/libs/antares/study/study.cpp +++ b/src/libs/antares/study/study.cpp @@ -150,6 +150,8 @@ void Study::createAsNew() // ... At study creation, renewable cluster is the default mode for RES (Renewable Energy // Source) parameters.renewableGeneration.rgModelling = Antares::Data::rgClusters; + // default mode for maintenancePlanning is Randomized + parameters.maintenancePlanning.mpModelling = Antares::Data::mpRandomized; parameters.yearsFilter = std::vector(1, true); From 830bbf85ad192be47b67ae1cfd49e187af925095 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 17 Oct 2023 16:41:59 +0200 Subject: [PATCH 002/315] Thermal clusters window - add options --- .../antares/study/parts/thermal/cluster.cpp | 28 +++++++++++++++++++ .../antares/study/parts/thermal/cluster.h | 9 ++++++ .../study/parts/thermal/cluster_list.cpp | 15 ++++++++++ 3 files changed, 52 insertions(+) diff --git a/src/libs/antares/study/parts/thermal/cluster.cpp b/src/libs/antares/study/parts/thermal/cluster.cpp index a6c8c49d6d..f7ef376a08 100644 --- a/src/libs/antares/study/parts/thermal/cluster.cpp +++ b/src/libs/antares/study/parts/thermal/cluster.cpp @@ -213,6 +213,11 @@ void Data::ThermalCluster::copyFrom(const ThermalCluster& cluster) modulation = cluster.modulation; cluster.modulation.unloadFromMemory(); + // Maintenance Planning additional parameters + optimizeMaintenance = cluster.optimizeMaintenance; + interPoPeriod = cluster.interPoPeriod; + poWindows = cluster.poWindows; + // Making sure that the data related to the prepro and timeseries are present // prepro if (not prepro) @@ -485,6 +490,11 @@ void Data::ThermalCluster::reset() modulation.fill(1.); modulation.fillColumn(thermalMinGenModulation, 0.); + // Maintenance Planning additional parameters + optimizeMaintenance = true; + interPoPeriod = 365; + poWindows = 0; + // prepro // warning: the variables `prepro` and `series` __must__ not be destroyed // since the interface may still have a pointer to them. @@ -597,6 +607,24 @@ bool Data::ThermalCluster::integrityCheck() ret = MatrixTestForPositiveValues(buffer.c_str(), &modulation) and ret; } + // Maintenance Planning additional parameters + if (interPoPeriod < 0 || interPoPeriod > 365) + { + interPoPeriod = 365; + logs.error() << "Thermal cluster: " << parentArea->name << '/' << pName + << ": The Inter PO period (days) must be within the range [0,365] (set to " + << interPoPeriod << ')'; + ret = false; + } + if (poWindows < 0 || poWindows > 365) + { + poWindows = 0; + logs.error() << "Thermal cluster: " << parentArea->name << '/' << pName + << ": The PO windows (+/- days) must be within the range [0,365] (set to " + << poWindows << ')'; + ret = false; + } + // la valeur minStablePower should not be modified /* if (minStablePower > nominalCapacity) diff --git a/src/libs/antares/study/parts/thermal/cluster.h b/src/libs/antares/study/parts/thermal/cluster.h index a75ce10a00..07b807bb43 100644 --- a/src/libs/antares/study/parts/thermal/cluster.h +++ b/src/libs/antares/study/parts/thermal/cluster.h @@ -294,6 +294,15 @@ class ThermalCluster final : public Cluster, public std::enable_shared_from_this //! Law (ts-generator) ThermalLaw plannedLaw; + // Maintenance Planning additional parameters + + //! Optimize maintenance yes/no + bool optimizeMaintenance = true; + //! Inter PO period (days) + int interPoPeriod = 365; + //! PO windows (+/- days) + int poWindows = 0; + //! \name Costs // Marginal (€/MWh) MA // Spread (€/MWh) SP diff --git a/src/libs/antares/study/parts/thermal/cluster_list.cpp b/src/libs/antares/study/parts/thermal/cluster_list.cpp index 2cd45cfa14..e016e882c1 100644 --- a/src/libs/antares/study/parts/thermal/cluster_list.cpp +++ b/src/libs/antares/study/parts/thermal/cluster_list.cpp @@ -231,6 +231,14 @@ static bool ThermalClusterLoadFromProperty(ThermalCluster& cluster, const IniFil if (p->key == "variableomcost") return p->value.to(cluster.variableomcost); + // Maintenance Planning additional parameters + if (p->key == "optimize-maintenance") + return p->value.to(cluster.optimizeMaintenance); + if (p->key == "inter-po-period") + return p->value.to(cluster.interPoPeriod); + if (p->key == "po-windows") + return p->value.to(cluster.poWindows); + //pollutant if (auto it = Pollutant::namesToEnum.find(p->key.c_str()); it != Pollutant::namesToEnum.end()) return p->value.to (cluster.emissions.factors[it->second]); @@ -405,6 +413,13 @@ bool ThermalClusterList::saveToFolder(const AnyString& folder) const if (!Math::Zero(c.variableomcost)) s->add("variableomcost", Math::Round(c.variableomcost,3)); + // Maintenance Planning additional parameters + if (!c.optimizeMaintenance) + s->add("optimize-maintenance", c.optimizeMaintenance); + if (c.interPoPeriod != 365) + s->add("inter-po-period", c.interPoPeriod); + if (!Math::Zero(c.poWindows)) + s->add("po-windows", c.poWindows); //pollutant factor for (auto const& [key, val] : Pollutant::namesToEnum) From c1e9bc201f84f755098801fdaa7d89311c8826da Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Mon, 30 Oct 2023 22:55:04 +0100 Subject: [PATCH 003/315] generate random days since last maintenance --- src/libs/antares/study/area/list.cpp | 1 + .../antares/study/parts/thermal/cluster.cpp | 2 ++ .../antares/study/parts/thermal/cluster.h | 5 ++++ .../study/parts/thermal/cluster_list.cpp | 24 +++++++++++++++++++ .../study/parts/thermal/cluster_list.h | 2 ++ 5 files changed, 34 insertions(+) diff --git a/src/libs/antares/study/area/list.cpp b/src/libs/antares/study/area/list.cpp index 5ce8975540..84d6b6128c 100644 --- a/src/libs/antares/study/area/list.cpp +++ b/src/libs/antares/study/area/list.cpp @@ -935,6 +935,7 @@ static bool AreaListLoadFromFolderSingleArea(Study& study, buffer.clear() << study.folderInput << SEP << "thermal" << SEP << "series"; ret = area.thermal.list.loadDataSeriesFromFolder(study, options, buffer) && ret; ret = area.thermal.list.loadEconomicCosts(study, buffer) && ret; + ret = area.thermal.list.generateRandomDaysSinceLastMaintenance(study) && ret; // In adequacy mode, all thermal clusters must be in 'mustrun' mode if (study.usedByTheSolver && study.parameters.mode == stdmAdequacy) diff --git a/src/libs/antares/study/parts/thermal/cluster.cpp b/src/libs/antares/study/parts/thermal/cluster.cpp index a91385e3e5..8ae1f93c1b 100644 --- a/src/libs/antares/study/parts/thermal/cluster.cpp +++ b/src/libs/antares/study/parts/thermal/cluster.cpp @@ -216,6 +216,7 @@ void Data::ThermalCluster::copyFrom(const ThermalCluster& cluster) optimizeMaintenance = cluster.optimizeMaintenance; interPoPeriod = cluster.interPoPeriod; poWindows = cluster.poWindows; + daysSinceLastMaintenance = cluster.daysSinceLastMaintenance; // Making sure that the data related to the prepro and timeseries are present // prepro @@ -485,6 +486,7 @@ void Data::ThermalCluster::reset() optimizeMaintenance = true; interPoPeriod = 365; poWindows = 0; + daysSinceLastMaintenance.clear(); // prepro // warning: the variables `prepro` and `series` __must__ not be destroyed diff --git a/src/libs/antares/study/parts/thermal/cluster.h b/src/libs/antares/study/parts/thermal/cluster.h index 07b807bb43..5a37dee030 100644 --- a/src/libs/antares/study/parts/thermal/cluster.h +++ b/src/libs/antares/study/parts/thermal/cluster.h @@ -302,6 +302,11 @@ class ThermalCluster final : public Cluster, public std::enable_shared_from_this int interPoPeriod = 365; //! PO windows (+/- days) int poWindows = 0; + // TODO: keep this here for now + // TODO: maybe create something like PreproThermal for Maintenance - and move everything there!!! + // days since last maintenance - random int number between 0-interPoPeriod + // defined per each unit of the cluster + std::vector daysSinceLastMaintenance; //! \name Costs // Marginal (€/MWh) MA diff --git a/src/libs/antares/study/parts/thermal/cluster_list.cpp b/src/libs/antares/study/parts/thermal/cluster_list.cpp index e016e882c1..8bccbf74a3 100644 --- a/src/libs/antares/study/parts/thermal/cluster_list.cpp +++ b/src/libs/antares/study/parts/thermal/cluster_list.cpp @@ -546,5 +546,29 @@ bool ThermalClusterList::loadEconomicCosts(Study& study, const AnyString& folder return ret; } +bool ThermalClusterList::generateRandomDaysSinceLastMaintenance(Study& study) +{ + if (empty() || study.parameters.maintenancePlanning.mpModelling != mpOptimized) + return true; + + bool ret = true; + MersenneTwister random[seedMax]; + + for (auto& [name, c] : cluster) + { + assert(c->parentArea and "cluster: invalid parent area"); + + if (!c->optimizeMaintenance) + continue; + + for (uint unitIndex = 0; unitIndex < c->unitCount; ++unitIndex) + { + c->daysSinceLastMaintenance.push_back( + (uint32_t)(floor(random[seedTsGenThermal].next() * c->interPoPeriod))); + } + } + return ret; +} + } // namespace Data } // namespace Antares diff --git a/src/libs/antares/study/parts/thermal/cluster_list.h b/src/libs/antares/study/parts/thermal/cluster_list.h index 1d15b028a9..b02077a0e1 100644 --- a/src/libs/antares/study/parts/thermal/cluster_list.h +++ b/src/libs/antares/study/parts/thermal/cluster_list.h @@ -84,6 +84,8 @@ class ThermalClusterList : public ClusterList bool loadEconomicCosts(Study& s, const AnyString& folder); + bool generateRandomDaysSinceLastMaintenance(Study& s); + bool savePreproToFolder(const AnyString& folder) const; bool saveEconomicCosts(const AnyString& folder) const; From 95c1c49bf7a7355df6c67d1c8e4281056d453e2b Mon Sep 17 00:00:00 2001 From: NikolaIlic Date: Tue, 31 Oct 2023 11:00:01 +0100 Subject: [PATCH 004/315] Initial Maintainence Folder --- src/libs/antares/study/CMakeLists.txt | 7 ++ src/libs/antares/study/area/list.cpp | 3 + .../maintenance_planning/MaintenanceGroup.cpp | 52 +++++++++++++ .../maintenance_planning/MaintenanceGroup.h | 77 +++++++++++++++++++ 4 files changed, 139 insertions(+) create mode 100644 src/libs/antares/study/maintenance_planning/MaintenanceGroup.cpp create mode 100644 src/libs/antares/study/maintenance_planning/MaintenanceGroup.h diff --git a/src/libs/antares/study/CMakeLists.txt b/src/libs/antares/study/CMakeLists.txt index b4db365a29..75a400a851 100644 --- a/src/libs/antares/study/CMakeLists.txt +++ b/src/libs/antares/study/CMakeLists.txt @@ -186,6 +186,12 @@ set(SRC_STUDY_BINDING_CONSTRAINT source_group("study\\constraint" FILES ${SRC_STUDY_BINDING_CONSTRAINT}) +set(SRC_STUDY_MAINTENANCE_PLANNING + maintenance_planning/MaintenanceGroup.h + maintenance_planning/MaintenanceGroup.cpp +) + +source_group("study\\maintenance" FILES ${SRC_STUDY_BINDING_CONSTRAINT}) set(SRC_XCAST xcast.h @@ -285,6 +291,7 @@ set(SRC_ALL ${SRC_STUDY_PARAMETERS} ${SRC_STUDY_FINDER} ${SRC_STUDY_BINDING_CONSTRAINT} + ${SRC_STUDY_MAINTENANCE_PLANNING} ${SRC_STUDY_PART_WIND} ${SRC_STUDY_PART_HYDRO} ${SRC_STUDY_PART_COMMON} diff --git a/src/libs/antares/study/area/list.cpp b/src/libs/antares/study/area/list.cpp index 0526108ee0..ce2ff0f5e1 100644 --- a/src/libs/antares/study/area/list.cpp +++ b/src/libs/antares/study/area/list.cpp @@ -682,6 +682,9 @@ bool AreaList::saveToFolder(const AnyString& folder) const buffer.clear() << folder << SEP << "input" << SEP << "bindingconstraints"; ret = IO::Directory::Create(buffer) && ret; + buffer.clear() << folder << SEP << "input" << SEP << "maintenanceplanning"; + ret = IO::Directory::Create(buffer) && ret; + buffer.clear() << folder << SEP << "input" << SEP << "links"; ret = IO::Directory::Create(buffer) && ret; diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroup.cpp b/src/libs/antares/study/maintenance_planning/MaintenanceGroup.cpp new file mode 100644 index 0000000000..e2e9d5134f --- /dev/null +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroup.cpp @@ -0,0 +1,52 @@ +#include "MaintenanceGroup.h" + +namespace Antares::Data +{ + +bool MaintenanceGroup::saveAreaListToFile(const std::string& filename) const +{ + if (!filename) + return false; + + std::string data; + { + // Preparing a new list of areas, sorted by their name + using List = std::list; + List list; + { + auto end = associatedAreas.end(); + for (auto i = associatedAreas.begin(); i != end; ++i) + list.push_back((i->second)->name.c_str()); + list.sort(); + } + { + auto end = list.end(); + for (auto i = list.begin(); i != end; ++i) + data << *i << '\n'; + } + } + + // Writing data into the appropriate file + std::ofstream file(filename); + if (!file.is_open()) + { + file << data; + return true; + } + logs.error() << "impossible to write " << filename; + return false; +} + +void MaintenanceGroup::name(const std::string& newname) +{ + name_ = newname; + ID_.clear(); + Antares::TransformNameIntoID(name_, ID_); +} + +uint MaintenanceGroup::getNbOfAssociatedAreas() const +{ + return associatedAreas.size(); +} + +} // namespace Antares::Data \ No newline at end of file diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroup.h b/src/libs/antares/study/maintenance_planning/MaintenanceGroup.h new file mode 100644 index 0000000000..fd496bf4fa --- /dev/null +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroup.h @@ -0,0 +1,77 @@ +/* +** 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 +#include +#include +#include "../fwd.h" +#include "../../constants.h" + +#include "../parts/thermal/cluster.h" +#include +#include + +#include "antares/study/filter.h" + +#include +#include +#include +#include +#include +#include "antares/study/area/area.h" +#include + +namespace Antares::Data +{ + +class MaintenanceGroup : public Yuni::NonCopyable +{ + using areaName = std::string; + using mapAreas = std::map; + using mapThermalClusters = std::map; +public: + void name(const std::string& newname); + uint getNbOfAssociatedAreas() const; + bool isEnabled() const; + bool saveAreaListToFile(const std::string& filename) const; + + + mapAreas associatedAreas; + mapThermalClusters associatedThermalClusters; + +private: + std::string name_; + std::string ID_; + + + + bool enabled_; + +}; + +} // namespace Antares::Data \ No newline at end of file From 2d2a628ea525b803dcf56e80b1bea94db4ae792b Mon Sep 17 00:00:00 2001 From: NikolaIlic Date: Tue, 31 Oct 2023 12:14:52 +0100 Subject: [PATCH 005/315] Comment due to build error --- .../maintenance_planning/MaintenanceGroup.cpp | 56 +++++++++---------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroup.cpp b/src/libs/antares/study/maintenance_planning/MaintenanceGroup.cpp index e2e9d5134f..c5587cd6a9 100644 --- a/src/libs/antares/study/maintenance_planning/MaintenanceGroup.cpp +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroup.cpp @@ -5,36 +5,36 @@ namespace Antares::Data bool MaintenanceGroup::saveAreaListToFile(const std::string& filename) const { - if (!filename) - return false; + // if (!filename) + // return false; - std::string data; - { - // Preparing a new list of areas, sorted by their name - using List = std::list; - List list; - { - auto end = associatedAreas.end(); - for (auto i = associatedAreas.begin(); i != end; ++i) - list.push_back((i->second)->name.c_str()); - list.sort(); - } - { - auto end = list.end(); - for (auto i = list.begin(); i != end; ++i) - data << *i << '\n'; - } - } + // std::string data; + // { + // // Preparing a new list of areas, sorted by their name + // using List = std::list; + // List list; + // { + // auto end = associatedAreas.end(); + // for (auto i = associatedAreas.begin(); i != end; ++i) + // list.push_back((i->second)->name.c_str()); + // list.sort(); + // } + // { + // auto end = list.end(); + // for (auto i = list.begin(); i != end; ++i) + // data << *i << '\n'; + // } + // } - // Writing data into the appropriate file - std::ofstream file(filename); - if (!file.is_open()) - { - file << data; - return true; - } - logs.error() << "impossible to write " << filename; - return false; + // // Writing data into the appropriate file + // std::ofstream file(filename); + // if (!file.is_open()) + // { + // file << data; + // return true; + // } + // logs.error() << "impossible to write " << filename; + return false; } void MaintenanceGroup::name(const std::string& newname) From 3fbd1f4050840ab287f525f2082c9d6a1622a8ed Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 31 Oct 2023 22:31:19 +0100 Subject: [PATCH 006/315] MaintenanceGroup - structure --- src/libs/antares/study/CMakeLists.txt | 3 +- .../maintenance_planning/MaintenanceGroup.cpp | 195 ++++++++++++++---- .../maintenance_planning/MaintenanceGroup.h | 192 +++++++++++++++-- .../maintenance_planning/MaintenanceGroup.hxx | 69 +++++++ 4 files changed, 405 insertions(+), 54 deletions(-) create mode 100644 src/libs/antares/study/maintenance_planning/MaintenanceGroup.hxx diff --git a/src/libs/antares/study/CMakeLists.txt b/src/libs/antares/study/CMakeLists.txt index 5257dbb359..238794baa0 100644 --- a/src/libs/antares/study/CMakeLists.txt +++ b/src/libs/antares/study/CMakeLists.txt @@ -182,10 +182,11 @@ source_group("study\\constraint" FILES ${SRC_STUDY_BINDING_CONSTRAINT}) set(SRC_STUDY_MAINTENANCE_PLANNING maintenance_planning/MaintenanceGroup.h + maintenance_planning/MaintenanceGroup.hxx maintenance_planning/MaintenanceGroup.cpp ) -source_group("study\\maintenance" FILES ${SRC_STUDY_BINDING_CONSTRAINT}) +source_group("study\\maintenance" FILES ${SRC_STUDY_MAINTENANCE_PLANNING}) set(SRC_XCAST xcast.h diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroup.cpp b/src/libs/antares/study/maintenance_planning/MaintenanceGroup.cpp index c5587cd6a9..d49cabf4ef 100644 --- a/src/libs/antares/study/maintenance_planning/MaintenanceGroup.cpp +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroup.cpp @@ -1,52 +1,169 @@ #include "MaintenanceGroup.h" +#include +#include +#include +#include +#include "../study.h" + +using namespace Yuni; +using namespace Antares; + +#define SEP IO::Separator namespace Antares::Data { -bool MaintenanceGroup::saveAreaListToFile(const std::string& filename) const -{ - // if (!filename) - // return false; - - // std::string data; - // { - // // Preparing a new list of areas, sorted by their name - // using List = std::list; - // List list; - // { - // auto end = associatedAreas.end(); - // for (auto i = associatedAreas.begin(); i != end; ++i) - // list.push_back((i->second)->name.c_str()); - // list.sort(); - // } - // { - // auto end = list.end(); - // for (auto i = list.begin(); i != end; ++i) - // data << *i << '\n'; - // } - // } - - // // Writing data into the appropriate file - // std::ofstream file(filename); - // if (!file.is_open()) - // { - // file << data; - // return true; - // } - // logs.error() << "impossible to write " << filename; - return false; -} - -void MaintenanceGroup::name(const std::string& newname) -{ - name_ = newname; +const char* MaintenanceGroup::ResidualLoadDefinitionTypeToCString( + MaintenanceGroup::ResidualLoadDefinitionType type) +{ + static const char* const names[typeMax + 1] = {"", "weights", "timeserie", ""}; + assert((uint)type < (uint)(typeMax + 1)); + return names[type]; +} + +MaintenanceGroup::ResidualLoadDefinitionType MaintenanceGroup::StringToResidualLoadDefinitionType( + const AnyString& text) +{ + ShortString16 l(text); + l.toLower(); + + if (l == "weights") + return typeWeights; + if (l == "timeserie") + return typeTimeserie; + return typeUnknown; +} + +MaintenanceGroup::~MaintenanceGroup() +{ +#ifndef NDEBUG + name_ = ""; + ID_ = ""; +#endif +} + +void MaintenanceGroup::name(const std::string& newName) +{ + name_ = std::move(newName); ID_.clear(); Antares::TransformNameIntoID(name_, ID_); } -uint MaintenanceGroup::getNbOfAssociatedAreas() const +void MaintenanceGroup::loadWeight(const Area* area, double w) +{ + if (area) + loadWeights_[area] = w; +} + +void MaintenanceGroup::renewableWeight(const Area* area, double w) +{ + if (area) + renewableWeights_[area] = w; +} + +void MaintenanceGroup::rorWeight(const Area* area, double w) +{ + if (area) + rorWeights_[area] = w; +} + +void MaintenanceGroup::removeAllWeights() +{ + loadWeights_.clear(); + renewableWeights_.clear(); + rorWeights_.clear(); +} + +void MaintenanceGroup::resetToDefaultValues() +{ + enabled_ = true; + removeAllWeights(); +} + +void MaintenanceGroup::clear() +{ + // Name / ID + this->name_.clear(); + this->ID_.clear(); + this->type_ = typeUnknown; + this->enabled_ = true; +} + +bool MaintenanceGroup::contains(const Area* area) const +{ + const auto i = loadWeights_.find(area); + return (i != loadWeights_.end()); +} + +uint64_t MaintenanceGroup::memoryUsage() const +{ + return sizeof(MaintenanceGroup) + // Estimation + + loadWeights_.size() * (sizeof(double) + 3 * sizeof(void*)) + // Estimation + + renewableWeights_.size() * (sizeof(int) + 3 * sizeof(void*)) + // Estimation + + rorWeights_.size() * (sizeof(double) + 3 * sizeof(void*)); +} + +void MaintenanceGroup::enabled(bool v) +{ + enabled_ = v; +} + +void MaintenanceGroup::setResidualLoadDefinitionType(MaintenanceGroup::ResidualLoadDefinitionType t) +{ + type_ = t; +} + +// TODO: not implemented for now - used only for UI - maybe to added later +bool MaintenanceGroup::hasAllWeightedClustersOnLayer(size_t layerID) +{ + return true; +} +// TODO: not implemented for now - used only for UI - maybe to added later +void MaintenanceGroup::copyWeights() +{ +} + +double MaintenanceGroup::loadWeight(const Area* area) const +{ + auto i = loadWeights_.find(area); + return (i != loadWeights_.end()) ? i->second : 0.; +} + +double MaintenanceGroup::renewableWeight(const Area* area) const +{ + auto i = renewableWeights_.find(area); + return (i != renewableWeights_.end()) ? i->second : 0.; +} + +double MaintenanceGroup::rorWeight(const Area* area) const +{ + auto i = rorWeights_.find(area); + return (i != rorWeights_.end()) ? i->second : 0.; +} + +void MaintenanceGroup::clearAndReset(const MaintenanceGroupName& name, + MaintenanceGroup::ResidualLoadDefinitionType newType) +{ + // Name / ID + name_ = std::move(name); + ID_.clear(); + TransformNameIntoID(name_, ID_); + // New type + type_ = newType; + // Resetting the weights + removeAllWeights(); +} + +void MaintenanceGroup::copyFrom(MaintenanceGroup const* original) { - return associatedAreas.size(); + clearAndReset(original->name(), original->type()); + loadWeights_ = original->loadWeights_; + renewableWeights_ = original->renewableWeights_; + rorWeights_ = original->rorWeights_; + enabled_ = original->enabled_; } } // namespace Antares::Data \ No newline at end of file diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroup.h b/src/libs/antares/study/maintenance_planning/MaintenanceGroup.h index fd496bf4fa..ee747ddf7e 100644 --- a/src/libs/antares/study/maintenance_planning/MaintenanceGroup.h +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroup.h @@ -48,30 +48,194 @@ namespace Antares::Data { - +// Forward declaration +struct CompareMaintenanceGroupName; class MaintenanceGroup : public Yuni::NonCopyable { - using areaName = std::string; - using mapAreas = std::map; - using mapThermalClusters = std::map; + // friend class MaintenanceGroupLoader; + // friend class MaintenanceGroupSaver; + public: - void name(const std::string& newname); - uint getNbOfAssociatedAreas() const; - bool isEnabled() const; - bool saveAreaListToFile(const std::string& filename) const; + enum ResidualLoadDefinitionType + { + //! Unknown status + typeUnknown = 0, + //! residual Load timeserie is defined using weights + typeWeights, + //! residual Load timeserie is given directly as an input + typeTimeserie, + //! The maximum number of types + typeMax + }; + + using MaintenanceGroupName = std::string; + //! Map of load, renewable or ror weight-s + using weightMap = std::map; + + /*! + ** \brief Convert a Residual Load Definition Type into a mere C-String + */ + static const char* ResidualLoadDefinitionTypeToCString(ResidualLoadDefinitionType t); + + /*! + ** \brief Convert a string into its corresponding Residual Load Definition Type + */ + static ResidualLoadDefinitionType StringToResidualLoadDefinitionType(const AnyString& text); + + //! \name Constructor & Destructor + //@{ + /*! + ** \brief Destructor + */ + ~MaintenanceGroup(); + //@} + + //! \name / ID + //@{ + /*! + ** \brief Get the name of the Maintenance Group + */ + const MaintenanceGroupName& name() const; // using here different string definition + /*! + ** \brief Set the name of the Maintenance Group + ** + ** The ID will be changed in the same time + */ + void name(const std::string& newname); // using here different string definition + + /*! + ** \brief Get the ID of the binding constraint + */ + const MaintenanceGroupName& id() const; + //@} + + /*! + ** \brief resets all to default data + */ + void resetToDefaultValues(); + + /*! + ** \brief returns if Maintenance Group is skipped for generating ts and if it is active + */ + bool skipped() const; + bool isActive() const; + + // used only for UI - maybe to added later + bool hasAllWeightedClustersOnLayer(size_t layerID); + + //! \name per Area + //@{ + /*! + ** \brief Get the load, renewable or ror weight of a given area + ** + ** \return The load, renewable or ror weight of the thermal area. 0. if not found + */ + double loadWeight(const Area* area) const; + double renewableWeight(const Area* area) const; + double rorWeight(const Area* area) const; + /*! + ** \brief Set the load, renewable or ror weight of a given area + */ + void loadWeight(const Area* area, double w); + void renewableWeight(const Area* area, double w); + void rorWeight(const Area* area, double w); - mapAreas associatedAreas; - mapThermalClusters associatedThermalClusters; + /*! + ** \brief Remove all weights for load, renewable and ror + */ + void removeAllWeights(); + + // used only in UI + /*! + ** \brief Copy all weights from another Maintenance Group + */ + void copyWeights(); + + /*! + ** \brief Get how many areas the Maintenance Group contains + */ + uint areaCount() const; + //@} + + //! \name Type of the Maintenance Group + //@{ + /*! + ** \brief Get the ResidualLoadDefinitionType of the Maintenance Group + */ + ResidualLoadDefinitionType type() const; + + /*! + ** \brief Set the ResidualLoadDefinitionType of the Maintenance Group + */ + void setResidualLoadDefinitionType(ResidualLoadDefinitionType t); + //@} + + //! \name Enabled / Disabled + //@{ + //! Get if the Maintenance Group is enabled + bool enabled() const; + //! Enabled / Disabled the Maintenance Group + void enabled(bool v); + //@} + + //! \name Reset // this is only used in UI and for BC in Kirchhoff generator, so we do not + //! really need it here + //@{ + /*! + ** \brief Clear all values and reset the Maintenance Group to its new type + ** + ** \param name Name of the Maintenance Group + ** \param newType Its new ResidualLoadDefinitionType + */ + void clearAndReset(const MaintenanceGroupName& name, ResidualLoadDefinitionType newType); + //@} + + //! \name Memory Usage + //@{ + /*! + ** \brief Get the memory usage + */ + uint64_t memoryUsage() const; + //@} + + /*! + ** \brief Get if the Maintenance Group contains a given area + */ + bool contains(const Area* area) const; private: - std::string name_; - std::string ID_; + //! Raw name + MaintenanceGroupName name_; + //! Raw ID + MaintenanceGroupName ID_; + + //! Weights for load, renewable and ror + weightMap loadWeights_; + weightMap renewableWeights_; + weightMap rorWeights_; + //! Type of the binding constraint + ResidualLoadDefinitionType type_ = typeWeights; + //! Enabled / Disabled + bool enabled_ = true; + void clear(); - bool enabled_; + void copyFrom(MaintenanceGroup const* original); +}; // class MaintenanceGroup + +// class MntGrpList +struct CompareMaintenanceGroupName final +{ + bool operator()(const std::shared_ptr& s1, + const std::shared_ptr& s2) const + { + return s1->name() < s2->name(); + } }; -} // namespace Antares::Data \ No newline at end of file +} // namespace Antares::Data + +#include "MaintenanceGroup.hxx" \ No newline at end of file diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroup.hxx b/src/libs/antares/study/maintenance_planning/MaintenanceGroup.hxx new file mode 100644 index 0000000000..f166c428c0 --- /dev/null +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroup.hxx @@ -0,0 +1,69 @@ +/* +** 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 +#include "MaintenanceGroup.h" + +namespace Antares::Data +{ +inline const MaintenanceGroup::MaintenanceGroupName& MaintenanceGroup::name() const +{ + return name_; +} + +inline const MaintenanceGroup::MaintenanceGroupName& MaintenanceGroup::id() const +{ + return ID_; +} + +inline uint MaintenanceGroup::areaCount() const +{ + return (uint)loadWeights_.size(); +} + +inline bool MaintenanceGroup::enabled() const +{ + return enabled_; +} + +inline MaintenanceGroup::ResidualLoadDefinitionType MaintenanceGroup::type() const +{ + return type_; +} + +inline bool MaintenanceGroup::skipped() const +{ + return areaCount() == 0; +} + +inline bool MaintenanceGroup::isActive() const +{ + return enabled() && !skipped(); +} + +} // namespace Antares::Data From 3abec8e7ffe0e2c2c50a4ad2e89ef1a3d01a5bba Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 1 Nov 2023 10:42:35 +0100 Subject: [PATCH 007/315] small refactor --- src/libs/antares/study/maintenance_planning/MaintenanceGroup.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroup.h b/src/libs/antares/study/maintenance_planning/MaintenanceGroup.h index ee747ddf7e..7efeafb140 100644 --- a/src/libs/antares/study/maintenance_planning/MaintenanceGroup.h +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroup.h @@ -215,13 +215,12 @@ class MaintenanceGroup : public Yuni::NonCopyable weightMap loadWeights_; weightMap renewableWeights_; weightMap rorWeights_; - //! Type of the binding constraint + //! Type of the Maintenance Group ResidualLoadDefinitionType type_ = typeWeights; //! Enabled / Disabled bool enabled_ = true; void clear(); - void copyFrom(MaintenanceGroup const* original); }; // class MaintenanceGroup From 3691358d4ad069dd6bbafa7bd7cdf088c622473d Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 1 Nov 2023 12:22:38 +0100 Subject: [PATCH 008/315] refactor MaintenanceGroup - put all three doubles into 1 struct --- .../maintenance_planning/MaintenanceGroup.cpp | 36 ++++++++----------- .../maintenance_planning/MaintenanceGroup.h | 13 ++++--- .../maintenance_planning/MaintenanceGroup.hxx | 2 +- 3 files changed, 24 insertions(+), 27 deletions(-) diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroup.cpp b/src/libs/antares/study/maintenance_planning/MaintenanceGroup.cpp index d49cabf4ef..e2992dac84 100644 --- a/src/libs/antares/study/maintenance_planning/MaintenanceGroup.cpp +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroup.cpp @@ -52,26 +52,24 @@ void MaintenanceGroup::name(const std::string& newName) void MaintenanceGroup::loadWeight(const Area* area, double w) { if (area) - loadWeights_[area] = w; + weights_[area].load = w; } void MaintenanceGroup::renewableWeight(const Area* area, double w) { if (area) - renewableWeights_[area] = w; + weights_[area].renewable = w; } void MaintenanceGroup::rorWeight(const Area* area, double w) { if (area) - rorWeights_[area] = w; + weights_[area].ror = w; } void MaintenanceGroup::removeAllWeights() { - loadWeights_.clear(); - renewableWeights_.clear(); - rorWeights_.clear(); + weights_.clear(); } void MaintenanceGroup::resetToDefaultValues() @@ -91,19 +89,15 @@ void MaintenanceGroup::clear() bool MaintenanceGroup::contains(const Area* area) const { - const auto i = loadWeights_.find(area); - return (i != loadWeights_.end()); + const auto i = weights_.find(area); + return (i != weights_.end()); } uint64_t MaintenanceGroup::memoryUsage() const { return sizeof(MaintenanceGroup) // Estimation - + loadWeights_.size() * (sizeof(double) + 3 * sizeof(void*)) - // Estimation - + renewableWeights_.size() * (sizeof(int) + 3 * sizeof(void*)) - // Estimation - + rorWeights_.size() * (sizeof(double) + 3 * sizeof(void*)); + + weights_.size() * (sizeof(double) * 3 + 3 * sizeof(void*) * 3); } void MaintenanceGroup::enabled(bool v) @@ -128,20 +122,20 @@ void MaintenanceGroup::copyWeights() double MaintenanceGroup::loadWeight(const Area* area) const { - auto i = loadWeights_.find(area); - return (i != loadWeights_.end()) ? i->second : 0.; + auto i = weights_.find(area); + return (i != weights_.end()) ? i->second.load : 0.; } double MaintenanceGroup::renewableWeight(const Area* area) const { - auto i = renewableWeights_.find(area); - return (i != renewableWeights_.end()) ? i->second : 0.; + auto i = weights_.find(area); + return (i != weights_.end()) ? i->second.renewable : 0.; } double MaintenanceGroup::rorWeight(const Area* area) const { - auto i = rorWeights_.find(area); - return (i != rorWeights_.end()) ? i->second : 0.; + auto i = weights_.find(area); + return (i != weights_.end()) ? i->second.ror : 0.; } void MaintenanceGroup::clearAndReset(const MaintenanceGroupName& name, @@ -160,9 +154,7 @@ void MaintenanceGroup::clearAndReset(const MaintenanceGroupName& name, void MaintenanceGroup::copyFrom(MaintenanceGroup const* original) { clearAndReset(original->name(), original->type()); - loadWeights_ = original->loadWeights_; - renewableWeights_ = original->renewableWeights_; - rorWeights_ = original->rorWeights_; + weights_ = original->weights_; enabled_ = original->enabled_; } diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroup.h b/src/libs/antares/study/maintenance_planning/MaintenanceGroup.h index 7efeafb140..d0a290a35a 100644 --- a/src/libs/antares/study/maintenance_planning/MaintenanceGroup.h +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroup.h @@ -68,9 +68,16 @@ class MaintenanceGroup : public Yuni::NonCopyable typeMax }; + struct Weights final + { + double load; + double renewable; + double ror; + }; + using MaintenanceGroupName = std::string; //! Map of load, renewable or ror weight-s - using weightMap = std::map; + using weightMap = std::map; /*! ** \brief Convert a Residual Load Definition Type into a mere C-String @@ -212,9 +219,7 @@ class MaintenanceGroup : public Yuni::NonCopyable MaintenanceGroupName ID_; //! Weights for load, renewable and ror - weightMap loadWeights_; - weightMap renewableWeights_; - weightMap rorWeights_; + weightMap weights_; //! Type of the Maintenance Group ResidualLoadDefinitionType type_ = typeWeights; //! Enabled / Disabled diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroup.hxx b/src/libs/antares/study/maintenance_planning/MaintenanceGroup.hxx index f166c428c0..6f89dd8161 100644 --- a/src/libs/antares/study/maintenance_planning/MaintenanceGroup.hxx +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroup.hxx @@ -43,7 +43,7 @@ inline const MaintenanceGroup::MaintenanceGroupName& MaintenanceGroup::id() cons inline uint MaintenanceGroup::areaCount() const { - return (uint)loadWeights_.size(); + return (uint)weights_.size(); } inline bool MaintenanceGroup::enabled() const From 5071147f124c81c349da819bf58530fcc33d3e30 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 1 Nov 2023 13:55:27 +0100 Subject: [PATCH 009/315] MaintenanceGroupSaver- structure --- src/libs/antares/study/CMakeLists.txt | 2 + .../maintenance_planning/MaintenanceGroup.h | 2 +- .../MaintenanceGroupSaver.cpp | 52 +++++++++++++++++++ .../MaintenanceGroupSaver.h | 35 +++++++++++++ 4 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 src/libs/antares/study/maintenance_planning/MaintenanceGroupSaver.cpp create mode 100644 src/libs/antares/study/maintenance_planning/MaintenanceGroupSaver.h diff --git a/src/libs/antares/study/CMakeLists.txt b/src/libs/antares/study/CMakeLists.txt index 238794baa0..ff61c6d024 100644 --- a/src/libs/antares/study/CMakeLists.txt +++ b/src/libs/antares/study/CMakeLists.txt @@ -184,6 +184,8 @@ set(SRC_STUDY_MAINTENANCE_PLANNING maintenance_planning/MaintenanceGroup.h maintenance_planning/MaintenanceGroup.hxx maintenance_planning/MaintenanceGroup.cpp + maintenance_planning/MaintenanceGroupSaver.h + maintenance_planning/MaintenanceGroupSaver.cpp ) source_group("study\\maintenance" FILES ${SRC_STUDY_MAINTENANCE_PLANNING}) diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroup.h b/src/libs/antares/study/maintenance_planning/MaintenanceGroup.h index d0a290a35a..6a079b21fc 100644 --- a/src/libs/antares/study/maintenance_planning/MaintenanceGroup.h +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroup.h @@ -53,7 +53,7 @@ struct CompareMaintenanceGroupName; class MaintenanceGroup : public Yuni::NonCopyable { // friend class MaintenanceGroupLoader; - // friend class MaintenanceGroupSaver; + friend class MaintenanceGroupSaver; public: enum ResidualLoadDefinitionType diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroupSaver.cpp b/src/libs/antares/study/maintenance_planning/MaintenanceGroupSaver.cpp new file mode 100644 index 0000000000..a29216d694 --- /dev/null +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroupSaver.cpp @@ -0,0 +1,52 @@ +// +// Created by milos on 1/11/23. +// +#include "MaintenanceGroupSaver.h" +#include "MaintenanceGroup.h" +#include +#include +#include "antares/study/area/area.h" +#include "antares/study/fwd.h" + +namespace Antares::Data +{ + +using namespace Yuni; +bool MaintenanceGroupSaver::saveToEnv(EnvForSaving& env, const MaintenanceGroup* maintenanceGroup) +{ + env.section->add("name", maintenanceGroup->name_); + env.section->add("id", maintenanceGroup->ID_); + env.section->add("enabled", maintenanceGroup->enabled_); + env.section->add( + "residual-load-definition", + MaintenanceGroup::ResidualLoadDefinitionTypeToCString(maintenanceGroup->type_)); + + if (!maintenanceGroup->weights_.empty()) + { + auto end = maintenanceGroup->weights_.end(); + for (auto i = maintenanceGroup->weights_.begin(); i != end; ++i) + { + // asserts + assert(i->first and "Invalid area"); + String value; + const Area& area = *(i->first); + + // add weight-load + env.key.clear() << area.name << '.weight-load'; + value << i->second.load; + env.section->add(env.key, value); + + // add weight-renewable + env.key.clear() << area.name << '.weight-renewable'; + value << i->second.renewable; + env.section->add(env.key, value); + + // add weight-ror + env.key.clear() << area.name << '.weight-ror'; + value << i->second.ror; + env.section->add(env.key, value); + } + } + return true; +} +} // namespace Antares::Data \ No newline at end of file diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroupSaver.h b/src/libs/antares/study/maintenance_planning/MaintenanceGroupSaver.h new file mode 100644 index 0000000000..5219367ca1 --- /dev/null +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroupSaver.h @@ -0,0 +1,35 @@ +// +// Created by milos on 1/11/23. +// + +#pragma once + +#include +#include "antares/study/fwd.h" +#include "MaintenanceGroup.h" + +namespace Antares::Data +{ +class MaintenanceGroupSaver +{ +public: + class EnvForSaving final + { + public: + EnvForSaving() = default; + + //! Current section + IniFile::Section* section = nullptr; + Yuni::Clob folder; + Yuni::CString<(ant_k_area_name_max_length + 15), false> key; + }; + + /*! + ** \brief Save the Maintenance Group into a folder and an INI file + ** + ** \param env All information needed to perform the task + ** \return True if the operation succeeded, false otherwise + */ + static bool saveToEnv(EnvForSaving& env, const MaintenanceGroup* maintenanceGroup); +}; +} // namespace Antares::Data \ No newline at end of file From 99b1da0a88c55407d9ce21d268bff0b191880db0 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 1 Nov 2023 16:55:32 +0100 Subject: [PATCH 010/315] refactor MaintenanceGroupSaver put all 3 weights in the the same line with % in between - like weight%offset for thermal cluster bc --- .../MaintenanceGroupSaver.cpp | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroupSaver.cpp b/src/libs/antares/study/maintenance_planning/MaintenanceGroupSaver.cpp index a29216d694..1cf1385b74 100644 --- a/src/libs/antares/study/maintenance_planning/MaintenanceGroupSaver.cpp +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroupSaver.cpp @@ -31,19 +31,9 @@ bool MaintenanceGroupSaver::saveToEnv(EnvForSaving& env, const MaintenanceGroup* String value; const Area& area = *(i->first); - // add weight-load - env.key.clear() << area.name << '.weight-load'; - value << i->second.load; - env.section->add(env.key, value); - - // add weight-renewable - env.key.clear() << area.name << '.weight-renewable'; - value << i->second.renewable; - env.section->add(env.key, value); - - // add weight-ror - env.key.clear() << area.name << '.weight-ror'; - value << i->second.ror; + // add weight-load+renewable+ror + env.key.clear() << area.name << '.weights'; + value << i->second.load << '%' << i->second.renewable << '%' << i->second.ror; env.section->add(env.key, value); } } From 8ee8e1107daf1b6626ee57a32f35aef24dea38d5 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 1 Nov 2023 17:34:41 +0100 Subject: [PATCH 011/315] MaintenanceGroupLoader- structure --- src/libs/antares/study/CMakeLists.txt | 2 + src/libs/antares/study/area/area.h | 5 + src/libs/antares/study/area/list.cpp | 12 ++ .../maintenance_planning/EnvForLoading.h | 31 ++++ .../maintenance_planning/MaintenanceGroup.h | 2 +- .../MaintenanceGroupLoader.cpp | 157 ++++++++++++++++++ .../MaintenanceGroupLoader.h | 29 ++++ 7 files changed, 237 insertions(+), 1 deletion(-) create mode 100644 src/libs/antares/study/maintenance_planning/EnvForLoading.h create mode 100644 src/libs/antares/study/maintenance_planning/MaintenanceGroupLoader.cpp create mode 100644 src/libs/antares/study/maintenance_planning/MaintenanceGroupLoader.h diff --git a/src/libs/antares/study/CMakeLists.txt b/src/libs/antares/study/CMakeLists.txt index ff61c6d024..cfe7ed9863 100644 --- a/src/libs/antares/study/CMakeLists.txt +++ b/src/libs/antares/study/CMakeLists.txt @@ -186,6 +186,8 @@ set(SRC_STUDY_MAINTENANCE_PLANNING maintenance_planning/MaintenanceGroup.cpp maintenance_planning/MaintenanceGroupSaver.h maintenance_planning/MaintenanceGroupSaver.cpp + maintenance_planning/MaintenanceGroupLoader.h + maintenance_planning/MaintenanceGroupLoader.cpp ) source_group("study\\maintenance" FILES ${SRC_STUDY_MAINTENANCE_PLANNING}) diff --git a/src/libs/antares/study/area/area.h b/src/libs/antares/study/area/area.h index 1a59fd5346..979201482b 100644 --- a/src/libs/antares/study/area/area.h +++ b/src/libs/antares/study/area/area.h @@ -627,6 +627,11 @@ class AreaList final : public Yuni::NonCopyable */ ThermalCluster* findClusterFromINIKey(const AnyString& key); + /*! + ** \brief Try to find the area from a given INI key (.'weights') + */ + Area* findAreaFromINIKey(const AnyString& key); + /*! ** \brief Get the total number of interconnections between all areas */ diff --git a/src/libs/antares/study/area/list.cpp b/src/libs/antares/study/area/list.cpp index d1532e34c8..e96ce5537a 100644 --- a/src/libs/antares/study/area/list.cpp +++ b/src/libs/antares/study/area/list.cpp @@ -1542,6 +1542,18 @@ ThermalCluster* AreaList::findClusterFromINIKey(const AnyString& key) return (i != nullptr) ? i : nullptr; } +Area* AreaList::findAreaFromINIKey(const AnyString& key) +{ + if (key.empty()) + return nullptr; + auto offset = key.find('.'); + if (offset == AreaName::npos || (0 == offset) || (offset == key.size() - 1)) + return nullptr; + AreaName parentName(key.c_str(), offset); + Area* parentArea = findFromName(parentName); + return (parentArea != nullptr) ? parentArea : nullptr; +} + void AreaList::updateNameIDSet() const { nameidSet.clear(); diff --git a/src/libs/antares/study/maintenance_planning/EnvForLoading.h b/src/libs/antares/study/maintenance_planning/EnvForLoading.h new file mode 100644 index 0000000000..e69b54495f --- /dev/null +++ b/src/libs/antares/study/maintenance_planning/EnvForLoading.h @@ -0,0 +1,31 @@ +// +// Created by milos on 1/11/23. +// + +#pragma once + +#include "yuni/core/fwd.h" +#include +#include + +namespace Antares::Data { + +class AreaList; +class EnvForLoading final +{ +public: + explicit EnvForLoading(AreaList& l, unsigned v) : areaList(l), version(v) + { + } + //! INI file + Yuni::Clob iniFilename; + //! Current section + IniFile::Section* section; + + //! List of areas + AreaList& areaList; + + unsigned version; +}; + +} // Data diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroup.h b/src/libs/antares/study/maintenance_planning/MaintenanceGroup.h index 6a079b21fc..84e3f23a74 100644 --- a/src/libs/antares/study/maintenance_planning/MaintenanceGroup.h +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroup.h @@ -52,7 +52,7 @@ namespace Antares::Data struct CompareMaintenanceGroupName; class MaintenanceGroup : public Yuni::NonCopyable { - // friend class MaintenanceGroupLoader; + friend class MaintenanceGroupLoader; friend class MaintenanceGroupSaver; public: diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroupLoader.cpp b/src/libs/antares/study/maintenance_planning/MaintenanceGroupLoader.cpp new file mode 100644 index 0000000000..05cb3170e8 --- /dev/null +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroupLoader.cpp @@ -0,0 +1,157 @@ +// +// Created by marechaljas on 11/05/23. +// + +#include "MaintenanceGroupLoader.h" +#include +#include +#include +#include +#include "MaintenanceGroup.h" +#include "yuni/core/string/string.h" +#include "antares/study/version.h" + +namespace Antares::Data +{ +using namespace Yuni; + +std::vector> MaintenanceGroupLoader::load(EnvForLoading env) +{ + auto mnt = std::make_shared(); + mnt->clear(); + + // Foreach property in the section... + for (const IniFile::Property* p = env.section->firstProperty; p; p = p->next) + { + if (p->key.empty()) + continue; + + if (p->key == "name") + { + mnt->name_ = p->value; + continue; + } + if (p->key == "id") + { + mnt->ID_ = toLower(p->value); + continue; + } + if (p->key == "enabled") + { + mnt->enabled_ = p->value.to(); + continue; + } + if (p->key == "residual-load-definition") + { + mnt->type_ = MaintenanceGroup::StringToResidualLoadDefinitionType(p->value); + continue; + } + + // initialize the values + MaintenanceGroup::Weights w = {0.0, 0.0, 0.0}; + + // Separate the key + auto setKey = p->key.find('.'); + if (0 == setKey || setKey == String::npos) + { + logs.error() << env.iniFilename << ": in [" << env.section->name << "]: `" << p->key + << "`: invalid key"; + continue; + } + + if (bool ret = SeparateValue(env, p, w); !ret) + continue; + + const Area* area = env.areaList.findAreaFromINIKey(p->key); + if (!area) + { + logs.error() << env.iniFilename << ": in [" << env.section->name << "]: `" << p->key + << "`: area not found"; + continue; + } + + mnt->loadWeight(area, w.load); + mnt->renewableWeight(area, w.renewable); + mnt->rorWeight(area, w.ror); + } + + // Checking for validity + if (!mnt->name_.empty()) + { + logs.error() << env.iniFilename << ": in [" << env.section->name + << "]: Invalid maintenance group name"; + return {}; + } + if (!mnt->ID_.empty()) + { + logs.error() << env.iniFilename << ": in [" << env.section->name + << "]: Invalid maintenance group id"; + return {}; + } + if (mnt->type_ == mnt->typeUnknown) + { + logs.error() << env.iniFilename << ": in [" << env.section->name + << "]: Invalid Residual Load Definition Type"; + return {}; + } + + return {mnt}; +} + +bool MaintenanceGroupLoader::SeparateValue(const EnvForLoading& env, + const IniFile::Property* p, + MaintenanceGroup::Weights& w) +{ + CString<64> string = p->value; + string.trim(); // trim + string.to(); + + // Split the string into parts based on '%' + std::vector parts; + std::istringstream ss(string); + std::string part; + while (std::getline(ss, part, '%')) + { + parts.push_back(part); + } + + // Check if there are exactly two parts + if (parts.size() != 3) + { + logs.error() << env.iniFilename << ": in [" << env.section->name << "]: `" << p->key + << "`: invalid number of weights"; + return false; + } + + // Convert each part to a double and report an error if conversion fails + double load, rnw, ror; + if (!(std::istringstream(parts[0]) >> load) || !(std::istringstream(parts[1]) >> rnw) + || !(std::istringstream(parts[2]) >> ror)) + { + logs.error() << env.iniFilename << ": in [" << env.section->name << "]: `" << p->key + << "`: one or more weights cannot be converted to numbers"; + return false; + } + + // Output the parsed numbers + w.load = load; + w.renewable = rnw; + w.ror = ror; + + return true; +} + +std::string MaintenanceGroupLoader::toLower(const std::string& str) +{ + std::string result = str; // Create a copy of the input string + + // Use std::transform to convert each character to lowercase + std::transform(result.begin(), + result.end(), + result.begin(), + [](unsigned char c) { return std::tolower(c); }); + + return result; +} + +} // namespace Antares::Data diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroupLoader.h b/src/libs/antares/study/maintenance_planning/MaintenanceGroupLoader.h new file mode 100644 index 0000000000..b0377173d5 --- /dev/null +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroupLoader.h @@ -0,0 +1,29 @@ +// +// Created by milos on 1/11/23. +// + +#pragma once + +#include +#include "antares/study/area/area.h" +#include "EnvForLoading.h" +#include "MaintenanceGroup.h" + +namespace Antares::Data +{ + +class MaintenanceGroup; +class MaintenanceGroupLoader +{ +public: + std::vector> load(EnvForLoading env); + +private: + static bool SeparateValue(const EnvForLoading& env, + const IniFile::Property* p, + MaintenanceGroup::Weights& w); + + std::string toLower(const std::string& str); +}; + +} // namespace Antares::Data From bee367f1f36941868be62de53fdcc0807fa0d0fd Mon Sep 17 00:00:00 2001 From: NikolaIlic Date: Wed, 1 Nov 2023 17:41:10 +0100 Subject: [PATCH 012/315] Loading function for class Study --- src/libs/antares/study/load.cpp | 8 ++++++++ src/libs/antares/study/study.h | 2 ++ 2 files changed, 10 insertions(+) diff --git a/src/libs/antares/study/load.cpp b/src/libs/antares/study/load.cpp index b93af9dcea..2242ad213c 100644 --- a/src/libs/antares/study/load.cpp +++ b/src/libs/antares/study/load.cpp @@ -205,6 +205,8 @@ bool Study::internalLoadFromFolder(const String& path, const StudyLoadOptions& o ret = internalLoadCorrelationMatrices(options) && ret; // Binding constraints ret = internalLoadBindingConstraints(options) && ret; + if(parameters.maintenancePlanning.isOptimized()) + ret = internalLoadMaintenanceGroup(options) && ret; // Sets of areas & links ret = internalLoadSets() && ret; @@ -268,6 +270,12 @@ bool Study::internalLoadBindingConstraints(const StudyLoadOptions& options) return (!r && options.loadOnlyNeeded) ? false : r; } +bool Study::internalLoadMaintenanceGroup(const StudyLoadOptions& options) +{ + // All checks should be performed in load functions + // +} + class SetHandlerAreas { public: diff --git a/src/libs/antares/study/study.h b/src/libs/antares/study/study.h index d52b587604..b30cdd306e 100644 --- a/src/libs/antares/study/study.h +++ b/src/libs/antares/study/study.h @@ -688,6 +688,8 @@ class Study: public Yuni::NonCopyable, public IObject, public LayerData bool internalLoadCorrelationMatrices(const StudyLoadOptions& options); //! Load all binding constraints virtual bool internalLoadBindingConstraints(const StudyLoadOptions& options); + //! Load all maintenance groups + virtual bool internalLoadMaintenanceGroup(const StudyLoadOptions& options); //! Load all set of areas and links bool internalLoadSets(); //@} From cc58bfd83b33074cc3cf1ce4fcc3c6e161897c2e Mon Sep 17 00:00:00 2001 From: NikolaIlic Date: Wed, 1 Nov 2023 18:19:31 +0100 Subject: [PATCH 013/315] Build error fix --- src/libs/antares/study/load.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libs/antares/study/load.cpp b/src/libs/antares/study/load.cpp index 2242ad213c..dce9ca1355 100644 --- a/src/libs/antares/study/load.cpp +++ b/src/libs/antares/study/load.cpp @@ -274,6 +274,7 @@ bool Study::internalLoadMaintenanceGroup(const StudyLoadOptions& options) { // All checks should be performed in load functions // + return true; } class SetHandlerAreas From ff2dca6641bd4b30ba361417d42292ab05e05f34 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 1 Nov 2023 18:25:22 +0100 Subject: [PATCH 014/315] fix comment --- .../study/maintenance_planning/MaintenanceGroupLoader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroupLoader.cpp b/src/libs/antares/study/maintenance_planning/MaintenanceGroupLoader.cpp index 05cb3170e8..8ff3e9f0e2 100644 --- a/src/libs/antares/study/maintenance_planning/MaintenanceGroupLoader.cpp +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroupLoader.cpp @@ -1,5 +1,5 @@ // -// Created by marechaljas on 11/05/23. +// Created by milos on 1/11/23. // #include "MaintenanceGroupLoader.h" From 24cd48dbd34df3e62fa2c632ab1e6770c394f028 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 1 Nov 2023 18:48:54 +0100 Subject: [PATCH 015/315] add CR27 to all TODO-a, to search them easier later --- .../antares/study/maintenance_planning/MaintenanceGroup.cpp | 4 ++-- src/libs/antares/study/parts/thermal/cluster.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroup.cpp b/src/libs/antares/study/maintenance_planning/MaintenanceGroup.cpp index e2992dac84..a8a236f61a 100644 --- a/src/libs/antares/study/maintenance_planning/MaintenanceGroup.cpp +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroup.cpp @@ -110,12 +110,12 @@ void MaintenanceGroup::setResidualLoadDefinitionType(MaintenanceGroup::ResidualL type_ = t; } -// TODO: not implemented for now - used only for UI - maybe to added later +// TODO CR27: not implemented for now - used only for UI - maybe to added later bool MaintenanceGroup::hasAllWeightedClustersOnLayer(size_t layerID) { return true; } -// TODO: not implemented for now - used only for UI - maybe to added later +// TODO CR27: not implemented for now - used only for UI - maybe to added later void MaintenanceGroup::copyWeights() { } diff --git a/src/libs/antares/study/parts/thermal/cluster.h b/src/libs/antares/study/parts/thermal/cluster.h index 5a37dee030..8bfa1661cf 100644 --- a/src/libs/antares/study/parts/thermal/cluster.h +++ b/src/libs/antares/study/parts/thermal/cluster.h @@ -302,8 +302,8 @@ class ThermalCluster final : public Cluster, public std::enable_shared_from_this int interPoPeriod = 365; //! PO windows (+/- days) int poWindows = 0; - // TODO: keep this here for now - // TODO: maybe create something like PreproThermal for Maintenance - and move everything there!!! + // TODO CR27: keep this here for now + // maybe create something like PreproThermal for Maintenance - and move everything there!!! // days since last maintenance - random int number between 0-interPoPeriod // defined per each unit of the cluster std::vector daysSinceLastMaintenance; From c1b84f31085091d8cc9e4acede0bffd1fc479266 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 1 Nov 2023 21:19:36 +0100 Subject: [PATCH 016/315] we are going to need folder name in load env --- src/libs/antares/study/maintenance_planning/EnvForLoading.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libs/antares/study/maintenance_planning/EnvForLoading.h b/src/libs/antares/study/maintenance_planning/EnvForLoading.h index e69b54495f..7f01ae7fb6 100644 --- a/src/libs/antares/study/maintenance_planning/EnvForLoading.h +++ b/src/libs/antares/study/maintenance_planning/EnvForLoading.h @@ -21,6 +21,8 @@ class EnvForLoading final Yuni::Clob iniFilename; //! Current section IniFile::Section* section; + // folder + Yuni::Clob folder; //! List of areas AreaList& areaList; From bca4912f2eccc578186b7447b704684009345a82 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 1 Nov 2023 21:20:53 +0100 Subject: [PATCH 017/315] we need method - contains(mnt) - generics + functor --- .../antares/study/maintenance_planning/MaintenanceGroup.cpp | 5 +++++ .../antares/study/maintenance_planning/MaintenanceGroup.h | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroup.cpp b/src/libs/antares/study/maintenance_planning/MaintenanceGroup.cpp index a8a236f61a..c155188fc4 100644 --- a/src/libs/antares/study/maintenance_planning/MaintenanceGroup.cpp +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroup.cpp @@ -87,6 +87,11 @@ void MaintenanceGroup::clear() this->enabled_ = true; } +bool MaintenanceGroup::contains(const MaintenanceGroup* mnt) const +{ + return (this == mnt); +} + bool MaintenanceGroup::contains(const Area* area) const { const auto i = weights_.find(area); diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroup.h b/src/libs/antares/study/maintenance_planning/MaintenanceGroup.h index 84e3f23a74..f85e05e988 100644 --- a/src/libs/antares/study/maintenance_planning/MaintenanceGroup.h +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroup.h @@ -211,6 +211,11 @@ class MaintenanceGroup : public Yuni::NonCopyable */ bool contains(const Area* area) const; + /*! + ** \brief Get if the given Maintenance Group is identical + */ + bool contains(const MaintenanceGroup* mnt) const; + private: //! Raw name From 0b78ea057a5d77e3a09a89d81bbbfd4be3c4f2eb Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 1 Nov 2023 21:48:16 +0100 Subject: [PATCH 018/315] re-use LoadEnv from BC --- .../maintenance_planning/EnvForLoading.h | 33 ------------------- 1 file changed, 33 deletions(-) delete mode 100644 src/libs/antares/study/maintenance_planning/EnvForLoading.h diff --git a/src/libs/antares/study/maintenance_planning/EnvForLoading.h b/src/libs/antares/study/maintenance_planning/EnvForLoading.h deleted file mode 100644 index 7f01ae7fb6..0000000000 --- a/src/libs/antares/study/maintenance_planning/EnvForLoading.h +++ /dev/null @@ -1,33 +0,0 @@ -// -// Created by milos on 1/11/23. -// - -#pragma once - -#include "yuni/core/fwd.h" -#include -#include - -namespace Antares::Data { - -class AreaList; -class EnvForLoading final -{ -public: - explicit EnvForLoading(AreaList& l, unsigned v) : areaList(l), version(v) - { - } - //! INI file - Yuni::Clob iniFilename; - //! Current section - IniFile::Section* section; - // folder - Yuni::Clob folder; - - //! List of areas - AreaList& areaList; - - unsigned version; -}; - -} // Data From 553f00a6acc5307b9fee58a1914f12df2e3187c2 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 1 Nov 2023 21:49:54 +0100 Subject: [PATCH 019/315] re-use LoadEnv from BC - #include --- .../antares/study/maintenance_planning/MaintenanceGroup.h | 6 +++--- .../study/maintenance_planning/MaintenanceGroupLoader.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroup.h b/src/libs/antares/study/maintenance_planning/MaintenanceGroup.h index f85e05e988..f552430568 100644 --- a/src/libs/antares/study/maintenance_planning/MaintenanceGroup.h +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroup.h @@ -30,9 +30,9 @@ #include #include #include "../fwd.h" -#include "../../constants.h" - -#include "../parts/thermal/cluster.h" +//#include "../../constants.h" +#include "../binding_constraint/EnvForLoading.h" +//#include "../parts/thermal/cluster.h" #include #include diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroupLoader.h b/src/libs/antares/study/maintenance_planning/MaintenanceGroupLoader.h index b0377173d5..12b0f0455b 100644 --- a/src/libs/antares/study/maintenance_planning/MaintenanceGroupLoader.h +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroupLoader.h @@ -6,7 +6,7 @@ #include #include "antares/study/area/area.h" -#include "EnvForLoading.h" +#include "../binding_constraint/EnvForLoading.h" #include "MaintenanceGroup.h" namespace Antares::Data From b0ab0445d6a8df928cb0cab70b4aab97623c2e2b Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 1 Nov 2023 21:50:58 +0100 Subject: [PATCH 020/315] MaintenanceGroupRepository- structure --- src/libs/antares/study/CMakeLists.txt | 3 + .../MaintenanceGroupRepository.cpp | 319 ++++++++++++++++++ .../MaintenanceGroupRepository.h | 165 +++++++++ .../MaintenanceGroupRepository.hxx | 38 +++ 4 files changed, 525 insertions(+) create mode 100644 src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.cpp create mode 100644 src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.h create mode 100644 src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.hxx diff --git a/src/libs/antares/study/CMakeLists.txt b/src/libs/antares/study/CMakeLists.txt index cfe7ed9863..dfc339b467 100644 --- a/src/libs/antares/study/CMakeLists.txt +++ b/src/libs/antares/study/CMakeLists.txt @@ -188,6 +188,9 @@ set(SRC_STUDY_MAINTENANCE_PLANNING maintenance_planning/MaintenanceGroupSaver.cpp maintenance_planning/MaintenanceGroupLoader.h maintenance_planning/MaintenanceGroupLoader.cpp + maintenance_planning/MaintenanceGroupRepository.h + maintenance_planning/MaintenanceGroupRepository.cpp + maintenance_planning/MaintenanceGroupRepository.hxx ) source_group("study\\maintenance" FILES ${SRC_STUDY_MAINTENANCE_PLANNING}) diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.cpp b/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.cpp new file mode 100644 index 0000000000..78e7f0775e --- /dev/null +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.cpp @@ -0,0 +1,319 @@ +// +// Created by milos on 1/11/23. +// + +#include "MaintenanceGroupRepository.h" +#include +#include +#include +#include +#include "MaintenanceGroup.h" +#include +#include "MaintenanceGroupLoader.h" +#include "MaintenanceGroupSaver.h" + +void Data::MaintenanceGroupRepository::clear() +{ + maintenanceGroups_.clear(); + activeMaintenanceGroups_.reset(); +} + +namespace Antares::Data +{ +std::shared_ptr MaintenanceGroupRepository::find(const AnyString& id) +{ + for (auto const& i : maintenanceGroups_) + { + if (i->id() == id) + return i; + } + return nullptr; +} + +std::shared_ptr MaintenanceGroupRepository::find( + const AnyString& id) const +{ + for (const auto& i : maintenanceGroups_) + { + if (i->id() == id) + return i; + } + return nullptr; +} + +MaintenanceGroup* MaintenanceGroupRepository::findByName(const AnyString& name) +{ + for (auto const& i : maintenanceGroups_) + { + if (i->name() == name) + return i.get(); + } + return nullptr; +} + +const MaintenanceGroup* MaintenanceGroupRepository::findByName(const AnyString& name) const +{ + for (const auto& i : maintenanceGroups_) + { + if (i->name() == name) + return i.get(); + } + return nullptr; +} + +void MaintenanceGroupRepository::removeMaintenanceGroupsWhoseNameConstains(const AnyString& filter) +{ + NameContainsMnt pred(filter); // vidi zasto ne hvat dobru strukturu + maintenanceGroups_.erase( + std::remove_if(maintenanceGroups_.begin(), maintenanceGroups_.end(), pred), + maintenanceGroups_.end()); +} + +bool compareMaintenanceGroups(const std::shared_ptr& s1, + const std::shared_ptr& s2) +{ + if (s1->name() != s2->name()) + { + return s1->name() < s2->name(); + } + else + { + return s1->type() < s2->type(); + } +} + +std::shared_ptr MaintenanceGroupRepository::add(const AnyString& name) +{ + auto mnt = std::make_shared(); + mnt->name(name); + maintenanceGroups_.push_back(mnt); + std::sort(maintenanceGroups_.begin(), maintenanceGroups_.end(), compareMaintenanceGroups); + return mnt; +} + +std::vector> MaintenanceGroupRepository::LoadMaintenanceGroup( + EnvForLoading env) +{ + MaintenanceGroupLoader loader; + return loader.load(std::move(env)); +} + +bool MaintenanceGroupRepository::saveToFolder(const AnyString& folder) const +{ + MaintenanceGroupSaver::EnvForSaving env; + env.folder = folder; + return internalSaveToFolder(env); +} + +bool MaintenanceGroupRepository::rename(MaintenanceGroup* mnt, const AnyString& newname) +{ + // Copy of the name + MaintenanceGroup::MaintenanceGroupName name; + name = newname; + if (name == mnt->name()) + return true; + MaintenanceGroup::MaintenanceGroupName id; + Antares::TransformNameIntoID(name, id); + if (std::any_of(maintenanceGroups_.begin(), + maintenanceGroups_.end(), + [&id](auto mntGroup) { return mntGroup->id() == id; })) + { + return false; + } + mnt->name(name); + return true; +} + +bool MaintenanceGroupRepository::loadFromFolder(Study& study, + const StudyLoadOptions& options, + const AnyString& folder) +{ + // Log entries + logs.info(); // space for beauty + logs.info() << "Loading maintenance groups..."; + + // Cleaning + clear(); + + if (study.usedByTheSolver) + { + if (!study.parameters.maintenancePlanning.mpModelling != mpOptimized) + { + logs.info() + << " The maintenance groups shall be ignored due to the advanced parameters"; + return true; + } + } + + EnvForLoading env(study.areas, study.header.version); + env.folder = folder; + + env.iniFilename << env.folder << Yuni::IO::Separator << "maintenancegroups.ini"; + IniFile ini; + if (!ini.open(env.iniFilename)) + { + return false; + } + + // For each section + if (ini.firstSection) + { + for (env.section = ini.firstSection; env.section; env.section = env.section->next) + { + if (env.section->firstProperty) + { + auto new_mnt = LoadMaintenanceGroup(env); + std::copy(new_mnt.begin(), new_mnt.end(), std::back_inserter(maintenanceGroups_)); + } + } + } + + // Logs + if (maintenanceGroups_.empty()) + logs.info() << "No maintenance group found"; + else + { + std::sort(maintenanceGroups_.begin(), maintenanceGroups_.end(), compareMaintenanceGroups); + + if (maintenanceGroups_.size() == 1) + logs.info() << "1 maintenance group found"; + else + logs.info() << maintenanceGroups_.size() << " maintenance groups found"; + } + + return true; +} + +bool MaintenanceGroupRepository::internalSaveToFolder( + MaintenanceGroupSaver::EnvForSaving& env) const +{ + if (maintenanceGroups_.empty()) + { + logs.info() << "No maintenance group to export."; + if (!Yuni::IO::Directory::Create(env.folder)) + return false; + // stripping the file + env.folder << Yuni::IO::Separator << "maintenancegroups.ini"; + return Yuni::IO::File::CreateEmptyFile(env.folder); + } + + if (maintenanceGroups_.size() == 1) + logs.info() << "Exporting 1 maintenance group..."; + else + logs.info() << "Exporting " << maintenanceGroups_.size() << " maintenance groups..."; + + if (!Yuni::IO::Directory::Create(env.folder)) + return false; + + IniFile ini; + bool ret = true; + uint index = 0; + auto end = maintenanceGroups_.end(); + Yuni::ShortString64 text; + + for (auto i = maintenanceGroups_.begin(); i != end; ++i, ++index) + { + text = index; + env.section = ini.addSection(text); + ret = Antares::Data::MaintenanceGroupSaver::saveToEnv(env, i->get()) && ret; + } + + env.folder << Yuni::IO::Separator << "maintenancegroups.ini"; + return ini.save(env.folder) && ret; +} + +void MaintenanceGroupRepository::reverseWeightSign(const AreaLink* lnk) +{ +} + +uint64_t MaintenanceGroupRepository::memoryUsage() const +{ + uint64_t m = sizeof(MaintenanceGroupRepository); + for (const auto& i : maintenanceGroups_) + m += i->memoryUsage(); + return m; +} + +namespace // anonymous +{ +template +class RemovePredicate final +{ +public: + explicit RemovePredicate(const T* u) : pItem(u) + { + } + + bool operator()(const std::shared_ptr& mnt) const + { + assert(mnt); + if (mnt->contains(pItem)) + { + logs.info() << "destroying the maintenance group " << mnt->name(); + return true; + } + return false; + } + +private: + const T* pItem; +}; + +} // anonymous namespace + +void MaintenanceGroupRepository::remove(const Area* area) +{ + RemovePredicate predicate(area); + auto e = std::remove_if(maintenanceGroups_.begin(), maintenanceGroups_.end(), predicate); + maintenanceGroups_.erase(e, maintenanceGroups_.end()); + activeMaintenanceGroups_.reset(); +} + +void MaintenanceGroupRepository::remove(const MaintenanceGroup* mnt) +{ + RemovePredicate predicate(mnt); + auto e = std::remove_if(maintenanceGroups_.begin(), maintenanceGroups_.end(), predicate); + maintenanceGroups_.erase(e, maintenanceGroups_.end()); + activeMaintenanceGroups_.reset(); +} + +MaintenanceGroupRepository::iterator MaintenanceGroupRepository::begin() +{ + return maintenanceGroups_.begin(); +} + +MaintenanceGroupRepository::const_iterator MaintenanceGroupRepository::begin() const +{ + return maintenanceGroups_.begin(); +} + +MaintenanceGroupRepository::iterator MaintenanceGroupRepository::end() +{ + return maintenanceGroups_.end(); +} + +MaintenanceGroupRepository::const_iterator MaintenanceGroupRepository::end() const +{ + return maintenanceGroups_.end(); +} + +std::vector> MaintenanceGroupRepository::activeMaintenanceGroups() + const +{ + if (activeMaintenanceGroups_) + { + return activeMaintenanceGroups_.value(); + } + else + { + std::vector> out; + std::copy_if(maintenanceGroups_.begin(), + maintenanceGroups_.end(), + std::back_inserter(out), + [](const auto& mnt) { return mnt->isActive(); }); + activeMaintenanceGroups_ = std::move(out); + return activeMaintenanceGroups_.value(); + } +} + +} // namespace Antares::Data diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.h b/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.h new file mode 100644 index 0000000000..5f67f5fa97 --- /dev/null +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.h @@ -0,0 +1,165 @@ +// +// Created by milos on 1/11/23. +// + +#pragma once + +#include +#include +#include "MaintenanceGroup.h" +#include "MaintenanceGroupSaver.h" + +namespace Antares::Data +{ +class MaintenanceGroupRepository final : public Yuni::NonCopyable +{ +public: + //! Vector of Maintenance Group-s + using Vector = std::vector>; + //! Ordered Set of Maintenance Group-s + using Set = std::set, CompareMaintenanceGroupName>; + + using iterator = Vector::iterator; + using const_iterator = Vector::const_iterator; + + //! \name Constructor && Destructor + //@{ + /*! + ** \brief Default constructor + */ + MaintenanceGroupRepository() = default; + /*! + ** \brief Destructor + */ + ~MaintenanceGroupRepository() = default; + //@} + + /*! + ** \brief Delete all Maintenance Group-s + */ + void clear(); + + //! \name Iterating through all Maintenance Group-s + //@{ + /*! + ** \brief Iterate through all Maintenance Group-s + */ + template + void each(const PredicateT& predicate); + /*! + ** \brief Iterate through all Maintenance Group-s (const) + */ + template + void each(const PredicateT& predicate) const; + + iterator begin(); + [[nodiscard]] const_iterator begin() const; + + iterator end(); + [[nodiscard]] const_iterator end() const; + + [[nodiscard]] bool empty() const; + //@} + + /*! + ** \brief Add a new Maintenance Group + */ + std::shared_ptr add(const AnyString& name); + + /*! + ** Try to find a Maintenance Group from its id + */ + std::shared_ptr find(const AnyString& id); + + /*! + ** \brief Try to find a Maintenance Group from its id (const) + */ + [[nodiscard]] std::shared_ptr find(const AnyString& id) const; + + /*! + ** \brief Try to find a Maintenance Group from its name + */ + [[nodiscard]] Data::MaintenanceGroup* findByName(const AnyString& name); + + /*! + ** \brief Try to find a Maintenance Group from its name (const) + */ + [[nodiscard]] const Data::MaintenanceGroup* findByName(const AnyString& name) const; + + /*! + ** \brief Load all Maintenance Group from a folder + */ + [[nodiscard]] bool loadFromFolder(Data::Study& s, + const Data::StudyLoadOptions& options, + const AnyString& folder); + + /*! + ** \brief Save all Maintenance Group into a folder + */ + [[nodiscard]] bool saveToFolder(const AnyString& folder) const; + + // TODO CR27: do we need this at all + /*! + ** \brief Reverse the sign of the weight for a given Maintenance Group + ** + ** This method is used when reverting an Maintenance Group + */ + void reverseWeightSign(const Data::AreaLink* lnk); + + //! Get the number of Maintenance Group + [[nodiscard]] uint size() const; + + /*! + ** \brief Remove a Maintenance Group + */ + void remove(const Data::MaintenanceGroup* bc); + /*! + ** \brief Remove any Maintenance Group linked with a given area + */ + void remove(const Data::Area* area); + + /*! + ** \brief Remove any Maintenance Group whose name contains the string in argument + */ + void removeMaintenanceGroupsWhoseNameConstains(const AnyString& filter); + + /*! + ** \brief Rename a Maintenance Group + */ + bool rename(Data::MaintenanceGroup* bc, const AnyString& newname); + + /*! + ** \brief Get the memory usage + */ + [[nodiscard]] uint64_t memoryUsage() const; + + static std::vector> LoadMaintenanceGroup(EnvForLoading env); + + [[nodiscard]] std::vector> activeMaintenanceGroups() const; + +private: + bool internalSaveToFolder(Data::MaintenanceGroupSaver::EnvForSaving& env) const; + + //! All Maintenance Group-s + Data::MaintenanceGroupRepository::Vector maintenanceGroups_; + + mutable std::optional>> activeMaintenanceGroups_; +}; + +struct NameContainsMnt final +{ +public: + explicit NameContainsMnt(AnyString filter) : pFilter(std::move(filter)) + { + } + bool operator()(const std::shared_ptr& s) const + { + return ((s->name()).find(pFilter) != std::string::npos); + } + +private: + AnyString pFilter; +}; +} // namespace Antares::Data + +#include "MaintenanceGroupRepository.hxx" \ No newline at end of file diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.hxx b/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.hxx new file mode 100644 index 0000000000..6f4a384967 --- /dev/null +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.hxx @@ -0,0 +1,38 @@ +// +// Created by milos on 1/11/23. +// + +#pragma once + +#include +#include + +namespace Antares::Data +{ + +inline uint MaintenanceGroupRepository::size() const +{ + return (uint)maintenanceGroups_.size(); +} + +inline bool MaintenanceGroupRepository::empty() const +{ + return maintenanceGroups_.empty(); +} + +template +inline void MaintenanceGroupRepository::each(const PredicateT& predicate) +{ + uint count = (uint)maintenanceGroups_.size(); + for (uint i = 0; i != count; ++i) + predicate(*(maintenanceGroups_[i])); +} + +template +inline void MaintenanceGroupRepository::each(const PredicateT& predicate) const +{ + uint count = (uint)maintenanceGroups_.size(); + for (uint i = 0; i != count; ++i) + predicate(*(maintenanceGroups_[i].get())); +} +} // namespace Antares::Data From 5f78269800a93a62c574bf3799c5a7956920d6f5 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 1 Nov 2023 22:06:48 +0100 Subject: [PATCH 021/315] TODOs phase I & II --- .../MaintenanceGroupLoader.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroupLoader.h b/src/libs/antares/study/maintenance_planning/MaintenanceGroupLoader.h index 12b0f0455b..b7a2e2276b 100644 --- a/src/libs/antares/study/maintenance_planning/MaintenanceGroupLoader.h +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroupLoader.h @@ -27,3 +27,19 @@ class MaintenanceGroupLoader }; } // namespace Antares::Data + + +/* +TODO CR27: + for I phase: + * load Maintenance Group only if version > 870 - client wont be able to open old models + for II phase: + * check if same area is inside more than 1 Maintenance Group - and throw error + * what happens when area name is changed - UI code + * we need to change the name in INI file in Maintenance Group + * what happens if the area is deleted - UI code + * we need to remove that area from all Maintenance Group-s + + +*/ + From 759a2589b4dfd1e88b34e78e07d396b6e19f0678 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 1 Nov 2023 22:25:55 +0100 Subject: [PATCH 022/315] clean --- .../study/maintenance_planning/MaintenanceGroupRepository.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.cpp b/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.cpp index 78e7f0775e..27a258ce5a 100644 --- a/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.cpp +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.cpp @@ -63,7 +63,7 @@ const MaintenanceGroup* MaintenanceGroupRepository::findByName(const AnyString& void MaintenanceGroupRepository::removeMaintenanceGroupsWhoseNameConstains(const AnyString& filter) { - NameContainsMnt pred(filter); // vidi zasto ne hvat dobru strukturu + NameContainsMnt pred(filter); maintenanceGroups_.erase( std::remove_if(maintenanceGroups_.begin(), maintenanceGroups_.end(), pred), maintenanceGroups_.end()); From 19f11b375084899b7ebac63a42b2af315d95a295 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Thu, 2 Nov 2023 11:26:57 +0100 Subject: [PATCH 023/315] do not load ini file if version < 870 --- .../study/maintenance_planning/MaintenanceGroupRepository.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.cpp b/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.cpp index 27a258ce5a..20f2e2cb9d 100644 --- a/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.cpp +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.cpp @@ -128,6 +128,10 @@ bool MaintenanceGroupRepository::loadFromFolder(Study& study, const StudyLoadOptions& options, const AnyString& folder) { + // do not load if below 870 + if (study.header.version < 870) + return true; + // Log entries logs.info(); // space for beauty logs.info() << "Loading maintenance groups..."; From f6a75012d8cdb73435fb7ecbd58db31844092c96 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Thu, 2 Nov 2023 11:29:22 +0100 Subject: [PATCH 024/315] clean --- src/libs/antares/study/maintenance_planning/MaintenanceGroup.h | 3 --- .../study/maintenance_planning/MaintenanceGroupLoader.h | 2 -- 2 files changed, 5 deletions(-) diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroup.h b/src/libs/antares/study/maintenance_planning/MaintenanceGroup.h index f552430568..2ff70812b0 100644 --- a/src/libs/antares/study/maintenance_planning/MaintenanceGroup.h +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroup.h @@ -30,12 +30,9 @@ #include #include #include "../fwd.h" -//#include "../../constants.h" #include "../binding_constraint/EnvForLoading.h" -//#include "../parts/thermal/cluster.h" #include #include - #include "antares/study/filter.h" #include diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroupLoader.h b/src/libs/antares/study/maintenance_planning/MaintenanceGroupLoader.h index b7a2e2276b..0aa48c6d69 100644 --- a/src/libs/antares/study/maintenance_planning/MaintenanceGroupLoader.h +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroupLoader.h @@ -31,8 +31,6 @@ class MaintenanceGroupLoader /* TODO CR27: - for I phase: - * load Maintenance Group only if version > 870 - client wont be able to open old models for II phase: * check if same area is inside more than 1 Maintenance Group - and throw error * what happens when area name is changed - UI code From eca84b28ae31ed66ad2ec6e5eb43199069f58d7b Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Thu, 2 Nov 2023 12:09:53 +0100 Subject: [PATCH 025/315] check weights are in [0-1] range --- .../study/maintenance_planning/MaintenanceGroupLoader.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroupLoader.cpp b/src/libs/antares/study/maintenance_planning/MaintenanceGroupLoader.cpp index 8ff3e9f0e2..341df3da80 100644 --- a/src/libs/antares/study/maintenance_planning/MaintenanceGroupLoader.cpp +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroupLoader.cpp @@ -133,6 +133,14 @@ bool MaintenanceGroupLoader::SeparateValue(const EnvForLoading& env, return false; } + // check if parsed numbers are between 0 and 1.0 + if (!(load >= 0.0 && load <= 1.0 && rnw >= 0.0 && rnw <= 1.0 && ror >= 0.0 && ror <= 1.0)) + { + logs.error() << env.iniFilename << ": in [" << env.section->name << "]: `" << p->key + << "`: one or more weights are not in the [0, 1] range"; + return false; + } + // Output the parsed numbers w.load = load; w.renewable = rnw; From 4006529bd8dcf08c7fd5cb736d3fa03268299d9c Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Thu, 2 Nov 2023 13:05:48 +0100 Subject: [PATCH 026/315] call maintenanceGroups.saveToFolder --- src/libs/antares/study/save.cpp | 4 ++++ src/libs/antares/study/study.h | 9 +++++++++ 2 files changed, 13 insertions(+) diff --git a/src/libs/antares/study/save.cpp b/src/libs/antares/study/save.cpp index f8dea51ebd..52f6539d92 100644 --- a/src/libs/antares/study/save.cpp +++ b/src/libs/antares/study/save.cpp @@ -225,6 +225,10 @@ bool Study::saveToFolder(const AnyString& newfolder) buffer.clear() << folder << SEP << "input" << SEP << "bindingconstraints"; ret = bindingConstraints.saveToFolder(buffer) and ret; + // Maintenance Group-s + buffer.clear() << folder << SEP << "input" << SEP << "maintenanceplanning"; + ret = maintenanceGroups.saveToFolder(buffer) and ret; + // Correlation matrices logs.info() << "Exporting the correlation matrices"; diff --git a/src/libs/antares/study/study.h b/src/libs/antares/study/study.h index b30cdd306e..4b21074064 100644 --- a/src/libs/antares/study/study.h +++ b/src/libs/antares/study/study.h @@ -54,6 +54,9 @@ #include "antares/study/binding_constraint/BindingConstraintsRepository.h" #include "antares/study/binding_constraint/BindingConstraintGroupRepository.h" +#include "maintenance_planning/MaintenanceGroup.h" +#include "antares/study/maintenance_planning/MaintenanceGroupRepository.h" + #include namespace Antares::Data @@ -584,6 +587,12 @@ class Study: public Yuni::NonCopyable, public IObject, public LayerData BindingConstraintGroupRepository bindingConstraintsGroups; //@} + //! \name Maintenance Group-s + //@{ + //! Maintenance Group-s + MaintenanceGroupRepository maintenanceGroups; + //@} + //! \name Correlation matrices used by the prepro //@{ //! Correlation matrix for the load time series generated by the prepro From dea90831f30cfd46029d8eea3c0a630658b0c1a4 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Thu, 2 Nov 2023 13:09:08 +0100 Subject: [PATCH 027/315] call maintenance Group-s clear/remove/memoryUsage methods --- .../InfoCollection/StudyInfoCollector.cpp | 2 ++ src/libs/antares/study/runtime/runtime.cpp | 1 + src/libs/antares/study/study.cpp | 16 ++++++++++++++++ src/libs/antares/study/ui-runtimeinfos.cpp | 3 +++ 4 files changed, 22 insertions(+) diff --git a/src/libs/antares/InfoCollection/StudyInfoCollector.cpp b/src/libs/antares/InfoCollection/StudyInfoCollector.cpp index 05f9894f12..de9d2a21e3 100644 --- a/src/libs/antares/InfoCollection/StudyInfoCollector.cpp +++ b/src/libs/antares/InfoCollection/StudyInfoCollector.cpp @@ -72,6 +72,8 @@ void StudyInfoCollector::enabledThermalClustersCountToFileContent(FileContent& f file_content.addItemToSection("study", "enabled thermal clusters", nbEnabledThermalClusters); } +// TODO CR27: what id this, writing to some file, do we need this + void StudyInfoCollector::enabledBindingConstraintsCountToFileContent(FileContent& file_content) { auto activeContraints = study_.bindingConstraints.activeContraints(); diff --git a/src/libs/antares/study/runtime/runtime.cpp b/src/libs/antares/study/runtime/runtime.cpp index 0a8f349847..a1eadc340d 100644 --- a/src/libs/antares/study/runtime/runtime.cpp +++ b/src/libs/antares/study/runtime/runtime.cpp @@ -332,6 +332,7 @@ bool StudyRuntimeInfos::loadFromStudy(Study& study) logs.info() << " thermal clusters (must-run): " << thermalPlantTotalCountMustRun; logs.info() << " short-term storages: " << shortTermStorageCount; logs.info() << " binding constraints: " << study.bindingConstraints.activeContraints().size(); + logs.info() << " maintenance groups: " << study.maintenanceGroups.activeMaintenanceGroups().size(); logs.info() << " geographic trimming:" << (gd.geographicTrimming ? "true" : "false"); logs.info() << " memory : " << ((study.memoryUsage()) / 1024 / 1024) << "Mo"; logs.info(); diff --git a/src/libs/antares/study/study.cpp b/src/libs/antares/study/study.cpp index b81299781e..b450f4f6c9 100644 --- a/src/libs/antares/study/study.cpp +++ b/src/libs/antares/study/study.cpp @@ -124,6 +124,9 @@ void Study::clear() bindingConstraintsGroups.clear(); areas.clear(); + // maintenance Group-s + maintenanceGroups.clear(); + // no folder ClearAndShrink(header.caption); ClearAndShrink(header.author); @@ -164,6 +167,9 @@ void Study::createAsNew() // Binding constraints bindingConstraints.clear(); + // maintenance Group-s + maintenanceGroups.clear(); + // Areas areas.clear(); @@ -209,6 +215,8 @@ uint64_t Study::memoryUsage() const + areas.memoryUsage() // Binding constraints + bindingConstraints.memoryUsage() + // maintenance Group-s + + maintenanceGroups.memoryUsage() // Correlations matrices + preproLoadCorrelation.memoryUsage() + preproSolarCorrelation.memoryUsage() + preproHydroCorrelation.memoryUsage() + preproWindCorrelation.memoryUsage() @@ -847,6 +855,8 @@ bool Study::areaDelete(Area* area) // Remove a single area // Remove all binding constraints attached to the area bindingConstraints.remove(area); + // Remove all Maintenance Group-s attached to the area + maintenanceGroups.remove(area); // Delete the area from the list areas.remove(area->id); @@ -898,6 +908,8 @@ void Study::areaDelete(Area::Vector& arealist) // Remove all binding constraints attached to the area bindingConstraints.remove(*i); + // Remove all Maintenance Group-s attached to the area + maintenanceGroups.remove(*i); // Delete the area from the list areas.remove(area.id); } @@ -1139,6 +1151,8 @@ void Study::destroyAllThermalTSGeneratorData() }); } +// TODO CR27: see if we need this one for mant groups - only used in UI - so II phase + void Study::ensureDataAreLoadedForAllBindingConstraints() { for(const auto& constraint: bindingConstraints) @@ -1505,6 +1519,8 @@ bool Study::checkForFilenameLimits(bool output, const String& chfolder) const } } } + + // TODO CR27: we probably do need to check Maximum path length limitation for mnt groups } return true; } diff --git a/src/libs/antares/study/ui-runtimeinfos.cpp b/src/libs/antares/study/ui-runtimeinfos.cpp index 0ba362f828..b68b16486f 100644 --- a/src/libs/antares/study/ui-runtimeinfos.cpp +++ b/src/libs/antares/study/ui-runtimeinfos.cpp @@ -108,6 +108,9 @@ void UIRuntimeInfo::reload() } } +//TODO CR27: make reload maintenanceGroups? it is used mostly in UI, but also have couple of uses in solver + + void UIRuntimeInfo::reloadBindingConstraints() { orderedConstraint.clear(); From 82a0ca4dbee676f6f851b7d42d944cfdda7367cc Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Thu, 2 Nov 2023 13:15:35 +0100 Subject: [PATCH 028/315] enabledMaintenanceGroupCountToFileContent implement --- src/libs/antares/InfoCollection/StudyInfoCollector.cpp | 8 +++++++- .../include/antares/infoCollection/StudyInfoCollector.h | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/libs/antares/InfoCollection/StudyInfoCollector.cpp b/src/libs/antares/InfoCollection/StudyInfoCollector.cpp index de9d2a21e3..f005cd8d84 100644 --- a/src/libs/antares/InfoCollection/StudyInfoCollector.cpp +++ b/src/libs/antares/InfoCollection/StudyInfoCollector.cpp @@ -19,6 +19,7 @@ void StudyInfoCollector::toFileContent(FileContent& file_content) performedYearsCountToFileContent(file_content); enabledThermalClustersCountToFileContent(file_content); enabledBindingConstraintsCountToFileContent(file_content); + enabledMaintenanceGroupCountToFileContent(file_content); unitCommitmentModeToFileContent(file_content); maxNbYearsInParallelToFileContent(file_content); solverVersionToFileContent(file_content); @@ -72,7 +73,12 @@ void StudyInfoCollector::enabledThermalClustersCountToFileContent(FileContent& f file_content.addItemToSection("study", "enabled thermal clusters", nbEnabledThermalClusters); } -// TODO CR27: what id this, writing to some file, do we need this +void StudyInfoCollector::enabledMaintenanceGroupCountToFileContent(FileContent& file_content) +{ + auto activeMntGroups = study_.maintenanceGroups.activeMaintenanceGroups(); + auto nbEnabledMNT = activeMntGroups.size(); + file_content.addItemToSection("study", "enabled Maintenance Group-s", nbEnabledMNT); +} void StudyInfoCollector::enabledBindingConstraintsCountToFileContent(FileContent& file_content) { diff --git a/src/libs/antares/InfoCollection/include/antares/infoCollection/StudyInfoCollector.h b/src/libs/antares/InfoCollection/include/antares/infoCollection/StudyInfoCollector.h index bb3b1f1df8..13137ffb95 100644 --- a/src/libs/antares/InfoCollection/include/antares/infoCollection/StudyInfoCollector.h +++ b/src/libs/antares/InfoCollection/include/antares/infoCollection/StudyInfoCollector.h @@ -24,6 +24,7 @@ class StudyInfoCollector void performedYearsCountToFileContent(FileContent& file_content); void enabledThermalClustersCountToFileContent(FileContent& file_content); void enabledBindingConstraintsCountToFileContent(FileContent& file_content); + void enabledMaintenanceGroupCountToFileContent(FileContent& file_content); void unitCommitmentModeToFileContent(FileContent& file_content); void maxNbYearsInParallelToFileContent(FileContent& file_content); void solverVersionToFileContent(FileContent& file_content); From 8e73c010a004dfa9cbf16fe7bf43b07da145f700 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Thu, 2 Nov 2023 13:31:06 +0100 Subject: [PATCH 029/315] check length limitation in study --- src/libs/antares/study/study.cpp | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/libs/antares/study/study.cpp b/src/libs/antares/study/study.cpp index b450f4f6c9..fc4acaf1ad 100644 --- a/src/libs/antares/study/study.cpp +++ b/src/libs/antares/study/study.cpp @@ -1520,7 +1520,29 @@ bool Study::checkForFilenameLimits(bool output, const String& chfolder) const } } - // TODO CR27: we probably do need to check Maximum path length limitation for mnt groups + if (not maintenanceGroups.empty()) + { + auto end = maintenanceGroups.end(); + for (auto i = maintenanceGroups.begin(); i != end; ++i) + { + // The current constraint + auto& mntGroup = *(*i); + + filename.clear(); + filename << studyfolder << "input" << SEP << "maintenanceplanning" << SEP; + filename << mntGroup.id() << ".ini"; + + if (filename.size() >= limit) + { + logs.error() + << "OS Maximum path length limitation obtained with the maintenance group '" + << mntGroup.name() << "' (got " << filename.size() << " characters)"; + logs.error() << "You may experience problems while accessing to this file: " + << filename; + return false; + } + } + } } return true; } From 51c2d4e3aa42a6ca298c05806c3d5dd97ad871d1 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Thu, 2 Nov 2023 13:36:06 +0100 Subject: [PATCH 030/315] update todo comment - reloadMntGrp - for II phase --- src/libs/antares/study/ui-runtimeinfos.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/antares/study/ui-runtimeinfos.cpp b/src/libs/antares/study/ui-runtimeinfos.cpp index b68b16486f..8d0f50b97f 100644 --- a/src/libs/antares/study/ui-runtimeinfos.cpp +++ b/src/libs/antares/study/ui-runtimeinfos.cpp @@ -108,7 +108,7 @@ void UIRuntimeInfo::reload() } } -//TODO CR27: make reload maintenanceGroups? it is used mostly in UI, but also have couple of uses in solver +//TODO CR27: make reload maintenanceGroups? it is used mostly in UI, but also have couple of uses in solver - leave it for II phase void UIRuntimeInfo::reloadBindingConstraints() From aa1303738f3c33df605f4c16bb1e494d16ed8b3b Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Thu, 2 Nov 2023 14:16:09 +0100 Subject: [PATCH 031/315] load MaintenanceGroupRepository --- src/libs/antares/study/load.cpp | 11 ++++++----- .../MaintenanceGroupRepository.cpp | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/libs/antares/study/load.cpp b/src/libs/antares/study/load.cpp index dce9ca1355..c35e3ffaef 100644 --- a/src/libs/antares/study/load.cpp +++ b/src/libs/antares/study/load.cpp @@ -205,8 +205,8 @@ bool Study::internalLoadFromFolder(const String& path, const StudyLoadOptions& o ret = internalLoadCorrelationMatrices(options) && ret; // Binding constraints ret = internalLoadBindingConstraints(options) && ret; - if(parameters.maintenancePlanning.isOptimized()) - ret = internalLoadMaintenanceGroup(options) && ret; + // Maintenance Group-s + ret = internalLoadMaintenanceGroup(options) && ret; // Sets of areas & links ret = internalLoadSets() && ret; @@ -272,9 +272,10 @@ bool Study::internalLoadBindingConstraints(const StudyLoadOptions& options) bool Study::internalLoadMaintenanceGroup(const StudyLoadOptions& options) { - // All checks should be performed in load functions - // - return true; + // All checks are performed in 'loadFromFolder' + buffer.clear() << folderInput << SEP << "maintenanceplanning"; + bool r = maintenanceGroups.loadFromFolder(*this, options, buffer); + return (!r && options.loadOnlyNeeded) ? false : r; } class SetHandlerAreas diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.cpp b/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.cpp index 20f2e2cb9d..fb281918a9 100644 --- a/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.cpp +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.cpp @@ -141,7 +141,7 @@ bool MaintenanceGroupRepository::loadFromFolder(Study& study, if (study.usedByTheSolver) { - if (!study.parameters.maintenancePlanning.mpModelling != mpOptimized) + if (!study.parameters.maintenancePlanning.isOptimized()) { logs.info() << " The maintenance groups shall be ignored due to the advanced parameters"; From d7e36f088a39f8e1437e2e9485a2f12f2f30ec41 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Thu, 2 Nov 2023 14:39:22 +0100 Subject: [PATCH 032/315] fix - checks --- .../study/maintenance_planning/MaintenanceGroupLoader.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroupLoader.cpp b/src/libs/antares/study/maintenance_planning/MaintenanceGroupLoader.cpp index 341df3da80..226282d6c5 100644 --- a/src/libs/antares/study/maintenance_planning/MaintenanceGroupLoader.cpp +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroupLoader.cpp @@ -76,13 +76,13 @@ std::vector> MaintenanceGroupLoader::load(EnvF } // Checking for validity - if (!mnt->name_.empty()) + if (mnt->name_.empty()) { logs.error() << env.iniFilename << ": in [" << env.section->name << "]: Invalid maintenance group name"; return {}; } - if (!mnt->ID_.empty()) + if (mnt->ID_.empty()) { logs.error() << env.iniFilename << ": in [" << env.section->name << "]: Invalid maintenance group id"; From eaba3e3d27fff14cedc830e194ea3a1fa0dc4894 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Thu, 2 Nov 2023 15:53:32 +0100 Subject: [PATCH 033/315] fix - save --- .../study/maintenance_planning/MaintenanceGroupSaver.cpp | 2 +- .../antares/study/maintenance_planning/MaintenanceGroupSaver.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroupSaver.cpp b/src/libs/antares/study/maintenance_planning/MaintenanceGroupSaver.cpp index 1cf1385b74..648da17769 100644 --- a/src/libs/antares/study/maintenance_planning/MaintenanceGroupSaver.cpp +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroupSaver.cpp @@ -32,7 +32,7 @@ bool MaintenanceGroupSaver::saveToEnv(EnvForSaving& env, const MaintenanceGroup* const Area& area = *(i->first); // add weight-load+renewable+ror - env.key.clear() << area.name << '.weights'; + env.key.clear() << area.name << ".weights"; value << i->second.load << '%' << i->second.renewable << '%' << i->second.ror; env.section->add(env.key, value); } diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroupSaver.h b/src/libs/antares/study/maintenance_planning/MaintenanceGroupSaver.h index 5219367ca1..a027b2ca15 100644 --- a/src/libs/antares/study/maintenance_planning/MaintenanceGroupSaver.h +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroupSaver.h @@ -21,7 +21,7 @@ class MaintenanceGroupSaver //! Current section IniFile::Section* section = nullptr; Yuni::Clob folder; - Yuni::CString<(ant_k_area_name_max_length + 15), false> key; + Yuni::CString<(ant_k_area_name_max_length + 8), false> key; }; /*! From af0c5e42a373b15ef1beb6bcc44738c506bd2942 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Thu, 2 Nov 2023 16:11:23 +0100 Subject: [PATCH 034/315] update TODO-s --- .../study/maintenance_planning/MaintenanceGroupLoader.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroupLoader.h b/src/libs/antares/study/maintenance_planning/MaintenanceGroupLoader.h index 0aa48c6d69..f633252b06 100644 --- a/src/libs/antares/study/maintenance_planning/MaintenanceGroupLoader.h +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroupLoader.h @@ -33,10 +33,11 @@ class MaintenanceGroupLoader TODO CR27: for II phase: * check if same area is inside more than 1 Maintenance Group - and throw error - * what happens when area name is changed - UI code - * we need to change the name in INI file in Maintenance Group - * what happens if the area is deleted - UI code - * we need to remove that area from all Maintenance Group-s + * what happens when area name is changed - UI code -- tested area name will be changed in INI file once study is saved - OK + * what happens if the area is deleted - UI code - tested all mnt groups containing area name will be removed from INI file once study is saved + - OK?! or not OK! - maybe it is better to remove this area from mnt group? + This will actually happen if you try to load the mnt groups from ini file and the area from INI file do not exist in the model. + That area,with all weights, will be removed from INI file. Mnt Group-s will not be removed - just missing area will be removed from the mnt group. */ From b22f448c8cadfddc1cd7f2aedaceb685f5d7d476 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Fri, 3 Nov 2023 09:50:39 +0100 Subject: [PATCH 035/315] add scenario length & number to repository --- .../MaintenanceGroupRepository.cpp | 2 ++ .../MaintenanceGroupRepository.h | 21 ++++++++++++++++++- .../MaintenanceGroupRepository.hxx | 20 ++++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.cpp b/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.cpp index fb281918a9..db43962bff 100644 --- a/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.cpp +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.cpp @@ -16,6 +16,8 @@ void Data::MaintenanceGroupRepository::clear() { maintenanceGroups_.clear(); activeMaintenanceGroups_.reset(); + scenariosLength_ = 0; + scenariosNumber_ =0; } namespace Antares::Data diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.h b/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.h index 5f67f5fa97..efd55160ee 100644 --- a/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.h +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.h @@ -137,12 +137,31 @@ class MaintenanceGroupRepository final : public Yuni::NonCopyable> activeMaintenanceGroups() const; + /*! + ** \brief The scenarios number and length + ** + ** \return Get the scenarios number and length + */ + uint scenariosNumber() const; + uint scenariosLength() const; + + /*! + ** \brief Set the scenarios number and length + */ + void scenariosNumber(uint num); + void scenariosLength(uint l); + private: + + // number and length of the Maintenance Group-s scenarios + uint scenariosNumber_ = 0; + uint scenariosLength_ = 0; + + // private methods bool internalSaveToFolder(Data::MaintenanceGroupSaver::EnvForSaving& env) const; //! All Maintenance Group-s Data::MaintenanceGroupRepository::Vector maintenanceGroups_; - mutable std::optional>> activeMaintenanceGroups_; }; diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.hxx b/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.hxx index 6f4a384967..e1683070bd 100644 --- a/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.hxx +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.hxx @@ -20,6 +20,26 @@ inline bool MaintenanceGroupRepository::empty() const return maintenanceGroups_.empty(); } +inline uint MaintenanceGroupRepository::scenariosNumber() const +{ + return scenariosNumber_; +} + +inline void MaintenanceGroupRepository::scenariosNumber(uint num) +{ + scenariosNumber_ = num; +} + +inline uint MaintenanceGroupRepository::scenariosLength() const +{ + return scenariosLength_; +} + +inline void MaintenanceGroupRepository::scenariosLength(uint l) +{ + scenariosLength_ = l; +} + template inline void MaintenanceGroupRepository::each(const PredicateT& predicate) { From c945061c8874e5e9371c8dd2a81459dbc5f714ed Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Fri, 3 Nov 2023 13:05:07 +0100 Subject: [PATCH 036/315] save scenario settings to ini file --- .../MaintenanceGroupRepository.cpp | 22 ++++++++++++++++++- .../MaintenanceGroupRepository.h | 1 + 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.cpp b/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.cpp index db43962bff..cf205554ee 100644 --- a/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.cpp +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.cpp @@ -104,7 +104,10 @@ bool MaintenanceGroupRepository::saveToFolder(const AnyString& folder) const { MaintenanceGroupSaver::EnvForSaving env; env.folder = folder; - return internalSaveToFolder(env); + bool ret = internalSaveToFolder(env); + env.folder = folder; + ret = internalSaveScenariosToFolder(env) && ret; + return ret; } bool MaintenanceGroupRepository::rename(MaintenanceGroup* mnt, const AnyString& newname) @@ -228,6 +231,23 @@ bool MaintenanceGroupRepository::internalSaveToFolder( return ini.save(env.folder) && ret; } +bool MaintenanceGroupRepository::internalSaveScenariosToFolder( + MaintenanceGroupSaver::EnvForSaving& env) const +{ + if (!Yuni::IO::Directory::Create(env.folder)) + return false; + + IniFile ini; + std::string text = "ScenariosSettings"; + + env.section = ini.addSection(text); + env.section->add("Number", scenariosNumber_); + env.section->add("Length", scenariosLength_); + + env.folder << Yuni::IO::Separator << "scenariossettings.ini"; + return ini.save(env.folder); +} + void MaintenanceGroupRepository::reverseWeightSign(const AreaLink* lnk) { } diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.h b/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.h index efd55160ee..61dc65b0c9 100644 --- a/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.h +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.h @@ -159,6 +159,7 @@ class MaintenanceGroupRepository final : public Yuni::NonCopyable Date: Fri, 3 Nov 2023 14:35:14 +0100 Subject: [PATCH 037/315] load scenario settings from ini file --- .../MaintenanceGroupRepository.cpp | 51 ++++++++++++++++++- .../MaintenanceGroupRepository.h | 1 + 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.cpp b/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.cpp index cf205554ee..bd81bf3f51 100644 --- a/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.cpp +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.cpp @@ -100,6 +100,54 @@ std::vector> MaintenanceGroupRepository::LoadM return loader.load(std::move(env)); } +bool MaintenanceGroupRepository::internalLoadScenarioSettings(EnvForLoading env) +{ + // set path + env.iniFilename = env.folder << Yuni::IO::Separator << "scenariossettings.ini"; + // try to open ini file + IniFile ini; + if (!ini.open(env.iniFilename)) + { + logs.info() << " File: " << env.iniFilename << " Does not exists. Unsuccessful loading!"; + return false; + } + // see if there is any section + if (!ini.firstSection) + { + return true; + } + // see if the fist and only section is called "ScenariosSettings" + if (ini.firstSection->name != "ScenariosSettings") + { + return true; + } + // read the first section + env.section = ini.firstSection; + // check if section has properties + if (!env.section->firstProperty) + { + return true; + } + // loop through all properties + for (const IniFile::Property* p = env.section->firstProperty; p; p = p->next) + { + if (p->key.empty()) + continue; + + if (p->key == "number") + { + scenariosNumber(p->value.to()); + continue; + } + if (p->key == "length") + { + scenariosLength(p->value.to()); + continue; + } + } + return true; +} + bool MaintenanceGroupRepository::saveToFolder(const AnyString& folder) const { MaintenanceGroupSaver::EnvForSaving env; @@ -190,7 +238,8 @@ bool MaintenanceGroupRepository::loadFromFolder(Study& study, logs.info() << maintenanceGroups_.size() << " maintenance groups found"; } - return true; + env.folder = folder; + return internalLoadScenarioSettings(env); } bool MaintenanceGroupRepository::internalSaveToFolder( diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.h b/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.h index 61dc65b0c9..aa5d7bab3c 100644 --- a/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.h +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.h @@ -160,6 +160,7 @@ class MaintenanceGroupRepository final : public Yuni::NonCopyable Date: Tue, 7 Nov 2023 10:14:16 +0100 Subject: [PATCH 038/315] add iterator to MaintenanceGroup - we may need it later --- .../maintenance_planning/MaintenanceGroup.h | 13 ++++++++++++ .../maintenance_planning/MaintenanceGroup.hxx | 20 +++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroup.h b/src/libs/antares/study/maintenance_planning/MaintenanceGroup.h index 2ff70812b0..5298272a71 100644 --- a/src/libs/antares/study/maintenance_planning/MaintenanceGroup.h +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroup.h @@ -75,6 +75,10 @@ class MaintenanceGroup : public Yuni::NonCopyable using MaintenanceGroupName = std::string; //! Map of load, renewable or ror weight-s using weightMap = std::map; + //! Iterator + using iterator = weightMap::iterator; + //! Const iterator + using const_iterator = weightMap::const_iterator; /*! ** \brief Convert a Residual Load Definition Type into a mere C-String @@ -113,6 +117,15 @@ class MaintenanceGroup : public Yuni::NonCopyable const MaintenanceGroupName& id() const; //@} + //! \name iterator + //@{ + iterator begin(); + const_iterator begin() const; + + iterator end(); + const_iterator end() const; + //@} + /*! ** \brief resets all to default data */ diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroup.hxx b/src/libs/antares/study/maintenance_planning/MaintenanceGroup.hxx index 6f89dd8161..89ebfd8b88 100644 --- a/src/libs/antares/study/maintenance_planning/MaintenanceGroup.hxx +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroup.hxx @@ -66,4 +66,24 @@ inline bool MaintenanceGroup::isActive() const return enabled() && !skipped(); } +inline MaintenanceGroup::iterator MaintenanceGroup::begin() +{ + return weights_.begin(); +} + +inline MaintenanceGroup::iterator MaintenanceGroup::end() +{ + return weights_.end(); +} + +inline MaintenanceGroup::const_iterator MaintenanceGroup::begin() const +{ + return weights_.begin(); +} + +inline MaintenanceGroup::const_iterator MaintenanceGroup::end() const +{ + return weights_.end(); +} + } // namespace Antares::Data From 6e51c684c89fbe7e10358765ec4dfa1cb9624629 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 7 Nov 2023 10:34:26 +0100 Subject: [PATCH 039/315] ResidualLoadTS -> for phase-II + for opt.problem parameters --- .../maintenance_planning/MaintenanceGroup.cpp | 10 ++++++++++ .../maintenance_planning/MaintenanceGroup.h | 20 +++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroup.cpp b/src/libs/antares/study/maintenance_planning/MaintenanceGroup.cpp index c155188fc4..ca5cbe6cb0 100644 --- a/src/libs/antares/study/maintenance_planning/MaintenanceGroup.cpp +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroup.cpp @@ -143,6 +143,16 @@ double MaintenanceGroup::rorWeight(const Area* area) const return (i != weights_.end()) ? i->second.ror : 0.; } +void MaintenanceGroup::setUsedResidualLoadTS(std::array ts) +{ + usedResidualLoadTS_ = ts; +} + +std::array MaintenanceGroup::getUsedResidualLoadTS() const +{ + return usedResidualLoadTS_; +} + void MaintenanceGroup::clearAndReset(const MaintenanceGroupName& name, MaintenanceGroup::ResidualLoadDefinitionType newType) { diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroup.h b/src/libs/antares/study/maintenance_planning/MaintenanceGroup.h index 5298272a71..a539e89634 100644 --- a/src/libs/antares/study/maintenance_planning/MaintenanceGroup.h +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroup.h @@ -188,6 +188,19 @@ class MaintenanceGroup : public Yuni::NonCopyable void setResidualLoadDefinitionType(ResidualLoadDefinitionType t); //@} + //! \name UsedResidualLoadTS + //@{ + /*! + ** \brief Get the UsedResidualLoadTS_ of the Maintenance Group + */ + void setUsedResidualLoadTS(std::array ts); + + /*! + ** \brief Set the UsedResidualLoadTS_ of the Maintenance Group + */ + std::array getUsedResidualLoadTS() const; + //@} + //! \name Enabled / Disabled //@{ //! Get if the Maintenance Group is enabled @@ -239,6 +252,13 @@ class MaintenanceGroup : public Yuni::NonCopyable ResidualLoadDefinitionType type_ = typeWeights; //! Enabled / Disabled bool enabled_ = true; + //! 8760 x 1 - Matrix of residual loads per h provided by the user + // TODO CR27: for phase-II -> setters, getters, reset, markAsModified, resetToDefaultValues, forceReload, memoryUsage + Matrix<> userProvidedResidualLoadTS_; + //! array of residual loads per h + //! if typeTimeserie -> equal to userProvidedResidualLoadTS_, + //! if typeWeights -> calculated using per area weights + std::array usedResidualLoadTS_; void clear(); void copyFrom(MaintenanceGroup const* original); From add5f329c366fe33db18e0f6f7fbb9c51b4bca67 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 7 Nov 2023 10:38:57 +0100 Subject: [PATCH 040/315] temporary comments for mnt-ts-generator backbone --- .../series/include/antares/series/series.h | 2 +- src/libs/antares/study/parameters.h | 2 +- .../antares/writer/antares/writer/i_writer.h | 2 +- src/solver/simulation/solver.hxx | 16 +++++----- src/solver/ts-generator/generator.h | 4 +-- src/solver/ts-generator/thermal.cpp | 30 +++++++++---------- 6 files changed, 28 insertions(+), 28 deletions(-) diff --git a/src/libs/antares/series/include/antares/series/series.h b/src/libs/antares/series/include/antares/series/series.h index 48b7b7e4fd..7dca43c839 100644 --- a/src/libs/antares/series/include/antares/series/series.h +++ b/src/libs/antares/series/include/antares/series/series.h @@ -86,7 +86,7 @@ class TimeSeries void markAsModified() const; uint64_t memoryUsage() const; - TS timeSeries; + TS timeSeries; // TMP.INFO CR27: TS-s will be written here! numbers& timeseriesNumbers; static const double emptyColumn[HOURS_PER_YEAR]; diff --git a/src/libs/antares/study/parameters.h b/src/libs/antares/study/parameters.h index cc97caec93..c09b9c9c05 100644 --- a/src/libs/antares/study/parameters.h +++ b/src/libs/antares/study/parameters.h @@ -304,7 +304,7 @@ class Parameters final ** This value is a mask bits for timeSeries. ** \see TimeSeries */ - uint timeSeriesToArchive; + uint timeSeriesToArchive; //TMP.INFO CR27: archives = load, thermal etc... - adds category only if store in ouput is yes and stochastic TS status is yes //@} //! \name Pre-Processor diff --git a/src/libs/antares/writer/antares/writer/i_writer.h b/src/libs/antares/writer/antares/writer/i_writer.h index be579165e5..f1881c592f 100644 --- a/src/libs/antares/writer/antares/writer/i_writer.h +++ b/src/libs/antares/writer/antares/writer/i_writer.h @@ -20,7 +20,7 @@ class IOError : public std::runtime_error using std::runtime_error::runtime_error; }; -class IResultWriter +class IResultWriter // TMP.INFO CR27: this is your TS generator writer { public: using Ptr = std::shared_ptr; diff --git a/src/solver/simulation/solver.hxx b/src/solver/simulation/solver.hxx index 8a33ad50b5..49cb2e4827 100644 --- a/src/solver/simulation/solver.hxx +++ b/src/solver/simulation/solver.hxx @@ -318,11 +318,11 @@ void ISimulation::run() // in general data of the study. logs.info() << " Only the preprocessors are enabled."; - regenerateTimeSeries(0); + regenerateTimeSeries(0);// TMP.INFO CR27: when running ts-gen ONLY. No refresh span needed. Year = 0. We only generate TS-s once. No refreshing TS-s is necessary // Destroy the TS Generators if any // It will export the time-series into the output in the same time - Solver::TSGenerator::DestroyAll(study); + Solver::TSGenerator::DestroyAll(study); // TMP.INFO CR27: be aware of this destroy - it is OK } else { @@ -363,7 +363,7 @@ void ISimulation::run() uint finalYear = 1 + study.runtime->rangeLimits.year[Data::rangeEnd]; { Benchmarking::Timer timer; - loopThroughYears(0, finalYear, state); + loopThroughYears(0, finalYear, state); // TMP.INFO CR27: inside this method is TS-generator timer.stop(); pDurationCollector.addDuration("mc_years", timer.get_duration()); } @@ -442,7 +442,7 @@ void ISimulation::writeResults(bool synthesis, uint year, uint numSpace) } template -void ISimulation::regenerateTimeSeries(uint year) +void ISimulation::regenerateTimeSeries(uint year) // TMP.INFO CR27: Generate TS-s. Input year - is MC year. { // A preprocessor can be launched for several reasons: // * The option "Preprocessor" is checked in the interface _and_ year == 0 @@ -482,10 +482,10 @@ void ISimulation::regenerateTimeSeries(uint year) pDurationCollector.addDuration("tsgen_hydro", timer.get_duration()); } // Thermal - const bool refreshTSonCurrentYear = (year % pData.refreshIntervalThermal == 0); + const bool refreshTSonCurrentYear = (year % pData.refreshIntervalThermal == 0); // TMP.INFO CR27: we are going to generate new set of TS-s only if MC-year is dividable by "refresh span" { Benchmarking::Timer timer; - GenerateThermalTimeSeries( + GenerateThermalTimeSeries( // TMP.INFO CR27: call the thermal ts- gen here! study, year, pData.haveToRefreshTSThermal, refreshTSonCurrentYear, pResultWriter); timer.stop(); pDurationCollector.addDuration("tsgen_thermal", timer.get_duration()); @@ -946,13 +946,13 @@ void ISimulation::loopThroughYears(uint firstYear, // Loop over sets of parallel years std::vector::iterator set_it; - for (set_it = setsOfParallelYears.begin(); set_it != setsOfParallelYears.end(); ++set_it) + for (set_it = setsOfParallelYears.begin(); set_it != setsOfParallelYears.end(); ++set_it) // TMP.INFO CR27: we are in parallel work here already { // 1 - We may want to regenerate the time-series this year. // This is the case when the preprocessors are enabled from the // interface and/or the refresh is enabled. if (set_it->regenerateTS) - regenerateTimeSeries(set_it->yearForTSgeneration); + regenerateTimeSeries(set_it->yearForTSgeneration); // TMP.INFO CR27: The TS-gen is going to be called ONLY for those years where at least one type [load,wind,hydro...] needs re-generation!! computeRandomNumbers(randomForParallelYears, set_it->yearsIndices, set_it->isYearPerformed); diff --git a/src/solver/ts-generator/generator.h b/src/solver/ts-generator/generator.h index 1f3582fb2c..1f2383f803 100644 --- a/src/solver/ts-generator/generator.h +++ b/src/solver/ts-generator/generator.h @@ -44,9 +44,9 @@ namespace TSGenerator ** \brief Regenerate the time-series */ template -bool GenerateTimeSeries(Data::Study& study, uint year, IResultWriter& writer); +bool GenerateTimeSeries(Data::Study& study, uint year, IResultWriter& writer); // TMP.INFO CR27: one TS gen for the rest -bool GenerateThermalTimeSeries(Data::Study& study, +bool GenerateThermalTimeSeries(Data::Study& study, // TMP.INFO CR27: One TS gen for thermal uint year, bool globalThermalTSgeneration, bool refresh, diff --git a/src/solver/ts-generator/thermal.cpp b/src/solver/ts-generator/thermal.cpp index e11d4a056c..8808fe3fb8 100644 --- a/src/solver/ts-generator/thermal.cpp +++ b/src/solver/ts-generator/thermal.cpp @@ -61,14 +61,14 @@ class GeneratorTempData final Solver::Progression::Task& progr, IResultWriter& writer); - void prepareOutputFoldersForAllAreas(uint year); + void prepareOutputFoldersForAllAreas(uint year); // TMP.INFO CR27: not used at all - void operator()(Data::Area& area, Data::ThermalCluster& cluster); + void operator()(Data::Area& area, Data::ThermalCluster& cluster); // TMP.INFO CR27: called as (*generator)(area, cluster); public: Data::Study& study; - bool archive; + bool archive; // TMP.INFO CR27: whether to write it in txt or not! uint currentYear; @@ -128,9 +128,9 @@ GeneratorTempData::GeneratorTempData(Data::Study& study, { auto& parameters = study.parameters; - archive = (0 != (parameters.timeSeriesToArchive & Data::timeSeriesThermal)); + archive = (0 != (parameters.timeSeriesToArchive & Data::timeSeriesThermal)); // TMP.INFO CR27: save to txt or not! - nbThermalTimeseries = parameters.nbTimeSeriesThermal; + nbThermalTimeseries = parameters.nbTimeSeriesThermal; // TMP.INFO CR27: this will be changed - and will be sc-num x sc-length - best to change it here - not to mess with importing the actual number in the simulator derated = parameters.derated; } @@ -205,7 +205,7 @@ void GeneratorTempData::prepareIndispoFromLaw(Data::ThermalLaw law, } } -int GeneratorTempData::durationGenerator(Data::ThermalLaw law, +int GeneratorTempData::durationGenerator(Data::ThermalLaw law, // TMP.INFO CR27: use this for mnt duration ?! int expec, double volat, double a, @@ -236,7 +236,7 @@ int GeneratorTempData::durationGenerator(Data::ThermalLaw law, return 0; } -void GeneratorTempData::operator()(Data::Area& area, Data::ThermalCluster& cluster) +void GeneratorTempData::operator()(Data::Area& area, Data::ThermalCluster& cluster) // TMP.INFO CR27: calling operator { if (not cluster.prepro) { @@ -251,14 +251,14 @@ void GeneratorTempData::operator()(Data::Area& area, Data::ThermalCluster& clust if (0 == cluster.unitCount or 0 == cluster.nominalCapacity) { - cluster.series.timeSeries.reset(1, nbHoursPerYear); + cluster.series.timeSeries.reset(1, nbHoursPerYear); // TMP.INFO CR27: still ok - keep it like this // actually add clusters not in any mnt-group to behave like this!! if (archive) writeResultsToDisk(area, cluster); return; } - cluster.series.timeSeries.resize(nbThermalTimeseries, nbHoursPerYear); + cluster.series.timeSeries.resize(nbThermalTimeseries, nbHoursPerYear); // TMP.INFO CR27: re-size here! const auto& preproData = *(cluster.prepro); @@ -353,7 +353,7 @@ void GeneratorTempData::operator()(Data::Area& area, Data::ThermalCluster& clust auto& modulation = cluster.modulation[Data::thermalModulationCapacity]; - double* dstSeries = nullptr; + double* dstSeries = nullptr; // TMP.INFO CR27: pointer to cluster.series.timeSeries columns const uint tsCount = nbThermalTimeseries + 2; for (uint tsIndex = 0; tsIndex != tsCount; ++tsIndex) @@ -593,14 +593,14 @@ void GeneratorTempData::operator()(Data::Area& area, Data::ThermalCluster& clust double AVPDayInTheYear = AVP[dayInTheYear]; for (uint h = 0; h != 24; ++h) { - dstSeries[hour] = Math::Round(AVPDayInTheYear * modulation[hour]); + dstSeries[hour] = Math::Round(AVPDayInTheYear * modulation[hour]); // TMP.INFO CR27: here it is changed ++hour; } } } } - if (derated) + if (derated) // TMP.INFO CR27: derated mode - averaging - keep it like this! cluster.series.timeSeries.averageTimeseries(); if (archive) @@ -610,7 +610,7 @@ void GeneratorTempData::operator()(Data::Area& area, Data::ThermalCluster& clust } } // namespace -bool GenerateThermalTimeSeries(Data::Study& study, +bool GenerateThermalTimeSeries(Data::Study& study, // TMP.INFO CR27: thermal ts-gen method definition uint year, bool globalThermalTSgeneration, bool refreshTSonCurrentYear, @@ -618,7 +618,7 @@ bool GenerateThermalTimeSeries(Data::Study& study, { logs.info(); logs.info() << "Generating the thermal time-series"; - Solver::Progression::Task progression(study, year, Solver::Progression::sectTSGThermal); + Solver::Progression::Task progression(study, year, Solver::Progression::sectTSGThermal); // TMP.INFO CR27: parallel work ??!! - NO auto* generator = new GeneratorTempData(study, progression, writer); @@ -630,7 +630,7 @@ bool GenerateThermalTimeSeries(Data::Study& study, { auto& cluster = *(it->second); - if (cluster.doWeGenerateTS(globalThermalTSgeneration) && refreshTSonCurrentYear) + if (cluster.doWeGenerateTS(globalThermalTSgeneration) && refreshTSonCurrentYear) // TMP.INFO CR27: we decide here for each cluster whether we generate TS or not - We need to get rid of refreshTSonCurrentYear - not important for mnt-planning - doWeGenerateTS is still ok to use! { (*generator)(area, cluster); } From 58ddac069df5a23d2dfb3aa13d4222d8986c66ab Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 7 Nov 2023 13:04:49 +0100 Subject: [PATCH 041/315] small refactor --- src/libs/antares/study/parts/thermal/cluster_list.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/antares/study/parts/thermal/cluster_list.cpp b/src/libs/antares/study/parts/thermal/cluster_list.cpp index 8bccbf74a3..6598e9eee0 100644 --- a/src/libs/antares/study/parts/thermal/cluster_list.cpp +++ b/src/libs/antares/study/parts/thermal/cluster_list.cpp @@ -548,7 +548,7 @@ bool ThermalClusterList::loadEconomicCosts(Study& study, const AnyString& folder bool ThermalClusterList::generateRandomDaysSinceLastMaintenance(Study& study) { - if (empty() || study.parameters.maintenancePlanning.mpModelling != mpOptimized) + if (empty() || !study.parameters.maintenancePlanning.isOptimized()) return true; bool ret = true; From f2b94f2981c859b754260d984fabdba576c7ea03 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 7 Nov 2023 13:05:46 +0100 Subject: [PATCH 042/315] todo: do we need calculationOfSpinning ? --- src/solver/ts-generator/thermal.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/solver/ts-generator/thermal.cpp b/src/solver/ts-generator/thermal.cpp index 8808fe3fb8..c4813b51dd 100644 --- a/src/solver/ts-generator/thermal.cpp +++ b/src/solver/ts-generator/thermal.cpp @@ -606,7 +606,7 @@ void GeneratorTempData::operator()(Data::Area& area, Data::ThermalCluster& clust if (archive) writeResultsToDisk(area, cluster); - cluster.calculationOfSpinning(); + cluster.calculationOfSpinning(); // TODO CR27 // do we still need to call this function?! } } // namespace From 290656c358ef63e8626c5345ae18387472e17d80 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 7 Nov 2023 13:48:13 +0100 Subject: [PATCH 043/315] separate thermal-ts-gen into randomized and optimized --- src/solver/ts-generator/generator.h | 11 +++++++++ src/solver/ts-generator/thermal.cpp | 35 +++++++++++++++++++++++++++-- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/src/solver/ts-generator/generator.h b/src/solver/ts-generator/generator.h index 1f2383f803..da8eaaacfc 100644 --- a/src/solver/ts-generator/generator.h +++ b/src/solver/ts-generator/generator.h @@ -52,6 +52,17 @@ bool GenerateThermalTimeSeries(Data::Study& study, // TMP.INFO CR27: One TS gen bool refresh, IResultWriter& writer); +bool GenerateRandomizedThermalTimeSeries(Data::Study& study, + uint year, + bool globalThermalTSgeneration, + bool refresh, + IResultWriter& writer); + +bool GenerateOptimizedThermalTimeSeries(Data::Study& study, + uint year, + bool globalThermalTSgeneration, + IResultWriter& writer); + /*! ** \brief Destroy all TS Generators */ diff --git a/src/solver/ts-generator/thermal.cpp b/src/solver/ts-generator/thermal.cpp index c4813b51dd..307e111695 100644 --- a/src/solver/ts-generator/thermal.cpp +++ b/src/solver/ts-generator/thermal.cpp @@ -610,14 +610,14 @@ void GeneratorTempData::operator()(Data::Area& area, Data::ThermalCluster& clust } } // namespace -bool GenerateThermalTimeSeries(Data::Study& study, // TMP.INFO CR27: thermal ts-gen method definition +bool GenerateRandomizedThermalTimeSeries(Data::Study& study, uint year, bool globalThermalTSgeneration, bool refreshTSonCurrentYear, Antares::Solver::IResultWriter& writer) { logs.info(); - logs.info() << "Generating the thermal time-series"; + logs.info() << "Generating randomized thermal time-series"; Solver::Progression::Task progression(study, year, Solver::Progression::sectTSGThermal); // TMP.INFO CR27: parallel work ??!! - NO auto* generator = new GeneratorTempData(study, progression, writer); @@ -644,6 +644,37 @@ bool GenerateThermalTimeSeries(Data::Study& study, // TMP.INFO CR27: thermal ts- return true; } +bool GenerateOptimizedThermalTimeSeries(Data::Study& study, + uint year, + bool globalThermalTSgeneration, + Antares::Solver::IResultWriter& writer) +{ + logs.info(); + logs.info() << "Generating optimized thermal time-series"; + Solver::Progression::Task progression(study, year, Solver::Progression::sectTSGThermal); + + + + return true; +} + +bool GenerateThermalTimeSeries(Data::Study& study, + uint year, + bool globalThermalTSgeneration, + bool refreshTSonCurrentYear, + Antares::Solver::IResultWriter& writer) +{ + if (study.parameters.maintenancePlanning.isOptimized()) + { + return GenerateOptimizedThermalTimeSeries(study, year, globalThermalTSgeneration, writer); + } + else + { + return GenerateRandomizedThermalTimeSeries( + study, year, globalThermalTSgeneration, refreshTSonCurrentYear, writer); + } +} + } // namespace TSGenerator } // namespace Solver } // namespace Antares From 2ab7224a96d80ecaf6133499fbeaae4b1c520797 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 7 Nov 2023 15:45:33 +0100 Subject: [PATCH 044/315] loop through mnt-groups-ares-clusters --- src/solver/ts-generator/thermal.cpp | 40 ++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/src/solver/ts-generator/thermal.cpp b/src/solver/ts-generator/thermal.cpp index 307e111695..1616fa37e0 100644 --- a/src/solver/ts-generator/thermal.cpp +++ b/src/solver/ts-generator/thermal.cpp @@ -645,15 +645,49 @@ bool GenerateRandomizedThermalTimeSeries(Data::Study& study, } bool GenerateOptimizedThermalTimeSeries(Data::Study& study, - uint year, - bool globalThermalTSgeneration, - Antares::Solver::IResultWriter& writer) + uint year, + bool globalThermalTSgeneration, + Antares::Solver::IResultWriter& writer) { + // optimized planning should only be called once. + // Due to possible thermal refresh span we can end up here more than once - but just ignore it + if (year != 0) + return true; + logs.info(); logs.info() << "Generating optimized thermal time-series"; Solver::Progression::Task progression(study, year, Solver::Progression::sectTSGThermal); + auto generator = GeneratorTempData(study, progression, writer); + + auto& repo = study.maintenanceGroups; + const auto& groups = repo.activeMaintenanceGroups(); + + generator.currentYear = year; + generator.nbThermalTimeseries = repo.scenariosNumber() * repo.scenariosLength(); + + // TODO CR27: This part needs a lot of refactoring- to many nested loops!! + for (const auto& entryGroups : groups) + { + const auto& group = *(entryGroups.get()); + for (const auto& entryGroup : group) + { + const auto& area = *(entryGroup.first); + // extract weights + for (auto it = area.thermal.list.mapping.begin(); it != area.thermal.list.mapping.end(); + ++it) + { + auto& cluster = *(it->second); + if (cluster.doWeGenerateTS(globalThermalTSgeneration) + && cluster.optimizeMaintenance) + { + + } + ++progression; + } + } + } return true; } From 9ba9617ef94d8a423805080ff905e6a9790b2039 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 7 Nov 2023 15:47:01 +0100 Subject: [PATCH 045/315] to be reverted - just trying out something --- src/solver/ts-generator/thermal.cpp | 31 +++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/src/solver/ts-generator/thermal.cpp b/src/solver/ts-generator/thermal.cpp index 1616fa37e0..32a8011107 100644 --- a/src/solver/ts-generator/thermal.cpp +++ b/src/solver/ts-generator/thermal.cpp @@ -76,9 +76,9 @@ class GeneratorTempData final bool derated; -private: - void writeResultsToDisk(const Data::Area& area, const Data::ThermalCluster& cluster); + void writeResultsToDisk(const Data::Area& area, const Data::ThermalCluster& cluster); // TODO CR27: just temporary, while playing, revert later +private: int durationGenerator(Data::ThermalLaw law, int expec, double volat, double a, double b); template @@ -681,7 +681,34 @@ bool GenerateOptimizedThermalTimeSeries(Data::Study& study, if (cluster.doWeGenerateTS(globalThermalTSgeneration) && cluster.optimizeMaintenance) { + // just playing here - this needs to go into new method - class - operator + logs.info() << "CR27-INFO: This cluster is active for mnt planning: " + << cluster.getFullName(); + + if (!cluster.prepro) + { + logs.error() << "Cluster: " << area.name << '/' << cluster.name() + << ": The timeseries will not be regenerated. All data " + "related to the ts-generator for " + << "'thermal' have been released."; + } + + assert(cluster.prepro); + + if (0 == cluster.unitCount or 0 == cluster.nominalCapacity) + { + cluster.series.timeSeries.reset(1, 8760); + } + else + { + cluster.series.timeSeries.reset(generator.nbThermalTimeseries, 8760); + cluster.series.timeSeries.fill(777.); + } + + if (generator.archive) + generator.writeResultsToDisk(area, cluster); + // end playing } ++progression; From 7fb606084f3446ad0d9be5eebc91bd7c443c7dd6 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 8 Nov 2023 11:17:59 +0100 Subject: [PATCH 046/315] create structure of OptimizedThermalGenerator class --- src/solver/ts-generator/thermal.cpp | 65 +++++++++++++++++++++++++---- 1 file changed, 57 insertions(+), 8 deletions(-) diff --git a/src/solver/ts-generator/thermal.cpp b/src/solver/ts-generator/thermal.cpp index 32a8011107..86c185f3a0 100644 --- a/src/solver/ts-generator/thermal.cpp +++ b/src/solver/ts-generator/thermal.cpp @@ -54,7 +54,7 @@ namespace TSGenerator { namespace { -class GeneratorTempData final +class GeneratorTempData { public: GeneratorTempData(Data::Study& study, @@ -76,11 +76,11 @@ class GeneratorTempData final bool derated; - void writeResultsToDisk(const Data::Area& area, const Data::ThermalCluster& cluster); // TODO CR27: just temporary, while playing, revert later - -private: + // I need these two functions for inheritance + void writeResultsToDisk(const Data::Area& area, const Data::ThermalCluster& cluster); int durationGenerator(Data::ThermalLaw law, int expec, double volat, double a, double b); +private: template void prepareIndispoFromLaw(Data::ThermalLaw law, double volatility, @@ -135,7 +135,7 @@ GeneratorTempData::GeneratorTempData(Data::Study& study, derated = parameters.derated; } -void GeneratorTempData::writeResultsToDisk(const Data::Area& area, +void GeneratorTempData::writeResultsToDisk(const Data::Area& area, // I want to inherit this method const Data::ThermalCluster& cluster) { if (not study.parameters.noOutput) @@ -205,7 +205,7 @@ void GeneratorTempData::prepareIndispoFromLaw(Data::ThermalLaw law, } } -int GeneratorTempData::durationGenerator(Data::ThermalLaw law, // TMP.INFO CR27: use this for mnt duration ?! +int GeneratorTempData::durationGenerator(Data::ThermalLaw law, // TMP.INFO CR27: use this for mnt duration ?! I want to inherit this method int expec, double volat, double a, @@ -610,6 +610,54 @@ void GeneratorTempData::operator()(Data::Area& area, Data::ThermalCluster& clust } } // namespace +namespace // TODO CR27: move this to separate *.h and *.cpp file +{ + +class OptimizedThermalGenerator : public GeneratorTempData +{ +private: + /* + in adq-patch we re-used existing structure(s) for helping us define an optimization problem -> + like: struct CORRESPONDANCES_DES_VARIABLES. + unfortunately here we have to create our own help-structure if we need one + Question: can we still use struct PROBLEME_ANTARES_A_RESOUDRE ?! + if we define problem for sirius solver we use this structure. + for OR tools solver we also use this structure I think ?! + */ + + // define here variables/structures that will help us build optimization problem + + // optimization problem construction methods + void calculateParameters(); + void buildProblemVariables(); + void setVariableBounds(); + void buildProblemConstraintsLHS(); + void buildProblemConstraintsRHS(); + void setProblemCost(); + void solveProblem(); + void allocateProblem(); // this one should be called in constructor. It basically resets all the + // vectors in PROBLEME_ANTARES_A_RESOUDRE for new opt problem. + +public: + void run(); // calls private optimization problem construction methods + + explicit OptimizedThermalGenerator(Data::Study& study, + Solver::Progression::Task& progr, + IResultWriter& writer) : + GeneratorTempData(study, progr, writer) + { + // do something here + + // allocateProblem(); + } + + ~OptimizedThermalGenerator() = default; +}; + +// start defining functions here! // Actually define them in *.cpp file +} + + bool GenerateRandomizedThermalTimeSeries(Data::Study& study, uint year, bool globalThermalTSgeneration, @@ -658,7 +706,7 @@ bool GenerateOptimizedThermalTimeSeries(Data::Study& study, logs.info() << "Generating optimized thermal time-series"; Solver::Progression::Task progression(study, year, Solver::Progression::sectTSGThermal); - auto generator = GeneratorTempData(study, progression, writer); + auto generator = OptimizedThermalGenerator(study, progression, writer); auto& repo = study.maintenanceGroups; const auto& groups = repo.activeMaintenanceGroups(); @@ -673,7 +721,8 @@ bool GenerateOptimizedThermalTimeSeries(Data::Study& study, for (const auto& entryGroup : group) { const auto& area = *(entryGroup.first); - // extract weights + // extract per area data: mnt-group weights, load, renewable and ror. + // calculate residual load array for (auto it = area.thermal.list.mapping.begin(); it != area.thermal.list.mapping.end(); ++it) { From 8c4da71138891590f8273fb7670c658f526f6c6e Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 8 Nov 2023 13:11:05 +0100 Subject: [PATCH 047/315] BIG TODO - TS number not available when ONLY running ts-gen --- src/solver/simulation/solver.hxx | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/solver/simulation/solver.hxx b/src/solver/simulation/solver.hxx index 49cb2e4827..c9f965512d 100644 --- a/src/solver/simulation/solver.hxx +++ b/src/solver/simulation/solver.hxx @@ -340,6 +340,18 @@ void ISimulation::run() // for a single simulation study.resizeAllTimeseriesNumbers(1 + study.runtime->rangeLimits.year[Data::rangeEnd]); // Now, we will prepare the time-series numbers + /* + TODO CR27: Just great! Time series numbers are available from here. + And we need them for average load, renewable and ror TS, Right? This is a big issue?! + So when we call regenerateTimeSeries(0) with settings.tsGeneratorsOnly = true. + We DO NOT have access to the random generated TS numbers for MC-years. + When we call loopThroughYears-> regenerateTimeSeries(set_it->yearForTSgeneration) + we DO HAVE access to the random generated TS numbers for MC-years. + (It still stands here that we call our new thermal ts-gen only once here - no refresh span) + Can we include TimeSeriesNumbers::Generate(study) when tsGeneratorsOnly = true && maintenancePlanning.isOptimized() + Just to be able to be able to calculate parameters for optimization problem?! + */ + if (not TimeSeriesNumbers::Generate(study)) { throw FatalError("An unrecoverable error has occured. Can not continue."); From 4ce680cbe62267a9c43bc1d53c047c42ceaebed6 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 8 Nov 2023 14:15:50 +0100 Subject: [PATCH 048/315] refactor OptimizedThermalGenerator - include repo inside the class --- src/solver/ts-generator/thermal.cpp | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/solver/ts-generator/thermal.cpp b/src/solver/ts-generator/thermal.cpp index 86c185f3a0..c4d189bf30 100644 --- a/src/solver/ts-generator/thermal.cpp +++ b/src/solver/ts-generator/thermal.cpp @@ -642,19 +642,27 @@ class OptimizedThermalGenerator : public GeneratorTempData void run(); // calls private optimization problem construction methods explicit OptimizedThermalGenerator(Data::Study& study, + uint year, Solver::Progression::Task& progr, IResultWriter& writer) : - GeneratorTempData(study, progr, writer) + GeneratorTempData(study, progr, writer), + repo(study.maintenanceGroups) { - // do something here - + currentYear = year; + nbThermalTimeseries = repo.scenariosNumber() * repo.scenariosLength(); // allocateProblem(); } ~OptimizedThermalGenerator() = default; + + // variables + Antares::Data::MaintenanceGroupRepository& repo; }; // start defining functions here! // Actually define them in *.cpp file + +#include "../../libs/antares/study/maintenance_planning/MaintenanceGroupRepository.h" +#include "../../libs/antares/study/maintenance_planning/MaintenanceGroup.h" } @@ -706,14 +714,9 @@ bool GenerateOptimizedThermalTimeSeries(Data::Study& study, logs.info() << "Generating optimized thermal time-series"; Solver::Progression::Task progression(study, year, Solver::Progression::sectTSGThermal); - auto generator = OptimizedThermalGenerator(study, progression, writer); - - auto& repo = study.maintenanceGroups; - const auto& groups = repo.activeMaintenanceGroups(); - - generator.currentYear = year; - generator.nbThermalTimeseries = repo.scenariosNumber() * repo.scenariosLength(); + auto generator = OptimizedThermalGenerator(study, year, progression, writer); + const auto& groups = generator.repo.activeMaintenanceGroups(); // TODO CR27: This part needs a lot of refactoring- to many nested loops!! for (const auto& entryGroups : groups) { From 641c6f6631ef6bbcca90c667fd7feae277c3b1fc Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 8 Nov 2023 19:05:21 +0100 Subject: [PATCH 049/315] set default weights to 1.0 --- .../antares/study/maintenance_planning/MaintenanceGroup.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroup.h b/src/libs/antares/study/maintenance_planning/MaintenanceGroup.h index a539e89634..83ea214d8d 100644 --- a/src/libs/antares/study/maintenance_planning/MaintenanceGroup.h +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroup.h @@ -67,9 +67,9 @@ class MaintenanceGroup : public Yuni::NonCopyable struct Weights final { - double load; - double renewable; - double ror; + double load = 1.0; + double renewable = 1.0; + double ror = 1.0; }; using MaintenanceGroupName = std::string; From d6da905838c41812f5f81cefdad0fe7308761d4e Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 8 Nov 2023 19:11:32 +0100 Subject: [PATCH 050/315] refactor MaintenanceGroupSaver --- .../maintenance_planning/MaintenanceGroupSaver.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroupSaver.cpp b/src/libs/antares/study/maintenance_planning/MaintenanceGroupSaver.cpp index 648da17769..1afc1a4506 100644 --- a/src/libs/antares/study/maintenance_planning/MaintenanceGroupSaver.cpp +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroupSaver.cpp @@ -31,9 +31,17 @@ bool MaintenanceGroupSaver::saveToEnv(EnvForSaving& env, const MaintenanceGroup* String value; const Area& area = *(i->first); - // add weight-load+renewable+ror - env.key.clear() << area.name << ".weights"; - value << i->second.load << '%' << i->second.renewable << '%' << i->second.ror; + // add weight-load + env.key.clear() << area.name << ".weight-load"; + value.clear() << i->second.load; + env.section->add(env.key, value); + // add weight-renewable + env.key.clear() << area.name << ".weight-renewable"; + value.clear() << i->second.renewable; + env.section->add(env.key, value); + // add weight-ror + env.key.clear() << area.name << ".weight-ror"; + value.clear() << i->second.ror; env.section->add(env.key, value); } } From 7d9918a1a2d49aff24a5903a4406f1036c279bc7 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 8 Nov 2023 19:11:54 +0100 Subject: [PATCH 051/315] refactor MaintenanceGroupLoader --- .../MaintenanceGroupLoader.cpp | 76 +++++++------------ .../MaintenanceGroupLoader.h | 4 +- 2 files changed, 27 insertions(+), 53 deletions(-) diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroupLoader.cpp b/src/libs/antares/study/maintenance_planning/MaintenanceGroupLoader.cpp index 226282d6c5..04b2aaa56a 100644 --- a/src/libs/antares/study/maintenance_planning/MaintenanceGroupLoader.cpp +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroupLoader.cpp @@ -47,21 +47,18 @@ std::vector> MaintenanceGroupLoader::load(EnvF continue; } - // initialize the values - MaintenanceGroup::Weights w = {0.0, 0.0, 0.0}; - - // Separate the key - auto setKey = p->key.find('.'); - if (0 == setKey || setKey == String::npos) + // Check if key is valid + std::string setKey = p->key.to(); + if (!((setKey.find(".weight-load") != std::string::npos) + || (setKey.find(".weight-renewable") != std::string::npos) + || (setKey.find(".weight-ror") != std::string::npos))) { logs.error() << env.iniFilename << ": in [" << env.section->name << "]: `" << p->key << "`: invalid key"; continue; } - if (bool ret = SeparateValue(env, p, w); !ret) - continue; - + // Separate the key const Area* area = env.areaList.findAreaFromINIKey(p->key); if (!area) { @@ -70,9 +67,19 @@ std::vector> MaintenanceGroupLoader::load(EnvF continue; } - mnt->loadWeight(area, w.load); - mnt->renewableWeight(area, w.renewable); - mnt->rorWeight(area, w.ror); + // Initialize the value + double val = 1; + if (bool ret = CheckValue(env, p, val); !ret) + continue; + + // check is it load, renewable or ror. + // It must be some of these because we already checked the validity of the key + if (setKey.find(".weight-load") != std::string::npos) + mnt->loadWeight(area, val); + else if (setKey.find(".weight-renewable") != std::string::npos) + mnt->renewableWeight(area, val); + else + mnt->rorWeight(area, val); } // Checking for validity @@ -98,53 +105,22 @@ std::vector> MaintenanceGroupLoader::load(EnvF return {mnt}; } -bool MaintenanceGroupLoader::SeparateValue(const EnvForLoading& env, - const IniFile::Property* p, - MaintenanceGroup::Weights& w) +bool MaintenanceGroupLoader::CheckValue(const EnvForLoading& env, + const IniFile::Property* p, + double& w) { - CString<64> string = p->value; - string.trim(); // trim - string.to(); - - // Split the string into parts based on '%' - std::vector parts; - std::istringstream ss(string); - std::string part; - while (std::getline(ss, part, '%')) - { - parts.push_back(part); - } - - // Check if there are exactly two parts - if (parts.size() != 3) - { - logs.error() << env.iniFilename << ": in [" << env.section->name << "]: `" << p->key - << "`: invalid number of weights"; - return false; - } - - // Convert each part to a double and report an error if conversion fails - double load, rnw, ror; - if (!(std::istringstream(parts[0]) >> load) || !(std::istringstream(parts[1]) >> rnw) - || !(std::istringstream(parts[2]) >> ror)) - { - logs.error() << env.iniFilename << ": in [" << env.section->name << "]: `" << p->key - << "`: one or more weights cannot be converted to numbers"; - return false; - } + double val = p->value.to(); // check if parsed numbers are between 0 and 1.0 - if (!(load >= 0.0 && load <= 1.0 && rnw >= 0.0 && rnw <= 1.0 && ror >= 0.0 && ror <= 1.0)) + if (!(val >= 0.0 && val <= 1.0)) { logs.error() << env.iniFilename << ": in [" << env.section->name << "]: `" << p->key - << "`: one or more weights are not in the [0, 1] range"; + << "`: weight is not in the [0, 1] range"; return false; } // Output the parsed numbers - w.load = load; - w.renewable = rnw; - w.ror = ror; + w = val; return true; } diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroupLoader.h b/src/libs/antares/study/maintenance_planning/MaintenanceGroupLoader.h index f633252b06..55cc20d3a7 100644 --- a/src/libs/antares/study/maintenance_planning/MaintenanceGroupLoader.h +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroupLoader.h @@ -19,9 +19,7 @@ class MaintenanceGroupLoader std::vector> load(EnvForLoading env); private: - static bool SeparateValue(const EnvForLoading& env, - const IniFile::Property* p, - MaintenanceGroup::Weights& w); + static bool CheckValue(const EnvForLoading& env, const IniFile::Property* p, double& w); std::string toLower(const std::string& str); }; From e7e02fc154a9bdc7d3443b1bc0678b67d7d652c9 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 8 Nov 2023 19:35:27 +0100 Subject: [PATCH 052/315] remove load/save scenario num/length from/to ini file --- .../MaintenanceGroupRepository.cpp | 73 +------------------ .../MaintenanceGroupRepository.h | 2 - 2 files changed, 2 insertions(+), 73 deletions(-) diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.cpp b/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.cpp index bd81bf3f51..db43962bff 100644 --- a/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.cpp +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.cpp @@ -100,62 +100,11 @@ std::vector> MaintenanceGroupRepository::LoadM return loader.load(std::move(env)); } -bool MaintenanceGroupRepository::internalLoadScenarioSettings(EnvForLoading env) -{ - // set path - env.iniFilename = env.folder << Yuni::IO::Separator << "scenariossettings.ini"; - // try to open ini file - IniFile ini; - if (!ini.open(env.iniFilename)) - { - logs.info() << " File: " << env.iniFilename << " Does not exists. Unsuccessful loading!"; - return false; - } - // see if there is any section - if (!ini.firstSection) - { - return true; - } - // see if the fist and only section is called "ScenariosSettings" - if (ini.firstSection->name != "ScenariosSettings") - { - return true; - } - // read the first section - env.section = ini.firstSection; - // check if section has properties - if (!env.section->firstProperty) - { - return true; - } - // loop through all properties - for (const IniFile::Property* p = env.section->firstProperty; p; p = p->next) - { - if (p->key.empty()) - continue; - - if (p->key == "number") - { - scenariosNumber(p->value.to()); - continue; - } - if (p->key == "length") - { - scenariosLength(p->value.to()); - continue; - } - } - return true; -} - bool MaintenanceGroupRepository::saveToFolder(const AnyString& folder) const { MaintenanceGroupSaver::EnvForSaving env; env.folder = folder; - bool ret = internalSaveToFolder(env); - env.folder = folder; - ret = internalSaveScenariosToFolder(env) && ret; - return ret; + return internalSaveToFolder(env); } bool MaintenanceGroupRepository::rename(MaintenanceGroup* mnt, const AnyString& newname) @@ -238,8 +187,7 @@ bool MaintenanceGroupRepository::loadFromFolder(Study& study, logs.info() << maintenanceGroups_.size() << " maintenance groups found"; } - env.folder = folder; - return internalLoadScenarioSettings(env); + return true; } bool MaintenanceGroupRepository::internalSaveToFolder( @@ -280,23 +228,6 @@ bool MaintenanceGroupRepository::internalSaveToFolder( return ini.save(env.folder) && ret; } -bool MaintenanceGroupRepository::internalSaveScenariosToFolder( - MaintenanceGroupSaver::EnvForSaving& env) const -{ - if (!Yuni::IO::Directory::Create(env.folder)) - return false; - - IniFile ini; - std::string text = "ScenariosSettings"; - - env.section = ini.addSection(text); - env.section->add("Number", scenariosNumber_); - env.section->add("Length", scenariosLength_); - - env.folder << Yuni::IO::Separator << "scenariossettings.ini"; - return ini.save(env.folder); -} - void MaintenanceGroupRepository::reverseWeightSign(const AreaLink* lnk) { } diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.h b/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.h index aa5d7bab3c..efd55160ee 100644 --- a/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.h +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.h @@ -159,8 +159,6 @@ class MaintenanceGroupRepository final : public Yuni::NonCopyable Date: Wed, 8 Nov 2023 20:05:37 +0100 Subject: [PATCH 053/315] avoid study crash - until we remove scenario MaintenanceGroupRepository --- .../study/maintenance_planning/MaintenanceGroupRepository.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.h b/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.h index efd55160ee..3c989a5390 100644 --- a/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.h +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.h @@ -154,8 +154,8 @@ class MaintenanceGroupRepository final : public Yuni::NonCopyable Date: Wed, 8 Nov 2023 20:06:02 +0100 Subject: [PATCH 054/315] add scenario to parameters --- src/libs/antares/study/parameters.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/libs/antares/study/parameters.h b/src/libs/antares/study/parameters.h index c09b9c9c05..02517e49ef 100644 --- a/src/libs/antares/study/parameters.h +++ b/src/libs/antares/study/parameters.h @@ -467,10 +467,17 @@ class Parameters final //! Maintenance Planning mode MaintenancePlanningModelling mpModelling; MaintenancePlanningModelling operator()() const; + uint scenarioNumber = 0; + uint scenarioLength = 0; void toRandomized(); void toOptimized(); bool isRandomized() const; bool isOptimized() const; + void setScenarioNumber(uint v); + void setScenarioLength(uint v); + uint getScenarioNumber() const; + uint getScenarioLength() const; + void clear(); }; MaintenancePlanning maintenancePlanning; From 93edd1698a59996f5b4d9d795f34dc8b86b7d804 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 8 Nov 2023 20:07:08 +0100 Subject: [PATCH 055/315] scenario num/length functions + create separate section --- src/libs/antares/study/parameters.cpp | 57 +++++++++++++++++++++++---- src/libs/antares/study/study.cpp | 2 +- 2 files changed, 50 insertions(+), 9 deletions(-) diff --git a/src/libs/antares/study/parameters.cpp b/src/libs/antares/study/parameters.cpp index 6c5ba86d02..a0451a436d 100644 --- a/src/libs/antares/study/parameters.cpp +++ b/src/libs/antares/study/parameters.cpp @@ -327,7 +327,8 @@ void Parameters::reset() unitCommitment.ucMode = ucHeuristicFast; nbCores.ncMode = ncAvg; renewableGeneration.rgModelling = rgAggregated; - maintenancePlanning.mpModelling = mpRandomized; + // maintenance Planning + maintenancePlanning.clear(); // Misc improveUnitsStartup = false; @@ -659,6 +660,18 @@ static bool SGDIntLoadFamily_AdqPatch(Parameters& d, return d.adqPatchParams.updateFromKeyValue(key, value); } +static bool SGDIntLoadFamily_MaintenancePlanning(Parameters& d, + const String& key, + const String& value, + const String&) +{ + // Maintenance planning modelling + if (key == "maintenance-planning-modelling") + return ConvertStringToMaintenancePlanningModelling(value, + d.maintenancePlanning.mpModelling); + return false; +} + static bool SGDIntLoadFamily_OtherPreferences(Parameters& d, const String& key, const String& value, @@ -761,11 +774,6 @@ static bool SGDIntLoadFamily_OtherPreferences(Parameters& d, return ConvertStringToRenewableGenerationModelling(value, d.renewableGeneration.rgModelling); - // Maintenance planning modelling - if (key == "maintenance-planning-modelling") - return ConvertStringToMaintenancePlanningModelling(value, - d.maintenancePlanning.mpModelling); - return false; } static bool SGDIntLoadFamily_AdvancedParameters(Parameters& d, @@ -995,6 +1003,7 @@ bool Parameters::loadFromINI(const IniFile& ini, uint version, const StudyLoadOp {"output", &SGDIntLoadFamily_Output}, {"optimization", &SGDIntLoadFamily_Optimization}, {"adequacy patch", &SGDIntLoadFamily_AdqPatch}, + {"maintenance planning", &SGDIntLoadFamily_MaintenancePlanning}, {"other preferences", &SGDIntLoadFamily_OtherPreferences}, {"advanced parameters", &SGDIntLoadFamily_AdvancedParameters}, {"playlist", &SGDIntLoadFamily_Playlist}, @@ -1627,6 +1636,13 @@ void Parameters::saveToINI(IniFile& ini) const // Adequacy patch adqPatchParams.saveToINI(ini); + // MaintenancePlanning + { + auto* section = ini.addSection("maintenance planning"); + section->add("maintenance-planning-modelling", + MaintenancePlanningModellingToCString(maintenancePlanning())); + } + // Other preferences { auto* section = ini.addSection("other preferences"); @@ -1641,8 +1657,6 @@ void Parameters::saveToINI(IniFile& ini) const section->add("number-of-cores-mode", NumberOfCoresModeToCString(nbCores.ncMode)); section->add("renewable-generation-modelling", RenewableGenerationModellingToCString(renewableGeneration())); - section->add("maintenance-planning-modelling", - MaintenancePlanningModellingToCString(maintenancePlanning())); } // Advanced parameters @@ -1849,6 +1863,33 @@ bool Parameters::MaintenancePlanning::isOptimized() const return mpModelling == Antares::Data::mpOptimized; } +void Parameters::MaintenancePlanning::setScenarioNumber(uint v) +{ + scenarioNumber = v; +} + +void Parameters::MaintenancePlanning::setScenarioLength(uint v) +{ + scenarioLength = v; +} + +uint Parameters::MaintenancePlanning::getScenarioNumber() const +{ + return scenarioNumber; +} + +uint Parameters::MaintenancePlanning::getScenarioLength() const +{ + return scenarioLength; +} + +void Parameters::MaintenancePlanning::clear() +{ + toRandomized(); + setScenarioNumber(0); + setScenarioLength(0); +} + // Some variables rely on dual values & marginal costs void Parameters::UCMode::addExcludedVariables(std::vector& out) const { diff --git a/src/libs/antares/study/study.cpp b/src/libs/antares/study/study.cpp index fc4acaf1ad..aa2c6d3e75 100644 --- a/src/libs/antares/study/study.cpp +++ b/src/libs/antares/study/study.cpp @@ -154,7 +154,7 @@ void Study::createAsNew() // Source) parameters.renewableGeneration.rgModelling = Antares::Data::rgClusters; // default mode for maintenancePlanning is Randomized - parameters.maintenancePlanning.mpModelling = Antares::Data::mpRandomized; + parameters.maintenancePlanning.clear(); parameters.yearsFilter = std::vector(1, true); From 0cf78c5b28fca9f2fc66de573a2b0d9df04c8519 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 8 Nov 2023 20:27:33 +0100 Subject: [PATCH 056/315] add scenario num & length to genera settings ini file --- src/libs/antares/study/parameters.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/libs/antares/study/parameters.cpp b/src/libs/antares/study/parameters.cpp index a0451a436d..0b5a43062b 100644 --- a/src/libs/antares/study/parameters.cpp +++ b/src/libs/antares/study/parameters.cpp @@ -661,14 +661,18 @@ static bool SGDIntLoadFamily_AdqPatch(Parameters& d, } static bool SGDIntLoadFamily_MaintenancePlanning(Parameters& d, - const String& key, - const String& value, - const String&) + const String& key, + const String& value, + const String&) { // Maintenance planning modelling if (key == "maintenance-planning-modelling") return ConvertStringToMaintenancePlanningModelling(value, d.maintenancePlanning.mpModelling); + if (key == "scenario-number") + return value.to(d.maintenancePlanning.scenarioNumber); + if (key == "scenario-length") + return value.to(d.maintenancePlanning.scenarioLength); return false; } @@ -1641,6 +1645,8 @@ void Parameters::saveToINI(IniFile& ini) const auto* section = ini.addSection("maintenance planning"); section->add("maintenance-planning-modelling", MaintenancePlanningModellingToCString(maintenancePlanning())); + section->add("scenario-number", maintenancePlanning.scenarioNumber); + section->add("scenario-length", maintenancePlanning.scenarioLength); } // Other preferences From 947bb2315f7148fed44bfdfad8bda43de1517f9d Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 8 Nov 2023 20:36:23 +0100 Subject: [PATCH 057/315] remove scenario num & length from MaintenanceGroupRepository --- .../MaintenanceGroupRepository.cpp | 2 -- .../MaintenanceGroupRepository.h | 18 ----------------- .../MaintenanceGroupRepository.hxx | 20 ------------------- src/solver/ts-generator/thermal.cpp | 5 +++-- 4 files changed, 3 insertions(+), 42 deletions(-) diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.cpp b/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.cpp index db43962bff..fb281918a9 100644 --- a/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.cpp +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.cpp @@ -16,8 +16,6 @@ void Data::MaintenanceGroupRepository::clear() { maintenanceGroups_.clear(); activeMaintenanceGroups_.reset(); - scenariosLength_ = 0; - scenariosNumber_ =0; } namespace Antares::Data diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.h b/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.h index 3c989a5390..4bdaf14dfd 100644 --- a/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.h +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.h @@ -137,26 +137,8 @@ class MaintenanceGroupRepository final : public Yuni::NonCopyable> activeMaintenanceGroups() const; - /*! - ** \brief The scenarios number and length - ** - ** \return Get the scenarios number and length - */ - uint scenariosNumber() const; - uint scenariosLength() const; - - /*! - ** \brief Set the scenarios number and length - */ - void scenariosNumber(uint num); - void scenariosLength(uint l); - private: - // number and length of the Maintenance Group-s scenarios - uint scenariosNumber_ = 1; - uint scenariosLength_ = 1; - // private methods bool internalSaveToFolder(Data::MaintenanceGroupSaver::EnvForSaving& env) const; diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.hxx b/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.hxx index e1683070bd..6f4a384967 100644 --- a/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.hxx +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroupRepository.hxx @@ -20,26 +20,6 @@ inline bool MaintenanceGroupRepository::empty() const return maintenanceGroups_.empty(); } -inline uint MaintenanceGroupRepository::scenariosNumber() const -{ - return scenariosNumber_; -} - -inline void MaintenanceGroupRepository::scenariosNumber(uint num) -{ - scenariosNumber_ = num; -} - -inline uint MaintenanceGroupRepository::scenariosLength() const -{ - return scenariosLength_; -} - -inline void MaintenanceGroupRepository::scenariosLength(uint l) -{ - scenariosLength_ = l; -} - template inline void MaintenanceGroupRepository::each(const PredicateT& predicate) { diff --git a/src/solver/ts-generator/thermal.cpp b/src/solver/ts-generator/thermal.cpp index c4d189bf30..e5ebfdf8d8 100644 --- a/src/solver/ts-generator/thermal.cpp +++ b/src/solver/ts-generator/thermal.cpp @@ -649,7 +649,8 @@ class OptimizedThermalGenerator : public GeneratorTempData repo(study.maintenanceGroups) { currentYear = year; - nbThermalTimeseries = repo.scenariosNumber() * repo.scenariosLength(); + nbThermalTimeseries = study.parameters.maintenancePlanning.getScenarioLength() + * study.parameters.maintenancePlanning.getScenarioNumber(); // allocateProblem(); } @@ -747,7 +748,7 @@ bool GenerateOptimizedThermalTimeSeries(Data::Study& study, assert(cluster.prepro); - if (0 == cluster.unitCount or 0 == cluster.nominalCapacity) + if (0 == cluster.unitCount or 0 == cluster.nominalCapacity or generator.nbThermalTimeseries == 0) { cluster.series.timeSeries.reset(1, 8760); } From e4d2813089b61294b72870eb57cacefc7d4bebc8 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Thu, 9 Nov 2023 09:37:32 +0100 Subject: [PATCH 058/315] add check if weight can properly be converted to double value in MaintenanceGroupLoader --- .../MaintenanceGroupLoader.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroupLoader.cpp b/src/libs/antares/study/maintenance_planning/MaintenanceGroupLoader.cpp index 04b2aaa56a..5f9012529d 100644 --- a/src/libs/antares/study/maintenance_planning/MaintenanceGroupLoader.cpp +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroupLoader.cpp @@ -109,9 +109,19 @@ bool MaintenanceGroupLoader::CheckValue(const EnvForLoading& env, const IniFile::Property* p, double& w) { - double val = p->value.to(); + // Convert to a double and report an error if conversion fails + auto stringValue = p->value.to(); + char* endptr; + strtod(stringValue.c_str(), &endptr); + if (!(*endptr == '\0')) + { + logs.error() << env.iniFilename << ": in [" << env.section->name << "]: `" << p->key + << "`: weight cannot be converted to number"; + return false; + } - // check if parsed numbers are between 0 and 1.0 + // check if number is between 0 and 1.0 + double val = p->value.to(); if (!(val >= 0.0 && val <= 1.0)) { logs.error() << env.iniFilename << ": in [" << env.section->name << "]: `" << p->key From 4aeb34e97dcde54504699cd70f85832e84bdea9a Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Thu, 9 Nov 2023 09:52:39 +0100 Subject: [PATCH 059/315] improve weight type check in MaintenanceGroupLoader (not only include but exact match) --- .../MaintenanceGroupLoader.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroupLoader.cpp b/src/libs/antares/study/maintenance_planning/MaintenanceGroupLoader.cpp index 5f9012529d..b5b48d3901 100644 --- a/src/libs/antares/study/maintenance_planning/MaintenanceGroupLoader.cpp +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroupLoader.cpp @@ -73,13 +73,20 @@ std::vector> MaintenanceGroupLoader::load(EnvF continue; // check is it load, renewable or ror. - // It must be some of these because we already checked the validity of the key - if (setKey.find(".weight-load") != std::string::npos) + auto offset = setKey.find("."); // It must be found because we already checked the validity of the key + std::string weightName(setKey.c_str() + offset + 1, setKey.size() - (offset + 1)); + if (weightName == "weight-load") mnt->loadWeight(area, val); - else if (setKey.find(".weight-renewable") != std::string::npos) + else if (weightName == "weight-renewable") mnt->renewableWeight(area, val); - else + else if (weightName == "weight-ror") mnt->rorWeight(area, val); + else + { + logs.error() << env.iniFilename << ": in [" << env.section->name << "]: `" << p->key + << "`: invalid key"; + continue; + } } // Checking for validity From 4af822b7b9c873fe8e7c6adfea82e53d87e308a9 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Thu, 9 Nov 2023 17:08:00 +0100 Subject: [PATCH 060/315] refactor OptimizedThermalGenerator & GenerateOptimizedThermalTimeSeries --- src/solver/ts-generator/thermal.cpp | 174 +++++++++++++++++++--------- 1 file changed, 117 insertions(+), 57 deletions(-) diff --git a/src/solver/ts-generator/thermal.cpp b/src/solver/ts-generator/thermal.cpp index e5ebfdf8d8..2cc3c351dc 100644 --- a/src/solver/ts-generator/thermal.cpp +++ b/src/solver/ts-generator/thermal.cpp @@ -76,6 +76,8 @@ class GeneratorTempData bool derated; + Solver::Progression::Task& pProgression; + // I need these two functions for inheritance void writeResultsToDisk(const Data::Area& area, const Data::ThermalCluster& cluster); int durationGenerator(Data::ThermalLaw law, int expec, double volat, double a, double b); @@ -114,7 +116,6 @@ class GeneratorTempData double PPOW[366][102]; String pTempFilename; - Solver::Progression::Task& pProgression; IResultWriter& pWriter; }; @@ -637,18 +638,30 @@ class OptimizedThermalGenerator : public GeneratorTempData void solveProblem(); void allocateProblem(); // this one should be called in constructor. It basically resets all the // vectors in PROBLEME_ANTARES_A_RESOUDRE for new opt problem. + + // some methods + void GenerateOptimizedThermalTimeSeriesPerOneMaintenanceGroup( + Antares::Data::MaintenanceGroup& group); + void calculateResidualLoad(Antares::Data::MaintenanceGroup& group); + void createOptimizationProblem(Antares::Data::MaintenanceGroup& group); + + // variables + Antares::Data::MaintenanceGroupRepository& maintenanceGroupRepo; + bool globalThermalTSgeneration_; public: void run(); // calls private optimization problem construction methods explicit OptimizedThermalGenerator(Data::Study& study, uint year, + bool globalThermalTSgeneration, Solver::Progression::Task& progr, IResultWriter& writer) : GeneratorTempData(study, progr, writer), - repo(study.maintenanceGroups) + maintenanceGroupRepo(study.maintenanceGroups) { currentYear = year; + globalThermalTSgeneration_ = globalThermalTSgeneration; nbThermalTimeseries = study.parameters.maintenancePlanning.getScenarioLength() * study.parameters.maintenancePlanning.getScenarioNumber(); // allocateProblem(); @@ -656,12 +669,109 @@ class OptimizedThermalGenerator : public GeneratorTempData ~OptimizedThermalGenerator() = default; - // variables - Antares::Data::MaintenanceGroupRepository& repo; + void GenerateOptimizedThermalTimeSeriesPerAllMaintenanceGroups(); }; // start defining functions here! // Actually define them in *.cpp file +void OptimizedThermalGenerator::GenerateOptimizedThermalTimeSeriesPerAllMaintenanceGroups() +{ + const auto& activeMaintenanceGroups = maintenanceGroupRepo.activeMaintenanceGroups(); + for (const auto& entryGroup : activeMaintenanceGroups) + { + auto& group = *(entryGroup.get()); + GenerateOptimizedThermalTimeSeriesPerOneMaintenanceGroup(group); + } +} + +void OptimizedThermalGenerator::GenerateOptimizedThermalTimeSeriesPerOneMaintenanceGroup( + Antares::Data::MaintenanceGroup& maintenanceGroup) +{ + calculateResidualLoad(maintenanceGroup); + createOptimizationProblem(maintenanceGroup); +} + +void OptimizedThermalGenerator::calculateResidualLoad(Antares::Data::MaintenanceGroup& maintenanceGroup) +{ + // dummy value for test + std::array values; + values.fill(2.5); + + // extract some info about the group + const std::string& groupName = maintenanceGroup.name(); + const auto& groupType = maintenanceGroup.type(); + const auto& groupResLoad = maintenanceGroup.getUsedResidualLoadTS(); + + // for phase II + if (groupType == Antares::Data::MaintenanceGroup::typeTimeserie) + { + // read user defined ts - userProvidedResidualLoadTS_ with getter - phase-II + maintenanceGroup.setUsedResidualLoadTS(values); + } + + // loop through the elements of weightMap weights_ + for (const auto& entryWeightMap : maintenanceGroup) + { + const auto& area = *(entryWeightMap.first); + auto weights = (entryWeightMap.second); + // we do not need to loop through clusters here + // per area data -> load, ror, renewable is all we need to calculate + // residual load TS + } + + // set resLoadTS + maintenanceGroup.setUsedResidualLoadTS(values); +} + +void OptimizedThermalGenerator::createOptimizationProblem(Antares::Data::MaintenanceGroup& maintenanceGroup) +{ + // loop through the elements of weightMap weights_ + for (const auto& entryWeightMap : maintenanceGroup) + { + const auto& area = *(entryWeightMap.first); + // loop through the thermal clusters inside the area + for (auto it = area.thermal.list.mapping.begin(); it != area.thermal.list.mapping.end(); + ++it) + { + auto& cluster = *(it->second); + if (cluster.doWeGenerateTS(globalThermalTSgeneration_) && cluster.optimizeMaintenance) + { + // just playing here - this needs to go into new method - class - operator + logs.info() << "CR27-INFO: This cluster is active for mnt planning: " + << cluster.getFullName(); + + if (!cluster.prepro) + { + logs.error() << "Cluster: " << area.name << '/' << cluster.name() + << ": The timeseries will not be regenerated. All data " + "related to the ts-generator for " + << "'thermal' have been released."; + } + + assert(cluster.prepro); + + if (0 == cluster.unitCount || 0 == cluster.nominalCapacity + || nbThermalTimeseries == 0) + { + cluster.series.timeSeries.reset(1, 8760); + } + else + { + cluster.series.timeSeries.reset(nbThermalTimeseries, 8760); + cluster.series.timeSeries.fill(777.); + } + + if (archive) + writeResultsToDisk(area, cluster); + + // end playing + } + + ++pProgression; + } + } +} + #include "../../libs/antares/study/maintenance_planning/MaintenanceGroupRepository.h" #include "../../libs/antares/study/maintenance_planning/MaintenanceGroup.h" } @@ -715,59 +825,9 @@ bool GenerateOptimizedThermalTimeSeries(Data::Study& study, logs.info() << "Generating optimized thermal time-series"; Solver::Progression::Task progression(study, year, Solver::Progression::sectTSGThermal); - auto generator = OptimizedThermalGenerator(study, year, progression, writer); - - const auto& groups = generator.repo.activeMaintenanceGroups(); - // TODO CR27: This part needs a lot of refactoring- to many nested loops!! - for (const auto& entryGroups : groups) - { - const auto& group = *(entryGroups.get()); - for (const auto& entryGroup : group) - { - const auto& area = *(entryGroup.first); - // extract per area data: mnt-group weights, load, renewable and ror. - // calculate residual load array - for (auto it = area.thermal.list.mapping.begin(); it != area.thermal.list.mapping.end(); - ++it) - { - auto& cluster = *(it->second); - if (cluster.doWeGenerateTS(globalThermalTSgeneration) - && cluster.optimizeMaintenance) - { - // just playing here - this needs to go into new method - class - operator - logs.info() << "CR27-INFO: This cluster is active for mnt planning: " - << cluster.getFullName(); - - if (!cluster.prepro) - { - logs.error() << "Cluster: " << area.name << '/' << cluster.name() - << ": The timeseries will not be regenerated. All data " - "related to the ts-generator for " - << "'thermal' have been released."; - } - - assert(cluster.prepro); - - if (0 == cluster.unitCount or 0 == cluster.nominalCapacity or generator.nbThermalTimeseries == 0) - { - cluster.series.timeSeries.reset(1, 8760); - } - else - { - cluster.series.timeSeries.reset(generator.nbThermalTimeseries, 8760); - cluster.series.timeSeries.fill(777.); - } - - if (generator.archive) - generator.writeResultsToDisk(area, cluster); - - // end playing - } - - ++progression; - } - } - } + auto generator + = OptimizedThermalGenerator(study, year, globalThermalTSgeneration, progression, writer); + generator.GenerateOptimizedThermalTimeSeriesPerAllMaintenanceGroups(); return true; } From c341d5e7c2cb7122f8a6daba12435469b92f7d1a Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Fri, 10 Nov 2023 10:44:49 +0100 Subject: [PATCH 061/315] further refactor OptimizedThermalGenerator & GenerateOptimizedThermalTimeSeries --- src/solver/ts-generator/thermal.cpp | 88 ++++++++++++++--------------- 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/src/solver/ts-generator/thermal.cpp b/src/solver/ts-generator/thermal.cpp index 2cc3c351dc..1445b99876 100644 --- a/src/solver/ts-generator/thermal.cpp +++ b/src/solver/ts-generator/thermal.cpp @@ -639,11 +639,11 @@ class OptimizedThermalGenerator : public GeneratorTempData void allocateProblem(); // this one should be called in constructor. It basically resets all the // vectors in PROBLEME_ANTARES_A_RESOUDRE for new opt problem. - // some methods + // some methods void GenerateOptimizedThermalTimeSeriesPerOneMaintenanceGroup( Antares::Data::MaintenanceGroup& group); void calculateResidualLoad(Antares::Data::MaintenanceGroup& group); - void createOptimizationProblem(Antares::Data::MaintenanceGroup& group); + void createOptimizationProblemPerCluster(const Data::Area& area, Data::ThermalCluster& cluster); // variables Antares::Data::MaintenanceGroupRepository& maintenanceGroupRepo; @@ -677,19 +677,13 @@ class OptimizedThermalGenerator : public GeneratorTempData void OptimizedThermalGenerator::GenerateOptimizedThermalTimeSeriesPerAllMaintenanceGroups() { const auto& activeMaintenanceGroups = maintenanceGroupRepo.activeMaintenanceGroups(); - for (const auto& entryGroup : activeMaintenanceGroups) + for (const auto& entryMaintenanceGroup : activeMaintenanceGroups) { - auto& group = *(entryGroup.get()); - GenerateOptimizedThermalTimeSeriesPerOneMaintenanceGroup(group); + auto& maintenanceGroup = *(entryMaintenanceGroup.get()); + calculateResidualLoad(maintenanceGroup); + GenerateOptimizedThermalTimeSeriesPerOneMaintenanceGroup(maintenanceGroup); } -} - -void OptimizedThermalGenerator::GenerateOptimizedThermalTimeSeriesPerOneMaintenanceGroup( - Antares::Data::MaintenanceGroup& maintenanceGroup) -{ - calculateResidualLoad(maintenanceGroup); - createOptimizationProblem(maintenanceGroup); -} +} void OptimizedThermalGenerator::calculateResidualLoad(Antares::Data::MaintenanceGroup& maintenanceGroup) { @@ -723,52 +717,57 @@ void OptimizedThermalGenerator::calculateResidualLoad(Antares::Data::Maintenance maintenanceGroup.setUsedResidualLoadTS(values); } -void OptimizedThermalGenerator::createOptimizationProblem(Antares::Data::MaintenanceGroup& maintenanceGroup) +void OptimizedThermalGenerator::GenerateOptimizedThermalTimeSeriesPerOneMaintenanceGroup( + Antares::Data::MaintenanceGroup& maintenanceGroup) { // loop through the elements of weightMap weights_ for (const auto& entryWeightMap : maintenanceGroup) { const auto& area = *(entryWeightMap.first); - // loop through the thermal clusters inside the area + // loop through the thermal clusters inside the area for (auto it = area.thermal.list.mapping.begin(); it != area.thermal.list.mapping.end(); ++it) { auto& cluster = *(it->second); - if (cluster.doWeGenerateTS(globalThermalTSgeneration_) && cluster.optimizeMaintenance) - { - // just playing here - this needs to go into new method - class - operator - logs.info() << "CR27-INFO: This cluster is active for mnt planning: " - << cluster.getFullName(); + createOptimizationProblemPerCluster(area, cluster); + ++pProgression; + } + } +} - if (!cluster.prepro) - { - logs.error() << "Cluster: " << area.name << '/' << cluster.name() - << ": The timeseries will not be regenerated. All data " - "related to the ts-generator for " - << "'thermal' have been released."; - } +void OptimizedThermalGenerator::createOptimizationProblemPerCluster(const Data::Area& area, + Data::ThermalCluster& cluster) +{ + if (cluster.doWeGenerateTS(globalThermalTSgeneration_) && cluster.optimizeMaintenance) + { + // just playing here - this needs to go into new method - class - operator + logs.info() << "CR27-INFO: This cluster is active for mnt planning: " + << cluster.getFullName(); - assert(cluster.prepro); + if (!cluster.prepro) + { + logs.error() << "Cluster: " << area.name << '/' << cluster.name() + << ": The timeseries will not be regenerated. All data " + "related to the ts-generator for " + << "'thermal' have been released."; + } - if (0 == cluster.unitCount || 0 == cluster.nominalCapacity - || nbThermalTimeseries == 0) - { - cluster.series.timeSeries.reset(1, 8760); - } - else - { - cluster.series.timeSeries.reset(nbThermalTimeseries, 8760); - cluster.series.timeSeries.fill(777.); - } + assert(cluster.prepro); - if (archive) - writeResultsToDisk(area, cluster); + if (0 == cluster.unitCount || 0 == cluster.nominalCapacity || nbThermalTimeseries == 0) + { + cluster.series.timeSeries.reset(1, 8760); + } + else + { + cluster.series.timeSeries.reset(nbThermalTimeseries, 8760); + cluster.series.timeSeries.fill(777.); + } - // end playing - } + if (archive) + writeResultsToDisk(area, cluster); - ++pProgression; - } + // end playing } } @@ -818,6 +817,7 @@ bool GenerateOptimizedThermalTimeSeries(Data::Study& study, { // optimized planning should only be called once. // Due to possible thermal refresh span we can end up here more than once - but just ignore it + // even if we set in Scenario playlist that year-1 should be skipped, we will execute this properly if (year != 0) return true; From c15a77f65ddfd1440f1e4087aa6d130ad2cc1680 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Fri, 10 Nov 2023 15:35:55 +0100 Subject: [PATCH 062/315] refactor - move OptimizedThermalGenerator to separate files --- src/solver/ts-generator/CMakeLists.txt | 20 + .../OptimizedGenerator.cpp | 107 +++ .../OptimizedGenerator.h | 68 ++ .../RandomizedGenerator.cpp | 512 ++++++++++++ .../RandomizedGenerator.h | 84 ++ src/solver/ts-generator/thermal.cpp | 754 +----------------- 6 files changed, 795 insertions(+), 750 deletions(-) create mode 100644 src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp create mode 100644 src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h create mode 100644 src/solver/ts-generator/randomized-thermal-generator/RandomizedGenerator.cpp create mode 100644 src/solver/ts-generator/randomized-thermal-generator/RandomizedGenerator.h diff --git a/src/solver/ts-generator/CMakeLists.txt b/src/solver/ts-generator/CMakeLists.txt index 2d0800f614..92830c170e 100644 --- a/src/solver/ts-generator/CMakeLists.txt +++ b/src/solver/ts-generator/CMakeLists.txt @@ -1,5 +1,23 @@ project(ts-generator) +# +# Randomized-thermal-ts-generator +# +set(SRC_RANDOMIZEDGENERATORS + randomized-thermal-generator/RandomizedGenerator.h + randomized-thermal-generator/RandomizedGenerator.cpp +) +source_group("ts-generator\\randomized-thermal-generator" FILES ${SRC_RANDOMIZEDGENERATORS}) + +# +# Optimized-thermal-ts-generator +# +set(SRC_OPTIMIZEDGENERATORS + optimized-thermal-generator/OptimizedGenerator.h + optimized-thermal-generator/OptimizedGenerator.cpp +) +source_group("ts-generator\\optimized-thermal-generator" FILES ${SRC_OPTIMIZEDGENERATORS}) + # # Time-Series Generators # @@ -38,6 +56,8 @@ source_group("ts-generator\\XCast" FILES ${SRC_XCAST}) # --- Library VARIABLES --- # add_library(antares-solver-ts-generator + ${SRC_RANDOMIZEDGENERATORS} + ${SRC_OPTIMIZEDGENERATORS} ${SRC_GENERATORS} ${SRC_XCAST}) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp new file mode 100644 index 0000000000..c99e390970 --- /dev/null +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp @@ -0,0 +1,107 @@ +// +// Created by milos on 10/11/23. +// + +#include "OptimizedGenerator.h" + +namespace Antares::Solver::TSGenerator +{ + +void OptimizedThermalGenerator::GenerateOptimizedThermalTimeSeriesPerAllMaintenanceGroups() +{ + const auto& activeMaintenanceGroups = maintenanceGroupRepo.activeMaintenanceGroups(); + for (const auto& entryMaintenanceGroup : activeMaintenanceGroups) + { + auto& maintenanceGroup = *(entryMaintenanceGroup.get()); + calculateResidualLoad(maintenanceGroup); + GenerateOptimizedThermalTimeSeriesPerOneMaintenanceGroup(maintenanceGroup); + } +} + +void OptimizedThermalGenerator::calculateResidualLoad(Data::MaintenanceGroup& maintenanceGroup) +{ + // dummy value for test + std::array values; + values.fill(2.5); + + // extract some info about the group + const std::string& groupName = maintenanceGroup.name(); + const auto& groupType = maintenanceGroup.type(); + const auto& groupResLoad = maintenanceGroup.getUsedResidualLoadTS(); + + // for phase II + if (groupType == Data::MaintenanceGroup::typeTimeserie) + { + // read user defined ts - userProvidedResidualLoadTS_ with getter - phase-II + maintenanceGroup.setUsedResidualLoadTS(values); + } + + // loop through the elements of weightMap weights_ + for (const auto& entryWeightMap : maintenanceGroup) + { + const auto& area = *(entryWeightMap.first); + auto weights = (entryWeightMap.second); + // we do not need to loop through clusters here + // per area data -> load, ror, renewable is all we need to calculate + // residual load TS + } + + // set resLoadTS + maintenanceGroup.setUsedResidualLoadTS(values); +} + +void OptimizedThermalGenerator::GenerateOptimizedThermalTimeSeriesPerOneMaintenanceGroup( + Data::MaintenanceGroup& maintenanceGroup) +{ + // loop through the elements of weightMap weights_ + for (const auto& entryWeightMap : maintenanceGroup) + { + const auto& area = *(entryWeightMap.first); + // loop through the thermal clusters inside the area + for (auto it = area.thermal.list.mapping.begin(); it != area.thermal.list.mapping.end(); + ++it) + { + auto& cluster = *(it->second); + createOptimizationProblemPerCluster(area, cluster); + ++pProgression; + } + } +} + +void OptimizedThermalGenerator::createOptimizationProblemPerCluster(const Data::Area& area, + Data::ThermalCluster& cluster) +{ + if (cluster.doWeGenerateTS(globalThermalTSgeneration_) && cluster.optimizeMaintenance) + { + // just playing here - this needs to go into new method - class - operator + logs.info() << "CR27-INFO: This cluster is active for mnt planning: " + << cluster.getFullName(); + + if (!cluster.prepro) + { + logs.error() << "Cluster: " << area.name << '/' << cluster.name() + << ": The timeseries will not be regenerated. All data " + "related to the ts-generator for " + << "'thermal' have been released."; + } + + assert(cluster.prepro); + + if (0 == cluster.unitCount || 0 == cluster.nominalCapacity || nbThermalTimeseries == 0) + { + cluster.series.timeSeries.reset(1, 8760); + } + else + { + cluster.series.timeSeries.reset(nbThermalTimeseries, 8760); + cluster.series.timeSeries.fill(777.); + } + + if (archive) + writeResultsToDisk(area, cluster); + + // end playing + } +} + +} // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h new file mode 100644 index 0000000000..b33138be91 --- /dev/null +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -0,0 +1,68 @@ +// +// Created by milos on 10/11/23. +// + +#pragma once + +#include "../randomized-thermal-generator/RandomizedGenerator.h" +#include "../../../libs/antares/study/maintenance_planning/MaintenanceGroupRepository.h" +#include "../../../libs/antares/study/maintenance_planning/MaintenanceGroup.h" + +namespace Antares::Solver::TSGenerator +{ + +class OptimizedThermalGenerator : public GeneratorTempData +{ +private: + /* + in adq-patch we re-used existing structure(s) for helping us define an optimization problem -> + like: struct CORRESPONDANCES_DES_VARIABLES. + unfortunately here we have to create our own help-structure if we need one + Question: can we still use struct PROBLEME_ANTARES_A_RESOUDRE ?! - no we use MPSolver class + */ + + // define here variables/structures that will help us build optimization problem + + // optimization problem construction methods + void calculateParameters(); + void buildProblemVariables(); + void setVariableBounds(); + void buildProblemConstraintsLHS(); + void buildProblemConstraintsRHS(); + void setProblemCost(); + void solveProblem(); + void allocateProblem(); // this one should be called in constructor. It basically resets all the + // vectors in PROBLEME_ANTARES_A_RESOUDRE for new opt problem. + + // some methods + void GenerateOptimizedThermalTimeSeriesPerOneMaintenanceGroup(Data::MaintenanceGroup& group); + void calculateResidualLoad(Data::MaintenanceGroup& group); + void createOptimizationProblemPerCluster(const Data::Area& area, Data::ThermalCluster& cluster); + + // variables + Data::MaintenanceGroupRepository& maintenanceGroupRepo; + bool globalThermalTSgeneration_; + +public: + void run(); // calls private optimization problem construction methods + + explicit OptimizedThermalGenerator(Data::Study& study, + uint year, + bool globalThermalTSgeneration, + Solver::Progression::Task& progr, + IResultWriter& writer) : + GeneratorTempData(study, progr, writer), maintenanceGroupRepo(study.maintenanceGroups) + { + currentYear = year; + globalThermalTSgeneration_ = globalThermalTSgeneration; + nbThermalTimeseries = study.parameters.maintenancePlanning.getScenarioLength() + * study.parameters.maintenancePlanning.getScenarioNumber(); + // allocateProblem(); + } + + ~OptimizedThermalGenerator() = default; + + void GenerateOptimizedThermalTimeSeriesPerAllMaintenanceGroups(); +}; + +} // namespace Antares::Solver::TSGenerator \ No newline at end of file diff --git a/src/solver/ts-generator/randomized-thermal-generator/RandomizedGenerator.cpp b/src/solver/ts-generator/randomized-thermal-generator/RandomizedGenerator.cpp new file mode 100644 index 0000000000..286d7a49e4 --- /dev/null +++ b/src/solver/ts-generator/randomized-thermal-generator/RandomizedGenerator.cpp @@ -0,0 +1,512 @@ +// // +// // Created by milos on 10/11/23. +// // + +#include "../../simulation/sim_extern_variables_globales.h" +#include "RandomizedGenerator.h" + +using namespace Yuni; + +namespace Antares::Solver::TSGenerator +{ + +GeneratorTempData::GeneratorTempData(Data::Study& study, + Solver::Progression::Task& progr, + IResultWriter& writer) : + study(study), + rndgenerator(study.runtime->random[Data::seedTsGenThermal]), + pProgression(progr), + pWriter(writer) +{ + auto& parameters = study.parameters; + + archive = (0 + != (parameters.timeSeriesToArchive + & Data::timeSeriesThermal)); + + nbThermalTimeseries + = parameters.nbTimeSeriesThermal; + + derated = parameters.derated; +} + +void GeneratorTempData::writeResultsToDisk(const Data::Area& area, + const Data::ThermalCluster& cluster) +{ + if (not study.parameters.noOutput) + { + pTempFilename.reserve(study.folderOutput.size() + 256); + + pTempFilename.clear() << "ts-generator" << SEP << "thermal" << SEP << "mc-" << currentYear + << SEP << area.id << SEP << cluster.id() << ".txt"; + + enum + { + precision = 0 + }; + + std::string buffer; + cluster.series.timeSeries.saveToBuffer(buffer, precision); + + pWriter.addEntryFromBuffer(pTempFilename.c_str(), buffer); + } + + ++pProgression; +} + +template +void GeneratorTempData::prepareIndispoFromLaw(Data::ThermalLaw law, + double volatility, + double A[], + double B[], + const T& duration) +{ + switch (law) + { + case Data::thermalLawUniform: + { + for (uint d = 0; d < daysPerYear; ++d) + { + double D = (double)duration[d]; + double xtemp = volatility * (D - 1.); + A[d] = D - xtemp; + B[d] = 2. * xtemp + 1.; + } + break; + } + case Data::thermalLawGeometric: + { + for (uint d = 0; d < daysPerYear; ++d) + { + double D = (double)duration[d]; + double xtemp = volatility * volatility * D * (D - 1.); + if (xtemp != 0) + { + B[d] = 4. * xtemp + 1.; + B[d] = sqrt(B[d]) - 1.; + B[d] /= 2. * xtemp; + A[d] = D - 1. / B[d]; + B[d] = log(1. - B[d]); + B[d] = 1. / B[d]; + } + else + { + B[d] = 1.; + A[d] = 1.; + } + } + break; + } + } +} + +int GeneratorTempData::durationGenerator( + Data::ThermalLaw law, + int expec, + double volat, + double a, + double b) +{ + if (volat == 0 or expec == 1) + return expec; + + double rndnumber = rndgenerator.next(); + switch (law) + { + case Data::thermalLawUniform: + { + return (int(a + rndnumber * b)); + } + case Data::thermalLawGeometric: + { + int resultat = (1 + int(a + (b)*log(rndnumber))); + enum + { + limit = Log_size / 2 - 1 + }; + assert(limit == 1999); + return (resultat <= limit) ? resultat : limit; + } + } + assert(false and "return is missing"); + return 0; +} + +void GeneratorTempData::operator()(Data::Area& area, + Data::ThermalCluster& cluster) +{ + if (not cluster.prepro) + { + logs.error() + << "Cluster: " << area.name << '/' << cluster.name() + << ": The timeseries will not be regenerated. All data related to the ts-generator for " + << "'thermal' have been released."; + return; + } + + assert(cluster.prepro); + + if (0 == cluster.unitCount or 0 == cluster.nominalCapacity) + { + cluster.series.timeSeries.reset( + 1, nbHoursPerYear); + + if (archive) + writeResultsToDisk(area, cluster); + return; + } + + cluster.series.timeSeries.resize(nbThermalTimeseries, + nbHoursPerYear); + + const auto& preproData = *(cluster.prepro); + + int AUN = (int)cluster.unitCount; + + auto& FOD = preproData.data[Data::PreproThermal::foDuration]; + + auto& POD = preproData.data[Data::PreproThermal::poDuration]; + + auto& FOR = preproData.data[Data::PreproThermal::foRate]; + + auto& POR = preproData.data[Data::PreproThermal::poRate]; + + auto& NPOmin = preproData.data[Data::PreproThermal::npoMin]; + + auto& NPOmax = preproData.data[Data::PreproThermal::npoMax]; + + double f_volatility = cluster.forcedVolatility; + + double p_volatility = cluster.plannedVolatility; + + auto f_law = cluster.forcedLaw; + + auto p_law = cluster.plannedLaw; + + int FODOfTheDay; + int PODOfTheDay; + + int FOD_reel = 0; + int POD_reel = 0; + + for (uint d = 0; d < daysPerYear; ++d) + { + PODOfTheDay = (int)POD[d]; + FODOfTheDay = (int)FOD[d]; + + lf[d] = FOR[d] / (FOR[d] + (FODOfTheDay) * (1. - FOR[d])); + lp[d] = POR[d] / (POR[d] + (PODOfTheDay) * (1. - POR[d])); + + if (0. < lf[d] and lf[d] < lp[d]) + lf[d] *= (1. - lp[d]) / (1. - lf[d]); + + if (0. < lp[d] and lp[d] < lf[d]) + lp[d] *= (1. - lf[d]) / (1. - lp[d]); + + double a = 0.; + double b = 0.; + + if (lf[d] <= FAILURE_RATE_EQ_1) + { + a = 1. - lf[d]; + ff[d] = lf[d] / a; + } + + if (lp[d] <= FAILURE_RATE_EQ_1) + { + b = 1. - lp[d]; + pp[d] = lp[d] / b; + } + + for (uint k = 0; k != cluster.unitCount + 1; ++k) + { + FPOW[d][k] = pow(a, (double)k); + PPOW[d][k] = pow(b, (double)k); + } + } + + prepareIndispoFromLaw(f_law, f_volatility, af, bf, FOD); + prepareIndispoFromLaw(p_law, p_volatility, ap, bp, POD); + + (void)::memset(AVP, 0, sizeof(AVP)); + (void)::memset(LOG, 0, sizeof(LOG)); + (void)::memset(LOGP, 0, sizeof(LOGP)); + + int MXO = 0; + + int PPO = 0; + + int PFO = 0; + + int NOW = 0; + + int FUT = 0; + + int NPO_cur = 0; + + int stock = 0; + + double A = 0; + double cumul = 0; + double last = 0; + + auto& modulation = cluster.modulation[Data::thermalModulationCapacity]; + + double* dstSeries = nullptr; + + const uint tsCount = nbThermalTimeseries + 2; + for (uint tsIndex = 0; tsIndex != tsCount; ++tsIndex) + { + uint hour = 0; + + if (tsIndex > 1) + dstSeries = cluster.series.timeSeries[tsIndex - 2]; + + for (uint dayInTheYear = 0; dayInTheYear < daysPerYear; ++dayInTheYear) + { + assert(AUN <= 100 and "Thermal Prepro: AUN is out of bounds (>=100)"); + assert(dayInTheYear < 366); + assert(not(lf[dayInTheYear] < 0.)); + assert(not(lp[dayInTheYear] < 0.)); + + PODOfTheDay = (int)POD[dayInTheYear]; + FODOfTheDay = (int)FOD[dayInTheYear]; + + assert(NOW < Log_size); + NPO_cur -= LOGP[NOW]; + LOGP[NOW] = 0; + AUN += LOG[NOW]; + LOG[NOW] = 0; + + if (NPO_cur > NPOmax[dayInTheYear]) + { + int cible_retour = NPO_cur - (int)NPOmax[dayInTheYear]; + + int cumul_retour = 0; + + for (int index = 1; index < Log_size; ++index) + { + if (cumul_retour == cible_retour) + break; + + if (LOGP[(NOW + index) % Log_size] + cumul_retour >= cible_retour) + { + LOGP[(NOW + index) % Log_size] -= (cible_retour - cumul_retour); + + LOG[(NOW + index) % Log_size] -= (cible_retour - cumul_retour); + + cumul_retour = cible_retour; + } + else + { + if (LOGP[(NOW + index) % Log_size] > 0) + { + cumul_retour += LOGP[(NOW + index) % Log_size]; + + LOG[(NOW + index) % Log_size] -= LOGP[(NOW + index) % Log_size]; + + LOGP[(NOW + index) % Log_size] = 0; + } + } + } + + AUN += cible_retour; + NPO_cur = (int)NPOmax[dayInTheYear]; + } + + int FOC = 0; + + int POC = 0; + + if (lf[dayInTheYear] > 0. and lf[dayInTheYear] <= FAILURE_RATE_EQ_1) + { + A = rndgenerator.next(); + last = FPOW[dayInTheYear][AUN]; + + if (A > last) + { + cumul = last; + for (int d = 1; d < AUN + 1; ++d) + { + last = ((last * ff[dayInTheYear]) * ((double)(AUN + 1. - d))) / (double)d; + cumul += last; + FOC = d; + if (A <= cumul) + break; + } + } + } + else + { + FOC = (lf[dayInTheYear] > 0.) ? AUN : 0; + } + + if (lp[dayInTheYear] > 0. and lp[dayInTheYear] <= FAILURE_RATE_EQ_1) + { + int AUN_app = AUN; + if (stock >= 0 and stock <= AUN) + AUN_app -= stock; + if (stock > AUN) + AUN_app = 0; + + last = PPOW[dayInTheYear][AUN_app]; + A = rndgenerator.next(); + + if (A > last) + { + cumul = last; + for (int d = 1; d < AUN_app + 1; ++d) + { + last + = ((last * pp[dayInTheYear]) * ((double)(AUN_app + 1. - d))) / (double)d; + cumul += last; + POC = d; + if (A <= cumul) + break; + } + } + } + else + { + POC = (lp[dayInTheYear] > 0.) ? AUN : 0; + } + + int candidat = POC + stock; + if (0 <= candidat and candidat <= AUN) + { + POC = candidat; + + stock = 0; + } + if (candidat > AUN) + { + stock = candidat - AUN; + + POC = AUN; + } + if (candidat < 0) + { + stock = candidat; + + POC = 0; + } + + if (POC + NPO_cur > NPOmax[dayInTheYear]) + { + stock += POC + NPO_cur - (int)NPOmax[dayInTheYear]; + + POC = (int)NPOmax[dayInTheYear] - NPO_cur; + + NPO_cur = (int)NPOmax[dayInTheYear]; + } + else + { + if (POC + NPO_cur < NPOmin[dayInTheYear]) + { + if (NPOmin[dayInTheYear] - NPO_cur > AUN) + { + stock -= (AUN - POC); + + POC = AUN; + NPO_cur += POC; + } + else + { + stock -= (int)NPOmin[dayInTheYear] - (POC + NPO_cur); + + POC = (int)NPOmin[dayInTheYear] - NPO_cur; + + NPO_cur = (int)NPOmin[dayInTheYear]; + } + } + else + { + NPO_cur += POC; + } + } + + if (cluster.unitCount == 1) + { + if (POC == 1 and FOC == 1) + { + PPO = 0; + PFO = 0; + MXO = 1; + } + else + { + MXO = 0; + PFO = FOC; + PPO = POC; + } + } + else + { + if (AUN != 0) + { + MXO = POC * FOC / AUN; + PPO = POC - MXO; + PFO = FOC - MXO; + } + else + { + MXO = 0; + PPO = 0; + PFO = 0; + } + } + + AUN = AUN - (PPO + PFO + MXO); + + if (PFO != 0 or MXO != 0) + FOD_reel = durationGenerator( + f_law, FODOfTheDay, f_volatility, af[dayInTheYear], bf[dayInTheYear]); + if (PPO != 0 or MXO != 0) + POD_reel = durationGenerator( + p_law, PODOfTheDay, p_volatility, ap[dayInTheYear], bp[dayInTheYear]); + + assert(FUT < Log_size); + if (PFO != 0) + { + FUT = (NOW + FOD_reel) % Log_size; + LOG[FUT] += PFO; + } + if (PPO != 0) + { + FUT = (NOW + POD_reel) % Log_size; + LOG[FUT] += PPO; + LOGP[FUT] = LOGP[FUT] + PPO; + } + if (MXO != 0) + { + FUT = (NOW + POD_reel + FOD_reel) % Log_size; + LOG[FUT] += MXO; + LOGP[FUT] = LOGP[FUT] + MXO; + } + NOW = (NOW + 1) % Log_size; + + AVP[dayInTheYear] = AUN * cluster.nominalCapacity; + + if (tsIndex > 1) + { + double AVPDayInTheYear = AVP[dayInTheYear]; + for (uint h = 0; h != 24; ++h) + { + dstSeries[hour] = Math::Round( + AVPDayInTheYear * modulation[hour]); + ++hour; + } + } + } + } + + if (derated) // TMP.INFO CR27: derated mode - averaging - keep it like this! + cluster.series.timeSeries.averageTimeseries(); + + if (archive) + writeResultsToDisk(area, cluster); + + cluster.calculationOfSpinning(); // TODO CR27 // do we still need to call this function?! +} + +} // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/randomized-thermal-generator/RandomizedGenerator.h b/src/solver/ts-generator/randomized-thermal-generator/RandomizedGenerator.h new file mode 100644 index 0000000000..c77f44fe32 --- /dev/null +++ b/src/solver/ts-generator/randomized-thermal-generator/RandomizedGenerator.h @@ -0,0 +1,84 @@ +// +// Created by milos on 10/11/23. +// +#pragma once + +#include "../../simulation/sim_extern_variables_globales.h" + +using namespace Yuni; + +#define SEP IO::Separator + +#define FAILURE_RATE_EQ_1 0.999 + +namespace Antares::Solver::TSGenerator +{ + +class GeneratorTempData +{ +public: + GeneratorTempData(Data::Study& study, + Solver::Progression::Task& progr, + IResultWriter& writer); + + void prepareOutputFoldersForAllAreas(uint year); + + void operator()(Data::Area& area, Data::ThermalCluster& cluster); + +public: + Data::Study& study; + + bool archive; + + uint currentYear; + + uint nbThermalTimeseries; + + bool derated; + + Solver::Progression::Task& pProgression; + + // I need these two functions for inheritance + void writeResultsToDisk(const Data::Area& area, const Data::ThermalCluster& cluster); + int durationGenerator(Data::ThermalLaw law, int expec, double volat, double a, double b); + +private: + template + void prepareIndispoFromLaw(Data::ThermalLaw law, + double volatility, + double A[], + double B[], + const T& duration); + +private: + const uint nbHoursPerYear = HOURS_PER_YEAR; + const uint daysPerYear = DAYS_PER_YEAR; + + MersenneTwister& rndgenerator; + + double AVP[366]; + enum + { + Log_size = 4000 + }; + int LOG[Log_size]; + int LOGP[Log_size]; + + double lf[366]; + double lp[366]; + double ff[366]; + double pp[366]; + double af[366]; + double ap[366]; + double bf[366]; + double bp[366]; + double FPOW[366][102]; + double PPOW[366][102]; + + String pTempFilename; + IResultWriter& pWriter; +}; + +} // namespace Antares::Solver::TSGenerator + +// #endif // OPTIMIZED_GENERATOR_H \ No newline at end of file diff --git a/src/solver/ts-generator/thermal.cpp b/src/solver/ts-generator/thermal.cpp index 1445b99876..fd25b0fa66 100644 --- a/src/solver/ts-generator/thermal.cpp +++ b/src/solver/ts-generator/thermal.cpp @@ -25,756 +25,12 @@ ** SPDX-License-Identifier: licenceRef-GPL3_WITH_RTE-Exceptions */ -#include - -#include -#include -#include - -#include -#include -#include - -#include "../simulation/simulation.h" -#include "../simulation/sim_structure_donnees.h" -#include "../simulation/sim_structure_probleme_economique.h" #include "../simulation/sim_extern_variables_globales.h" +#include "randomized-thermal-generator/RandomizedGenerator.h" +#include "optimized-thermal-generator/OptimizedGenerator.h" -using namespace Yuni; - -#define SEP IO::Separator - -#define FAILURE_RATE_EQ_1 0.999 - -namespace Antares -{ -namespace Solver -{ -namespace TSGenerator -{ -namespace -{ -class GeneratorTempData -{ -public: - GeneratorTempData(Data::Study& study, - Solver::Progression::Task& progr, - IResultWriter& writer); - - void prepareOutputFoldersForAllAreas(uint year); // TMP.INFO CR27: not used at all - - void operator()(Data::Area& area, Data::ThermalCluster& cluster); // TMP.INFO CR27: called as (*generator)(area, cluster); - -public: - Data::Study& study; - - bool archive; // TMP.INFO CR27: whether to write it in txt or not! - - uint currentYear; - - uint nbThermalTimeseries; - - bool derated; - - Solver::Progression::Task& pProgression; - - // I need these two functions for inheritance - void writeResultsToDisk(const Data::Area& area, const Data::ThermalCluster& cluster); - int durationGenerator(Data::ThermalLaw law, int expec, double volat, double a, double b); - -private: - template - void prepareIndispoFromLaw(Data::ThermalLaw law, - double volatility, - double A[], - double B[], - const T& duration); - -private: - const uint nbHoursPerYear = HOURS_PER_YEAR; - const uint daysPerYear = DAYS_PER_YEAR; - - MersenneTwister& rndgenerator; - - double AVP[366]; - enum - { - Log_size = 4000 - }; - int LOG[Log_size]; - int LOGP[Log_size]; - - double lf[366]; - double lp[366]; - double ff[366]; - double pp[366]; - double af[366]; - double ap[366]; - double bf[366]; - double bp[366]; - double FPOW[366][102]; - double PPOW[366][102]; - - String pTempFilename; - IResultWriter& pWriter; -}; - -GeneratorTempData::GeneratorTempData(Data::Study& study, - Solver::Progression::Task& progr, - IResultWriter& writer) : - study(study), - rndgenerator(study.runtime->random[Data::seedTsGenThermal]), - pProgression(progr), - pWriter(writer) -{ - auto& parameters = study.parameters; - - archive = (0 != (parameters.timeSeriesToArchive & Data::timeSeriesThermal)); // TMP.INFO CR27: save to txt or not! - - nbThermalTimeseries = parameters.nbTimeSeriesThermal; // TMP.INFO CR27: this will be changed - and will be sc-num x sc-length - best to change it here - not to mess with importing the actual number in the simulator - - derated = parameters.derated; -} - -void GeneratorTempData::writeResultsToDisk(const Data::Area& area, // I want to inherit this method - const Data::ThermalCluster& cluster) -{ - if (not study.parameters.noOutput) - { - pTempFilename.reserve(study.folderOutput.size() + 256); - - pTempFilename.clear() << "ts-generator" << SEP << "thermal" << SEP << "mc-" << currentYear - << SEP << area.id << SEP << cluster.id() << ".txt"; - - enum - { - precision = 0 - }; - - std::string buffer; - cluster.series.timeSeries.saveToBuffer(buffer, precision); - - pWriter.addEntryFromBuffer(pTempFilename.c_str(), buffer); - } - - ++pProgression; -} - -template -void GeneratorTempData::prepareIndispoFromLaw(Data::ThermalLaw law, - double volatility, - double A[], - double B[], - const T& duration) -{ - switch (law) - { - case Data::thermalLawUniform: - { - for (uint d = 0; d < daysPerYear; ++d) - { - double D = (double)duration[d]; - double xtemp = volatility * (D - 1.); - A[d] = D - xtemp; - B[d] = 2. * xtemp + 1.; - } - break; - } - case Data::thermalLawGeometric: - { - for (uint d = 0; d < daysPerYear; ++d) - { - double D = (double)duration[d]; - double xtemp = volatility * volatility * D * (D - 1.); - if (xtemp != 0) - { - B[d] = 4. * xtemp + 1.; - B[d] = sqrt(B[d]) - 1.; - B[d] /= 2. * xtemp; - A[d] = D - 1. / B[d]; - B[d] = log(1. - B[d]); - B[d] = 1. / B[d]; - } - else - { - B[d] = 1.; - A[d] = 1.; - } - } - break; - } - } -} - -int GeneratorTempData::durationGenerator(Data::ThermalLaw law, // TMP.INFO CR27: use this for mnt duration ?! I want to inherit this method - int expec, - double volat, - double a, - double b) -{ - if (volat == 0 or expec == 1) - return expec; - - double rndnumber = rndgenerator.next(); - switch (law) - { - case Data::thermalLawUniform: - { - return (int(a + rndnumber * b)); - } - case Data::thermalLawGeometric: - { - int resultat = (1 + int(a + (b)*log(rndnumber))); - enum - { - limit = Log_size / 2 - 1 - }; - assert(limit == 1999); - return (resultat <= limit) ? resultat : limit; - } - } - assert(false and "return is missing"); - return 0; -} - -void GeneratorTempData::operator()(Data::Area& area, Data::ThermalCluster& cluster) // TMP.INFO CR27: calling operator -{ - if (not cluster.prepro) - { - logs.error() - << "Cluster: " << area.name << '/' << cluster.name() - << ": The timeseries will not be regenerated. All data related to the ts-generator for " - << "'thermal' have been released."; - return; - } - - assert(cluster.prepro); - - if (0 == cluster.unitCount or 0 == cluster.nominalCapacity) - { - cluster.series.timeSeries.reset(1, nbHoursPerYear); // TMP.INFO CR27: still ok - keep it like this // actually add clusters not in any mnt-group to behave like this!! - - if (archive) - writeResultsToDisk(area, cluster); - return; - } - - cluster.series.timeSeries.resize(nbThermalTimeseries, nbHoursPerYear); // TMP.INFO CR27: re-size here! - - const auto& preproData = *(cluster.prepro); - - int AUN = (int)cluster.unitCount; - - auto& FOD = preproData.data[Data::PreproThermal::foDuration]; - - auto& POD = preproData.data[Data::PreproThermal::poDuration]; - - auto& FOR = preproData.data[Data::PreproThermal::foRate]; - - auto& POR = preproData.data[Data::PreproThermal::poRate]; - - auto& NPOmin = preproData.data[Data::PreproThermal::npoMin]; - - auto& NPOmax = preproData.data[Data::PreproThermal::npoMax]; - - double f_volatility = cluster.forcedVolatility; - - double p_volatility = cluster.plannedVolatility; - - auto f_law = cluster.forcedLaw; - - auto p_law = cluster.plannedLaw; - - int FODOfTheDay; - int PODOfTheDay; - - int FOD_reel = 0; - int POD_reel = 0; - - for (uint d = 0; d < daysPerYear; ++d) - { - PODOfTheDay = (int)POD[d]; - FODOfTheDay = (int)FOD[d]; - - lf[d] = FOR[d] / (FOR[d] + (FODOfTheDay) * (1. - FOR[d])); - lp[d] = POR[d] / (POR[d] + (PODOfTheDay) * (1. - POR[d])); - - if (0. < lf[d] and lf[d] < lp[d]) - lf[d] *= (1. - lp[d]) / (1. - lf[d]); - - if (0. < lp[d] and lp[d] < lf[d]) - lp[d] *= (1. - lf[d]) / (1. - lp[d]); - - double a = 0.; - double b = 0.; - - if (lf[d] <= FAILURE_RATE_EQ_1) - { - a = 1. - lf[d]; - ff[d] = lf[d] / a; - } - - if (lp[d] <= FAILURE_RATE_EQ_1) - { - b = 1. - lp[d]; - pp[d] = lp[d] / b; - } - - for (uint k = 0; k != cluster.unitCount + 1; ++k) - { - FPOW[d][k] = pow(a, (double)k); - PPOW[d][k] = pow(b, (double)k); - } - } - - prepareIndispoFromLaw(f_law, f_volatility, af, bf, FOD); - prepareIndispoFromLaw(p_law, p_volatility, ap, bp, POD); - - (void)::memset(AVP, 0, sizeof(AVP)); - (void)::memset(LOG, 0, sizeof(LOG)); - (void)::memset(LOGP, 0, sizeof(LOGP)); - - int MXO = 0; - - int PPO = 0; - - int PFO = 0; - - int NOW = 0; - - int FUT = 0; - - int NPO_cur = 0; - - int stock = 0; - - double A = 0; - double cumul = 0; - double last = 0; - - auto& modulation = cluster.modulation[Data::thermalModulationCapacity]; - - double* dstSeries = nullptr; // TMP.INFO CR27: pointer to cluster.series.timeSeries columns - - const uint tsCount = nbThermalTimeseries + 2; - for (uint tsIndex = 0; tsIndex != tsCount; ++tsIndex) - { - uint hour = 0; - - if (tsIndex > 1) - dstSeries = cluster.series.timeSeries[tsIndex - 2]; - - for (uint dayInTheYear = 0; dayInTheYear < daysPerYear; ++dayInTheYear) - { - assert(AUN <= 100 and "Thermal Prepro: AUN is out of bounds (>=100)"); - assert(dayInTheYear < 366); - assert(not(lf[dayInTheYear] < 0.)); - assert(not(lp[dayInTheYear] < 0.)); - - PODOfTheDay = (int)POD[dayInTheYear]; - FODOfTheDay = (int)FOD[dayInTheYear]; - - assert(NOW < Log_size); - NPO_cur -= LOGP[NOW]; - LOGP[NOW] = 0; - AUN += LOG[NOW]; - LOG[NOW] = 0; - - if (NPO_cur > NPOmax[dayInTheYear]) - { - int cible_retour = NPO_cur - (int)NPOmax[dayInTheYear]; - - int cumul_retour = 0; - - for (int index = 1; index < Log_size; ++index) - { - if (cumul_retour == cible_retour) - break; - - if (LOGP[(NOW + index) % Log_size] + cumul_retour >= cible_retour) - { - LOGP[(NOW + index) % Log_size] -= (cible_retour - cumul_retour); - - LOG[(NOW + index) % Log_size] -= (cible_retour - cumul_retour); - - cumul_retour = cible_retour; - } - else - { - if (LOGP[(NOW + index) % Log_size] > 0) - { - cumul_retour += LOGP[(NOW + index) % Log_size]; - - LOG[(NOW + index) % Log_size] -= LOGP[(NOW + index) % Log_size]; - - LOGP[(NOW + index) % Log_size] = 0; - } - } - } - - AUN += cible_retour; - NPO_cur = (int)NPOmax[dayInTheYear]; - } - - int FOC = 0; - - int POC = 0; - - if (lf[dayInTheYear] > 0. and lf[dayInTheYear] <= FAILURE_RATE_EQ_1) - { - A = rndgenerator.next(); - last = FPOW[dayInTheYear][AUN]; - - if (A > last) - { - cumul = last; - for (int d = 1; d < AUN + 1; ++d) - { - last = ((last * ff[dayInTheYear]) * ((double)(AUN + 1. - d))) / (double)d; - cumul += last; - FOC = d; - if (A <= cumul) - break; - } - } - } - else - { - FOC = (lf[dayInTheYear] > 0.) ? AUN : 0; - } - - if (lp[dayInTheYear] > 0. and lp[dayInTheYear] <= FAILURE_RATE_EQ_1) - { - int AUN_app = AUN; - if (stock >= 0 and stock <= AUN) - AUN_app -= stock; - if (stock > AUN) - AUN_app = 0; - - last = PPOW[dayInTheYear][AUN_app]; - A = rndgenerator.next(); - - if (A > last) - { - cumul = last; - for (int d = 1; d < AUN_app + 1; ++d) - { - last - = ((last * pp[dayInTheYear]) * ((double)(AUN_app + 1. - d))) / (double)d; - cumul += last; - POC = d; - if (A <= cumul) - break; - } - } - } - else - { - POC = (lp[dayInTheYear] > 0.) ? AUN : 0; - } - - int candidat = POC + stock; - if (0 <= candidat and candidat <= AUN) - { - POC = candidat; - - stock = 0; - } - if (candidat > AUN) - { - stock = candidat - AUN; - - POC = AUN; - } - if (candidat < 0) - { - stock = candidat; - - POC = 0; - } - - if (POC + NPO_cur > NPOmax[dayInTheYear]) - { - stock += POC + NPO_cur - (int)NPOmax[dayInTheYear]; - - POC = (int)NPOmax[dayInTheYear] - NPO_cur; - - NPO_cur = (int)NPOmax[dayInTheYear]; - } - else - { - if (POC + NPO_cur < NPOmin[dayInTheYear]) - { - if (NPOmin[dayInTheYear] - NPO_cur > AUN) - { - stock -= (AUN - POC); - - POC = AUN; - NPO_cur += POC; - } - else - { - stock -= (int)NPOmin[dayInTheYear] - (POC + NPO_cur); - - POC = (int)NPOmin[dayInTheYear] - NPO_cur; - - NPO_cur = (int)NPOmin[dayInTheYear]; - } - } - else - { - NPO_cur += POC; - } - } - - if (cluster.unitCount == 1) - { - if (POC == 1 and FOC == 1) - { - PPO = 0; - PFO = 0; - MXO = 1; - } - else - { - MXO = 0; - PFO = FOC; - PPO = POC; - } - } - else - { - if (AUN != 0) - { - MXO = POC * FOC / AUN; - PPO = POC - MXO; - PFO = FOC - MXO; - } - else - { - MXO = 0; - PPO = 0; - PFO = 0; - } - } - - AUN = AUN - (PPO + PFO + MXO); - - if (PFO != 0 or MXO != 0) - FOD_reel = durationGenerator( - f_law, FODOfTheDay, f_volatility, af[dayInTheYear], bf[dayInTheYear]); - if (PPO != 0 or MXO != 0) - POD_reel = durationGenerator( - p_law, PODOfTheDay, p_volatility, ap[dayInTheYear], bp[dayInTheYear]); - - assert(FUT < Log_size); - if (PFO != 0) - { - FUT = (NOW + FOD_reel) % Log_size; - LOG[FUT] += PFO; - } - if (PPO != 0) - { - FUT = (NOW + POD_reel) % Log_size; - LOG[FUT] += PPO; - LOGP[FUT] = LOGP[FUT] + PPO; - } - if (MXO != 0) - { - FUT = (NOW + POD_reel + FOD_reel) % Log_size; - LOG[FUT] += MXO; - LOGP[FUT] = LOGP[FUT] + MXO; - } - NOW = (NOW + 1) % Log_size; - - AVP[dayInTheYear] = AUN * cluster.nominalCapacity; - - if (tsIndex > 1) - { - double AVPDayInTheYear = AVP[dayInTheYear]; - for (uint h = 0; h != 24; ++h) - { - dstSeries[hour] = Math::Round(AVPDayInTheYear * modulation[hour]); // TMP.INFO CR27: here it is changed - ++hour; - } - } - } - } - - if (derated) // TMP.INFO CR27: derated mode - averaging - keep it like this! - cluster.series.timeSeries.averageTimeseries(); - - if (archive) - writeResultsToDisk(area, cluster); - - cluster.calculationOfSpinning(); // TODO CR27 // do we still need to call this function?! -} -} // namespace - -namespace // TODO CR27: move this to separate *.h and *.cpp file -{ - -class OptimizedThermalGenerator : public GeneratorTempData -{ -private: - /* - in adq-patch we re-used existing structure(s) for helping us define an optimization problem -> - like: struct CORRESPONDANCES_DES_VARIABLES. - unfortunately here we have to create our own help-structure if we need one - Question: can we still use struct PROBLEME_ANTARES_A_RESOUDRE ?! - if we define problem for sirius solver we use this structure. - for OR tools solver we also use this structure I think ?! - */ - - // define here variables/structures that will help us build optimization problem - - // optimization problem construction methods - void calculateParameters(); - void buildProblemVariables(); - void setVariableBounds(); - void buildProblemConstraintsLHS(); - void buildProblemConstraintsRHS(); - void setProblemCost(); - void solveProblem(); - void allocateProblem(); // this one should be called in constructor. It basically resets all the - // vectors in PROBLEME_ANTARES_A_RESOUDRE for new opt problem. - - // some methods - void GenerateOptimizedThermalTimeSeriesPerOneMaintenanceGroup( - Antares::Data::MaintenanceGroup& group); - void calculateResidualLoad(Antares::Data::MaintenanceGroup& group); - void createOptimizationProblemPerCluster(const Data::Area& area, Data::ThermalCluster& cluster); - - // variables - Antares::Data::MaintenanceGroupRepository& maintenanceGroupRepo; - bool globalThermalTSgeneration_; - -public: - void run(); // calls private optimization problem construction methods - - explicit OptimizedThermalGenerator(Data::Study& study, - uint year, - bool globalThermalTSgeneration, - Solver::Progression::Task& progr, - IResultWriter& writer) : - GeneratorTempData(study, progr, writer), - maintenanceGroupRepo(study.maintenanceGroups) - { - currentYear = year; - globalThermalTSgeneration_ = globalThermalTSgeneration; - nbThermalTimeseries = study.parameters.maintenancePlanning.getScenarioLength() - * study.parameters.maintenancePlanning.getScenarioNumber(); - // allocateProblem(); - } - - ~OptimizedThermalGenerator() = default; - - void GenerateOptimizedThermalTimeSeriesPerAllMaintenanceGroups(); -}; - -// start defining functions here! // Actually define them in *.cpp file - -void OptimizedThermalGenerator::GenerateOptimizedThermalTimeSeriesPerAllMaintenanceGroups() -{ - const auto& activeMaintenanceGroups = maintenanceGroupRepo.activeMaintenanceGroups(); - for (const auto& entryMaintenanceGroup : activeMaintenanceGroups) - { - auto& maintenanceGroup = *(entryMaintenanceGroup.get()); - calculateResidualLoad(maintenanceGroup); - GenerateOptimizedThermalTimeSeriesPerOneMaintenanceGroup(maintenanceGroup); - } -} - -void OptimizedThermalGenerator::calculateResidualLoad(Antares::Data::MaintenanceGroup& maintenanceGroup) -{ - // dummy value for test - std::array values; - values.fill(2.5); - - // extract some info about the group - const std::string& groupName = maintenanceGroup.name(); - const auto& groupType = maintenanceGroup.type(); - const auto& groupResLoad = maintenanceGroup.getUsedResidualLoadTS(); - - // for phase II - if (groupType == Antares::Data::MaintenanceGroup::typeTimeserie) - { - // read user defined ts - userProvidedResidualLoadTS_ with getter - phase-II - maintenanceGroup.setUsedResidualLoadTS(values); - } - - // loop through the elements of weightMap weights_ - for (const auto& entryWeightMap : maintenanceGroup) - { - const auto& area = *(entryWeightMap.first); - auto weights = (entryWeightMap.second); - // we do not need to loop through clusters here - // per area data -> load, ror, renewable is all we need to calculate - // residual load TS - } - - // set resLoadTS - maintenanceGroup.setUsedResidualLoadTS(values); -} - -void OptimizedThermalGenerator::GenerateOptimizedThermalTimeSeriesPerOneMaintenanceGroup( - Antares::Data::MaintenanceGroup& maintenanceGroup) -{ - // loop through the elements of weightMap weights_ - for (const auto& entryWeightMap : maintenanceGroup) - { - const auto& area = *(entryWeightMap.first); - // loop through the thermal clusters inside the area - for (auto it = area.thermal.list.mapping.begin(); it != area.thermal.list.mapping.end(); - ++it) - { - auto& cluster = *(it->second); - createOptimizationProblemPerCluster(area, cluster); - ++pProgression; - } - } -} - -void OptimizedThermalGenerator::createOptimizationProblemPerCluster(const Data::Area& area, - Data::ThermalCluster& cluster) +namespace Antares::Solver::TSGenerator { - if (cluster.doWeGenerateTS(globalThermalTSgeneration_) && cluster.optimizeMaintenance) - { - // just playing here - this needs to go into new method - class - operator - logs.info() << "CR27-INFO: This cluster is active for mnt planning: " - << cluster.getFullName(); - - if (!cluster.prepro) - { - logs.error() << "Cluster: " << area.name << '/' << cluster.name() - << ": The timeseries will not be regenerated. All data " - "related to the ts-generator for " - << "'thermal' have been released."; - } - - assert(cluster.prepro); - - if (0 == cluster.unitCount || 0 == cluster.nominalCapacity || nbThermalTimeseries == 0) - { - cluster.series.timeSeries.reset(1, 8760); - } - else - { - cluster.series.timeSeries.reset(nbThermalTimeseries, 8760); - cluster.series.timeSeries.fill(777.); - } - - if (archive) - writeResultsToDisk(area, cluster); - - // end playing - } -} - -#include "../../libs/antares/study/maintenance_planning/MaintenanceGroupRepository.h" -#include "../../libs/antares/study/maintenance_planning/MaintenanceGroup.h" -} - bool GenerateRandomizedThermalTimeSeries(Data::Study& study, uint year, @@ -849,6 +105,4 @@ bool GenerateThermalTimeSeries(Data::Study& study, } } -} // namespace TSGenerator -} // namespace Solver -} // namespace Antares +} // namespace Antares::Solver::TSGenerator From c66ea7e0a05f4a71f0a303d2da17529d5d068039 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Fri, 10 Nov 2023 15:46:41 +0100 Subject: [PATCH 063/315] clean --- .../randomized-thermal-generator/RandomizedGenerator.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/solver/ts-generator/randomized-thermal-generator/RandomizedGenerator.h b/src/solver/ts-generator/randomized-thermal-generator/RandomizedGenerator.h index c77f44fe32..5766410800 100644 --- a/src/solver/ts-generator/randomized-thermal-generator/RandomizedGenerator.h +++ b/src/solver/ts-generator/randomized-thermal-generator/RandomizedGenerator.h @@ -79,6 +79,4 @@ class GeneratorTempData IResultWriter& pWriter; }; -} // namespace Antares::Solver::TSGenerator - -// #endif // OPTIMIZED_GENERATOR_H \ No newline at end of file +} // namespace Antares::Solver::TSGenerator \ No newline at end of file From b1ebf4219f9a6aa58c8a5e0c36b47b6f021f92a5 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Fri, 10 Nov 2023 17:51:16 +0100 Subject: [PATCH 064/315] add pre-check: interactions between the maintenance planning and other timeseries generations --- .../antares/checks/checkLoadedInputData.h | 2 ++ .../antares/checks/checkLoadedInputData.cpp | 19 +++++++++++++++++++ src/libs/antares/exception/LoadingError.cpp | 6 ++++++ .../antares/exception/LoadingError.hpp | 6 ++++++ src/solver/application.cpp | 2 ++ 5 files changed, 35 insertions(+) diff --git a/src/libs/antares/checks/antares/checks/checkLoadedInputData.h b/src/libs/antares/checks/antares/checks/checkLoadedInputData.h index ad036cafc0..f1950db360 100644 --- a/src/libs/antares/checks/antares/checks/checkLoadedInputData.h +++ b/src/libs/antares/checks/antares/checks/checkLoadedInputData.h @@ -46,4 +46,6 @@ void checkMinStablePower(bool tsGenThermal, const Antares::Data::AreaList& areas void checkFuelCostColumnNumber(const Antares::Data::AreaList& areas); void checkCO2CostColumnNumber(const Antares::Data::AreaList& areas); +void checkMaintenancePlanningSettings(const Antares::Data::Parameters* parameters); + } // namespace Antares::Check diff --git a/src/libs/antares/checks/checkLoadedInputData.cpp b/src/libs/antares/checks/checkLoadedInputData.cpp index d585ffdaa1..53c0e15208 100644 --- a/src/libs/antares/checks/checkLoadedInputData.cpp +++ b/src/libs/antares/checks/checkLoadedInputData.cpp @@ -200,4 +200,23 @@ void checkCO2CostColumnNumber(const Antares::Data::AreaList& areas) &Antares::Data::EconomicInputData::co2cost); } +void checkMaintenancePlanningSettings(const Antares::Data::Parameters* parameters) +{ + const auto timeSeriesToGenerate = parameters->timeSeriesToGenerate; + bool aggregatedMode = parameters->renewableGeneration.isAggregated(); + + bool activeThermalTSGenAndMntPlanning + = (parameters->maintenancePlanning.isOptimized() + && (timeSeriesToGenerate & Antares::Data::timeSeriesThermal)); + + bool activeOtherTSGen + = ((timeSeriesToGenerate & Antares::Data::timeSeriesLoad) + || (timeSeriesToGenerate & Antares::Data::timeSeriesHydro) + || ((timeSeriesToGenerate & Antares::Data::timeSeriesWind) && aggregatedMode) + || ((timeSeriesToGenerate & Antares::Data::timeSeriesSolar) && aggregatedMode)); + + if (activeThermalTSGenAndMntPlanning && activeOtherTSGen) + throw Error::IncompatibleMaintenancePlanningUsage(); +} + } // namespace Antares::Check diff --git a/src/libs/antares/exception/LoadingError.cpp b/src/libs/antares/exception/LoadingError.cpp index 92c6f26bfa..3dd12678cc 100644 --- a/src/libs/antares/exception/LoadingError.cpp +++ b/src/libs/antares/exception/LoadingError.cpp @@ -166,5 +166,11 @@ IncompatibleFuelCostColumns::IncompatibleFuelCostColumns() : { } +IncompatibleMaintenancePlanningUsage::IncompatibleMaintenancePlanningUsage() : + LoadingError("When generating thermal time series using Maintenance Planning, Stochastic " + "ts-generator for load, hydro and renewables must ne off") +{ +} + } // namespace Error } // namespace Antares diff --git a/src/libs/antares/exception/antares/exception/LoadingError.hpp b/src/libs/antares/exception/antares/exception/LoadingError.hpp index d3b7e15b74..322602d9dc 100644 --- a/src/libs/antares/exception/antares/exception/LoadingError.hpp +++ b/src/libs/antares/exception/antares/exception/LoadingError.hpp @@ -221,5 +221,11 @@ class IncompatibleFuelCostColumns : public LoadingError IncompatibleFuelCostColumns(); }; +class IncompatibleMaintenancePlanningUsage : public LoadingError +{ +public: + IncompatibleMaintenancePlanningUsage(); +}; + } // namespace Error } // namespace Antares diff --git a/src/solver/application.cpp b/src/solver/application.cpp index a2aa4e3dbd..467ff74c1a 100644 --- a/src/solver/application.cpp +++ b/src/solver/application.cpp @@ -164,6 +164,8 @@ void Application::prepare(int argc, char* argv[]) checkFuelCostColumnNumber(pStudy->areas); checkCO2CostColumnNumber(pStudy->areas); + checkMaintenancePlanningSettings(pParameters); + // Start the progress meter pStudy->initializeProgressMeter(pSettings.tsGeneratorsOnly); if (pSettings.noOutput) From b4d7fcef5e0844c31c552edc5b8024813330657a Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Fri, 10 Nov 2023 17:58:41 +0100 Subject: [PATCH 065/315] clang format --- .../RandomizedGenerator.cpp | 30 +++++++------------ .../RandomizedGenerator.h | 4 +-- 2 files changed, 12 insertions(+), 22 deletions(-) diff --git a/src/solver/ts-generator/randomized-thermal-generator/RandomizedGenerator.cpp b/src/solver/ts-generator/randomized-thermal-generator/RandomizedGenerator.cpp index 286d7a49e4..5644408c22 100644 --- a/src/solver/ts-generator/randomized-thermal-generator/RandomizedGenerator.cpp +++ b/src/solver/ts-generator/randomized-thermal-generator/RandomizedGenerator.cpp @@ -20,12 +20,9 @@ GeneratorTempData::GeneratorTempData(Data::Study& study, { auto& parameters = study.parameters; - archive = (0 - != (parameters.timeSeriesToArchive - & Data::timeSeriesThermal)); + archive = (0 != (parameters.timeSeriesToArchive & Data::timeSeriesThermal)); - nbThermalTimeseries - = parameters.nbTimeSeriesThermal; + nbThermalTimeseries = parameters.nbTimeSeriesThermal; derated = parameters.derated; } @@ -100,12 +97,11 @@ void GeneratorTempData::prepareIndispoFromLaw(Data::ThermalLaw law, } } -int GeneratorTempData::durationGenerator( - Data::ThermalLaw law, - int expec, - double volat, - double a, - double b) +int GeneratorTempData::durationGenerator(Data::ThermalLaw law, + int expec, + double volat, + double a, + double b) { if (volat == 0 or expec == 1) return expec; @@ -132,8 +128,7 @@ int GeneratorTempData::durationGenerator( return 0; } -void GeneratorTempData::operator()(Data::Area& area, - Data::ThermalCluster& cluster) +void GeneratorTempData::operator()(Data::Area& area, Data::ThermalCluster& cluster) { if (not cluster.prepro) { @@ -148,16 +143,14 @@ void GeneratorTempData::operator()(Data::Area& area, if (0 == cluster.unitCount or 0 == cluster.nominalCapacity) { - cluster.series.timeSeries.reset( - 1, nbHoursPerYear); + cluster.series.timeSeries.reset(1, nbHoursPerYear); if (archive) writeResultsToDisk(area, cluster); return; } - cluster.series.timeSeries.resize(nbThermalTimeseries, - nbHoursPerYear); + cluster.series.timeSeries.resize(nbThermalTimeseries, nbHoursPerYear); const auto& preproData = *(cluster.prepro); @@ -492,8 +485,7 @@ void GeneratorTempData::operator()(Data::Area& area, double AVPDayInTheYear = AVP[dayInTheYear]; for (uint h = 0; h != 24; ++h) { - dstSeries[hour] = Math::Round( - AVPDayInTheYear * modulation[hour]); + dstSeries[hour] = Math::Round(AVPDayInTheYear * modulation[hour]); ++hour; } } diff --git a/src/solver/ts-generator/randomized-thermal-generator/RandomizedGenerator.h b/src/solver/ts-generator/randomized-thermal-generator/RandomizedGenerator.h index 5766410800..0e7a90a0d4 100644 --- a/src/solver/ts-generator/randomized-thermal-generator/RandomizedGenerator.h +++ b/src/solver/ts-generator/randomized-thermal-generator/RandomizedGenerator.h @@ -17,9 +17,7 @@ namespace Antares::Solver::TSGenerator class GeneratorTempData { public: - GeneratorTempData(Data::Study& study, - Solver::Progression::Task& progr, - IResultWriter& writer); + GeneratorTempData(Data::Study& study, Solver::Progression::Task& progr, IResultWriter& writer); void prepareOutputFoldersForAllAreas(uint year); From c8921b3b06a211ae4f72467861fdb1b1b4fb2001 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Fri, 10 Nov 2023 19:19:10 +0100 Subject: [PATCH 066/315] small refactor: replace 8760->HOURS_PER_YEAR --- .../antares/study/maintenance_planning/MaintenanceGroup.cpp | 4 ++-- .../antares/study/maintenance_planning/MaintenanceGroup.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroup.cpp b/src/libs/antares/study/maintenance_planning/MaintenanceGroup.cpp index ca5cbe6cb0..3d7b29f152 100644 --- a/src/libs/antares/study/maintenance_planning/MaintenanceGroup.cpp +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroup.cpp @@ -143,12 +143,12 @@ double MaintenanceGroup::rorWeight(const Area* area) const return (i != weights_.end()) ? i->second.ror : 0.; } -void MaintenanceGroup::setUsedResidualLoadTS(std::array ts) +void MaintenanceGroup::setUsedResidualLoadTS(std::array ts) { usedResidualLoadTS_ = ts; } -std::array MaintenanceGroup::getUsedResidualLoadTS() const +std::array MaintenanceGroup::getUsedResidualLoadTS() const { return usedResidualLoadTS_; } diff --git a/src/libs/antares/study/maintenance_planning/MaintenanceGroup.h b/src/libs/antares/study/maintenance_planning/MaintenanceGroup.h index 83ea214d8d..4d50940b89 100644 --- a/src/libs/antares/study/maintenance_planning/MaintenanceGroup.h +++ b/src/libs/antares/study/maintenance_planning/MaintenanceGroup.h @@ -258,7 +258,7 @@ class MaintenanceGroup : public Yuni::NonCopyable //! array of residual loads per h //! if typeTimeserie -> equal to userProvidedResidualLoadTS_, //! if typeWeights -> calculated using per area weights - std::array usedResidualLoadTS_; + std::array usedResidualLoadTS_; void clear(); void copyFrom(MaintenanceGroup const* original); From 94624b5759870065943954c076ed7db5ea3d4921 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Fri, 10 Nov 2023 19:20:40 +0100 Subject: [PATCH 067/315] calculateResidualLoad - I part --- .../OptimizedGenerator.cpp | 58 ++++++++++++++----- .../OptimizedGenerator.h | 3 + 2 files changed, 45 insertions(+), 16 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp index c99e390970..37f223cc71 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp @@ -18,36 +18,62 @@ void OptimizedThermalGenerator::GenerateOptimizedThermalTimeSeriesPerAllMaintena } } -void OptimizedThermalGenerator::calculateResidualLoad(Data::MaintenanceGroup& maintenanceGroup) +std::array OptimizedThermalGenerator::calculateAverageLoadTs(const Data::Area& area) +{ + std::array values; + values.fill(2.5); + return values; +} +std::array OptimizedThermalGenerator::calculateAverageRorTs(const Data::Area& area) { - // dummy value for test - std::array values; + std::array values; values.fill(2.5); + return values; +} +std::array OptimizedThermalGenerator::calculateAverageRenewableTs( + const Data::Area& area) +{ + std::array values; + values.fill(2.5); + return values; +} - // extract some info about the group - const std::string& groupName = maintenanceGroup.name(); - const auto& groupType = maintenanceGroup.type(); - const auto& groupResLoad = maintenanceGroup.getUsedResidualLoadTS(); +void OptimizedThermalGenerator::calculateResidualLoad(Data::MaintenanceGroup& maintenanceGroup) +{ + // create reference value arrays + std::array refValueLoad = {}; + std::array refValueRor = {}; + std::array refValueRenewable = {}; + std::array refValue = {}; // for phase II - if (groupType == Data::MaintenanceGroup::typeTimeserie) + if (maintenanceGroup.type() == Data::MaintenanceGroup::typeTimeserie) { // read user defined ts - userProvidedResidualLoadTS_ with getter - phase-II - maintenanceGroup.setUsedResidualLoadTS(values); } // loop through the elements of weightMap weights_ for (const auto& entryWeightMap : maintenanceGroup) { const auto& area = *(entryWeightMap.first); - auto weights = (entryWeightMap.second); - // we do not need to loop through clusters here - // per area data -> load, ror, renewable is all we need to calculate - // residual load TS - } + const auto weights = (entryWeightMap.second); + + auto tmpLoad = calculateAverageLoadTs(area); + auto tmpRor = calculateAverageRorTs(area); + auto tmpRenewable = calculateAverageRenewableTs(area); - // set resLoadTS - maintenanceGroup.setUsedResidualLoadTS(values); + for (std::size_t i = 0; i < HOURS_PER_YEAR; ++i) + { + refValueLoad[i] += tmpLoad[i] * weights.load; + refValueRor[i] += tmpRor[i] * weights.ror; + refValueRenewable[i] += tmpRenewable[i] * weights.renewable; + } + } + // calculate reference value + for (std::size_t i = 0; i < HOURS_PER_YEAR; ++i) + refValue[i] = refValueLoad[i] - refValueRor[i] - refValueRenewable[i]; + // set ResidualLoadTS + maintenanceGroup.setUsedResidualLoadTS(refValue); } void OptimizedThermalGenerator::GenerateOptimizedThermalTimeSeriesPerOneMaintenanceGroup( diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index b33138be91..134e9301ae 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -38,6 +38,9 @@ class OptimizedThermalGenerator : public GeneratorTempData void GenerateOptimizedThermalTimeSeriesPerOneMaintenanceGroup(Data::MaintenanceGroup& group); void calculateResidualLoad(Data::MaintenanceGroup& group); void createOptimizationProblemPerCluster(const Data::Area& area, Data::ThermalCluster& cluster); + std::array calculateAverageLoadTs(const Data::Area& area); + std::array calculateAverageRorTs(const Data::Area& area); + std::array calculateAverageRenewableTs(const Data::Area& area); // variables Data::MaintenanceGroupRepository& maintenanceGroupRepo; From 75f352bfaf02ead9d0b14ba71bd6c2fd598d0090 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Fri, 10 Nov 2023 20:52:55 +0100 Subject: [PATCH 068/315] typo --- src/libs/antares/exception/LoadingError.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/antares/exception/LoadingError.cpp b/src/libs/antares/exception/LoadingError.cpp index 3dd12678cc..99f38ec8f5 100644 --- a/src/libs/antares/exception/LoadingError.cpp +++ b/src/libs/antares/exception/LoadingError.cpp @@ -168,7 +168,7 @@ IncompatibleFuelCostColumns::IncompatibleFuelCostColumns() : IncompatibleMaintenancePlanningUsage::IncompatibleMaintenancePlanningUsage() : LoadingError("When generating thermal time series using Maintenance Planning, Stochastic " - "ts-generator for load, hydro and renewables must ne off") + "ts-generator for load, hydro and renewables must be turned off") { } From 575b344bdd8b8b402a628886f63d11c0f996b24b Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Fri, 10 Nov 2023 20:54:42 +0100 Subject: [PATCH 069/315] cheat - generate TimeSeriesNumbers even if tsGeneratorsOnly=true, if we are using maintenancePlanning --- src/solver/simulation/solver.hxx | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/solver/simulation/solver.hxx b/src/solver/simulation/solver.hxx index c9f965512d..578f485752 100644 --- a/src/solver/simulation/solver.hxx +++ b/src/solver/simulation/solver.hxx @@ -318,6 +318,28 @@ void ISimulation::run() // in general data of the study. logs.info() << " Only the preprocessors are enabled."; + // we want to know TS numbers if we want to use Maintenance planning - so we are cheating + // here + // TODO CR27: put this in a separate void function! + if (study.parameters.maintenancePlanning.isOptimized() + && (study.parameters.timeSeriesToGenerate & Antares::Data::timeSeriesThermal)) + { + if (not ImplementationType::simulationBegin()) + return; + // Allocating the memory + ImplementationType::variables.simulationBegin(); + + study.resizeAllTimeseriesNumbers(1 + study.runtime->rangeLimits.year[Data::rangeEnd]); + + if (not TimeSeriesNumbers::Generate(study)) + { + throw FatalError("An unrecoverable error has occurred. Can not continue."); + } + + if (study.parameters.useCustomScenario) + ApplyCustomScenario(study); + } + regenerateTimeSeries(0);// TMP.INFO CR27: when running ts-gen ONLY. No refresh span needed. Year = 0. We only generate TS-s once. No refreshing TS-s is necessary // Destroy the TS Generators if any From 20f380e7706c8acf4ecd829ea114fed3ddbda662 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Fri, 10 Nov 2023 20:56:50 +0100 Subject: [PATCH 070/315] clean --- src/solver/simulation/solver.hxx | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/src/solver/simulation/solver.hxx b/src/solver/simulation/solver.hxx index 578f485752..c4fbfe3428 100644 --- a/src/solver/simulation/solver.hxx +++ b/src/solver/simulation/solver.hxx @@ -340,11 +340,11 @@ void ISimulation::run() ApplyCustomScenario(study); } - regenerateTimeSeries(0);// TMP.INFO CR27: when running ts-gen ONLY. No refresh span needed. Year = 0. We only generate TS-s once. No refreshing TS-s is necessary + regenerateTimeSeries(0); // Destroy the TS Generators if any // It will export the time-series into the output in the same time - Solver::TSGenerator::DestroyAll(study); // TMP.INFO CR27: be aware of this destroy - it is OK + Solver::TSGenerator::DestroyAll(study); } else { @@ -362,18 +362,6 @@ void ISimulation::run() // for a single simulation study.resizeAllTimeseriesNumbers(1 + study.runtime->rangeLimits.year[Data::rangeEnd]); // Now, we will prepare the time-series numbers - /* - TODO CR27: Just great! Time series numbers are available from here. - And we need them for average load, renewable and ror TS, Right? This is a big issue?! - So when we call regenerateTimeSeries(0) with settings.tsGeneratorsOnly = true. - We DO NOT have access to the random generated TS numbers for MC-years. - When we call loopThroughYears-> regenerateTimeSeries(set_it->yearForTSgeneration) - we DO HAVE access to the random generated TS numbers for MC-years. - (It still stands here that we call our new thermal ts-gen only once here - no refresh span) - Can we include TimeSeriesNumbers::Generate(study) when tsGeneratorsOnly = true && maintenancePlanning.isOptimized() - Just to be able to be able to calculate parameters for optimization problem?! - */ - if (not TimeSeriesNumbers::Generate(study)) { throw FatalError("An unrecoverable error has occured. Can not continue."); From ad1db76f58c81edb49893a53dd2788e7ad189a22 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Fri, 10 Nov 2023 22:07:33 +0100 Subject: [PATCH 071/315] calculateResidualLoad - II part - NOT TESTED - test on monday --- .../OptimizedGenerator.cpp | 110 +++++++++++++++--- .../OptimizedGenerator.h | 5 + 2 files changed, 99 insertions(+), 16 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp index 37f223cc71..cfe928595f 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp @@ -18,24 +18,102 @@ void OptimizedThermalGenerator::GenerateOptimizedThermalTimeSeriesPerAllMaintena } } +std::array OptimizedThermalGenerator::calculateAverageTs( + const Matrix& tsValue, + const Matrix& tsNumbers) +{ + // define array + std::array averageTs = {}; + // calculate sum + for (std::size_t year = 0; year < tsNumbers.height; ++year) + { + for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) + { + averageTs[row] += tsValue[tsNumbers[0][year]][row]; + } + } + // calculate mean + for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) + { + averageTs[row] = averageTs[row] / tsNumbers.height; + } + // return + return averageTs; +} + std::array OptimizedThermalGenerator::calculateAverageLoadTs(const Data::Area& area) { - std::array values; - values.fill(2.5); - return values; + // we assume ready-make TS - (pre-check exist for this!) + const auto tsValues = area.load.series.timeSeries; + const auto tsNumbers = area.load.series.timeseriesNumbers; + return calculateAverageTs(tsValues, tsNumbers); } -std::array OptimizedThermalGenerator::calculateAverageRorTs(const Data::Area& area) + +std::array OptimizedThermalGenerator::calculateAverageRorTs( + const Data::Area& area) { - std::array values; - values.fill(2.5); - return values; + const auto tsValues = area.hydro.series->ror.timeSeries; + auto tsNumbers = area.hydro.series->ror.timeseriesNumbers; + return calculateAverageTs(tsValues, tsNumbers); } + +std::array OptimizedThermalGenerator::calculateAverageRenewableTsAggregated( + const Data::Area& area) +{ + std::array averageTsSolar + = calculateAverageTs(area.solar.series.timeSeries, area.solar.series.timeseriesNumbers); + std::array averageTsWind + = calculateAverageTs(area.wind.series.timeSeries, area.wind.series.timeseriesNumbers); + + std::array averageTsRenewable = {}; + for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) + { + averageTsRenewable[row] = (averageTsSolar[row] + averageTsWind[row]) / 2; + } + return averageTsRenewable; +} + +std::array OptimizedThermalGenerator::calculateAverageRenewableTsClusters( + const Data::Area& area) +{ + std::array averageTsRenewable = {}; + uint enabledClusterCount = 0; + for (const auto& entryCluster : area.renewable.clusters) + { + auto& cluster = *entryCluster; + if (!cluster.enabled) // do we consider if cluster is of or on + continue; + enabledClusterCount++; + auto tmpArrayPerCluster + = calculateAverageTs(cluster.series.timeSeries, cluster.series.timeseriesNumbers); + for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) + { + if (cluster.productionFactor) + averageTsRenewable[row] + += tmpArrayPerCluster[row] * cluster.unitCount * cluster.nominalCapacity; + else + averageTsRenewable[row] += tmpArrayPerCluster[row]; + } + } + // calculate mean + for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) + { + averageTsRenewable[row] = averageTsRenewable[row] / enabledClusterCount; + } + return averageTsRenewable; +} + std::array OptimizedThermalGenerator::calculateAverageRenewableTs( const Data::Area& area) { - std::array values; - values.fill(2.5); - return values; + if (study.parameters.renewableGeneration.isAggregated()) + { + return calculateAverageRenewableTsAggregated(area); + } + else // clusters it is + { + return calculateAverageRenewableTsClusters(area); + } } void OptimizedThermalGenerator::calculateResidualLoad(Data::MaintenanceGroup& maintenanceGroup) @@ -62,16 +140,16 @@ void OptimizedThermalGenerator::calculateResidualLoad(Data::MaintenanceGroup& ma auto tmpRor = calculateAverageRorTs(area); auto tmpRenewable = calculateAverageRenewableTs(area); - for (std::size_t i = 0; i < HOURS_PER_YEAR; ++i) + for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) { - refValueLoad[i] += tmpLoad[i] * weights.load; - refValueRor[i] += tmpRor[i] * weights.ror; - refValueRenewable[i] += tmpRenewable[i] * weights.renewable; + refValueLoad[row] += tmpLoad[row] * weights.load; + refValueRor[row] += tmpRor[row] * weights.ror; + refValueRenewable[row] += tmpRenewable[row] * weights.renewable; } } // calculate reference value - for (std::size_t i = 0; i < HOURS_PER_YEAR; ++i) - refValue[i] = refValueLoad[i] - refValueRor[i] - refValueRenewable[i]; + for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) + refValue[row] = refValueLoad[row] - refValueRor[row] - refValueRenewable[row]; // set ResidualLoadTS maintenanceGroup.setUsedResidualLoadTS(refValue); } diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 134e9301ae..fb50ff580e 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -38,8 +38,13 @@ class OptimizedThermalGenerator : public GeneratorTempData void GenerateOptimizedThermalTimeSeriesPerOneMaintenanceGroup(Data::MaintenanceGroup& group); void calculateResidualLoad(Data::MaintenanceGroup& group); void createOptimizationProblemPerCluster(const Data::Area& area, Data::ThermalCluster& cluster); + std::array calculateAverageTs(const Matrix& tsValue, + const Matrix& tsNumbers); std::array calculateAverageLoadTs(const Data::Area& area); std::array calculateAverageRorTs(const Data::Area& area); + std::array calculateAverageRenewableTsAggregated( + const Data::Area& area); + std::array calculateAverageRenewableTsClusters(const Data::Area& area); std::array calculateAverageRenewableTs(const Data::Area& area); // variables From 61403d36921aff1a0f002f295e6f2dd9dc458159 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Mon, 13 Nov 2023 10:00:21 +0100 Subject: [PATCH 072/315] fix calculateAverageRenewableTs --- .../optimized-thermal-generator/OptimizedGenerator.cpp | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp index cfe928595f..555ba4591d 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp @@ -68,7 +68,7 @@ std::array OptimizedThermalGenerator::calculateAverageRe std::array averageTsRenewable = {}; for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) { - averageTsRenewable[row] = (averageTsSolar[row] + averageTsWind[row]) / 2; + averageTsRenewable[row] = (averageTsSolar[row] + averageTsWind[row]); // ask Hugo do we divide by 2 ? } return averageTsRenewable; } @@ -77,13 +77,11 @@ std::array OptimizedThermalGenerator::calculateAverageRe const Data::Area& area) { std::array averageTsRenewable = {}; - uint enabledClusterCount = 0; for (const auto& entryCluster : area.renewable.clusters) { auto& cluster = *entryCluster; if (!cluster.enabled) // do we consider if cluster is of or on continue; - enabledClusterCount++; auto tmpArrayPerCluster = calculateAverageTs(cluster.series.timeSeries, cluster.series.timeseriesNumbers); for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) @@ -95,11 +93,6 @@ std::array OptimizedThermalGenerator::calculateAverageRe averageTsRenewable[row] += tmpArrayPerCluster[row]; } } - // calculate mean - for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) - { - averageTsRenewable[row] = averageTsRenewable[row] / enabledClusterCount; - } return averageTsRenewable; } From a50962feda769ff1b31024bdaba68823009459b2 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Mon, 13 Nov 2023 10:19:41 +0100 Subject: [PATCH 073/315] clean --- .../optimized-thermal-generator/OptimizedGenerator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp index 555ba4591d..71e2885989 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp @@ -68,7 +68,7 @@ std::array OptimizedThermalGenerator::calculateAverageRe std::array averageTsRenewable = {}; for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) { - averageTsRenewable[row] = (averageTsSolar[row] + averageTsWind[row]); // ask Hugo do we divide by 2 ? + averageTsRenewable[row] = (averageTsSolar[row] + averageTsWind[row]); } return averageTsRenewable; } From ae0810d6725fc61681ae4016b2867ca4346438cc Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Mon, 13 Nov 2023 12:00:16 +0100 Subject: [PATCH 074/315] fix calculateAverageRenewableTs - 2 --- .../optimized-thermal-generator/OptimizedGenerator.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp index 71e2885989..be47454628 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp @@ -80,13 +80,16 @@ std::array OptimizedThermalGenerator::calculateAverageRe for (const auto& entryCluster : area.renewable.clusters) { auto& cluster = *entryCluster; - if (!cluster.enabled) // do we consider if cluster is of or on + // this is not even necessary - because area.renewable.clusters returns list of only ENABLED + // clusters + // but let's keep it for now + if (!cluster.enabled) continue; auto tmpArrayPerCluster = calculateAverageTs(cluster.series.timeSeries, cluster.series.timeseriesNumbers); for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) { - if (cluster.productionFactor) + if (cluster.tsMode == Data::RenewableCluster::productionFactor) averageTsRenewable[row] += tmpArrayPerCluster[row] * cluster.unitCount * cluster.nominalCapacity; else @@ -121,6 +124,7 @@ void OptimizedThermalGenerator::calculateResidualLoad(Data::MaintenanceGroup& ma if (maintenanceGroup.type() == Data::MaintenanceGroup::typeTimeserie) { // read user defined ts - userProvidedResidualLoadTS_ with getter - phase-II + return; } // loop through the elements of weightMap weights_ From 2d59c60a55e3d1113fe72f6464c36fc66fb8118f Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Mon, 13 Nov 2023 14:02:06 +0100 Subject: [PATCH 075/315] refactor solver.hxx -> to run-only-ts-gen -> ApplyScenarioBuilderDueToMaintenancePlanning --- src/solver/simulation/solver.hxx | 24 ++------------- src/solver/ts-generator/CMakeLists.txt | 2 ++ .../pre-scenario-builder.cpp | 29 +++++++++++++++++++ .../pre-scenario-builder.h | 11 +++++++ 4 files changed, 45 insertions(+), 21 deletions(-) create mode 100644 src/solver/ts-generator/optimized-thermal-generator/pre-scenario-builder.cpp create mode 100644 src/solver/ts-generator/optimized-thermal-generator/pre-scenario-builder.h diff --git a/src/solver/simulation/solver.hxx b/src/solver/simulation/solver.hxx index c4fbfe3428..ffb37b1871 100644 --- a/src/solver/simulation/solver.hxx +++ b/src/solver/simulation/solver.hxx @@ -40,6 +40,7 @@ #include "../ts-generator/generator.h" #include "opt_time_writer.h" #include "../hydro/management.h" // Added for use of randomReservoirLevel(...) +#include "../ts-generator/optimized-thermal-generator/pre-scenario-builder.h" #include #include @@ -318,27 +319,8 @@ void ISimulation::run() // in general data of the study. logs.info() << " Only the preprocessors are enabled."; - // we want to know TS numbers if we want to use Maintenance planning - so we are cheating - // here - // TODO CR27: put this in a separate void function! - if (study.parameters.maintenancePlanning.isOptimized() - && (study.parameters.timeSeriesToGenerate & Antares::Data::timeSeriesThermal)) - { - if (not ImplementationType::simulationBegin()) - return; - // Allocating the memory - ImplementationType::variables.simulationBegin(); - - study.resizeAllTimeseriesNumbers(1 + study.runtime->rangeLimits.year[Data::rangeEnd]); - - if (not TimeSeriesNumbers::Generate(study)) - { - throw FatalError("An unrecoverable error has occurred. Can not continue."); - } - - if (study.parameters.useCustomScenario) - ApplyCustomScenario(study); - } + // we want to know TS numbers if we want to use Maintenance planning + ApplyScenarioBuilderDueToMaintenancePlanning(study); regenerateTimeSeries(0); diff --git a/src/solver/ts-generator/CMakeLists.txt b/src/solver/ts-generator/CMakeLists.txt index 92830c170e..75846dde21 100644 --- a/src/solver/ts-generator/CMakeLists.txt +++ b/src/solver/ts-generator/CMakeLists.txt @@ -13,6 +13,8 @@ source_group("ts-generator\\randomized-thermal-generator" FILES ${SRC_RANDOMIZED # Optimized-thermal-ts-generator # set(SRC_OPTIMIZEDGENERATORS + optimized-thermal-generator/pre-scenario-builder.h + optimized-thermal-generator/pre-scenario-builder.cpp optimized-thermal-generator/OptimizedGenerator.h optimized-thermal-generator/OptimizedGenerator.cpp ) diff --git a/src/solver/ts-generator/optimized-thermal-generator/pre-scenario-builder.cpp b/src/solver/ts-generator/optimized-thermal-generator/pre-scenario-builder.cpp new file mode 100644 index 0000000000..1400a664c1 --- /dev/null +++ b/src/solver/ts-generator/optimized-thermal-generator/pre-scenario-builder.cpp @@ -0,0 +1,29 @@ +/* +** created by milos 13/11/2023 +*/ + +#include +#include "pre-scenario-builder.h" +#include "../../simulation/apply-scenario.h" +#include "../../simulation/timeseries-numbers.h" + +namespace Antares::Solver +{ +void ApplyScenarioBuilderDueToMaintenancePlanning(Data::Study& study) +{ + if (study.parameters.maintenancePlanning.isOptimized() + && (study.parameters.timeSeriesToGenerate & Antares::Data::timeSeriesThermal)) + { + study.resizeAllTimeseriesNumbers(1 + study.runtime->rangeLimits.year[Data::rangeEnd]); + + if (!TimeSeriesNumbers::Generate(study)) + { + throw FatalError("An unrecoverable error has occurred. Can not continue."); + } + + if (study.parameters.useCustomScenario) + ApplyCustomScenario(study); + } +} + +} // namespace Antares::Solver diff --git a/src/solver/ts-generator/optimized-thermal-generator/pre-scenario-builder.h b/src/solver/ts-generator/optimized-thermal-generator/pre-scenario-builder.h new file mode 100644 index 0000000000..388c49b0d6 --- /dev/null +++ b/src/solver/ts-generator/optimized-thermal-generator/pre-scenario-builder.h @@ -0,0 +1,11 @@ +/* +** created by milos 13/11/2023 +*/ +#pragma once + +#include + +namespace Antares::Solver +{ +void ApplyScenarioBuilderDueToMaintenancePlanning(Data::Study& study); +} // namespace Antares::Solver From 96b789c2492aa6ba572c4177f5ff5e226c5ca242 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Mon, 13 Nov 2023 14:30:35 +0100 Subject: [PATCH 076/315] refactor ApplyScenarioBuilderDueToMaintenancePlanning --- .../pre-scenario-builder.cpp | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/pre-scenario-builder.cpp b/src/solver/ts-generator/optimized-thermal-generator/pre-scenario-builder.cpp index 1400a664c1..afa1345bb8 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/pre-scenario-builder.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/pre-scenario-builder.cpp @@ -11,19 +11,21 @@ namespace Antares::Solver { void ApplyScenarioBuilderDueToMaintenancePlanning(Data::Study& study) { - if (study.parameters.maintenancePlanning.isOptimized() - && (study.parameters.timeSeriesToGenerate & Antares::Data::timeSeriesThermal)) - { - study.resizeAllTimeseriesNumbers(1 + study.runtime->rangeLimits.year[Data::rangeEnd]); + if (!study.parameters.maintenancePlanning.isOptimized()) + return; + + if (!(study.parameters.timeSeriesToGenerate & Antares::Data::timeSeriesThermal)) + return; - if (!TimeSeriesNumbers::Generate(study)) - { - throw FatalError("An unrecoverable error has occurred. Can not continue."); - } + study.resizeAllTimeseriesNumbers(1 + study.runtime->rangeLimits.year[Data::rangeEnd]); - if (study.parameters.useCustomScenario) - ApplyCustomScenario(study); + if (!TimeSeriesNumbers::Generate(study)) + { + throw FatalError("An unrecoverable error has occurred. Can not continue."); } + + if (study.parameters.useCustomScenario) + ApplyCustomScenario(study); } } // namespace Antares::Solver From 5302a71a8b1171ebad4d9b77e802cc76203c81d5 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Mon, 13 Nov 2023 16:47:37 +0100 Subject: [PATCH 077/315] method calculateTimeHorizonAndStep --- .../antares/study/parts/thermal/cluster.h | 4 +-- .../OptimizedGenerator.cpp | 34 +++++++++++++++++++ .../OptimizedGenerator.h | 1 + 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/libs/antares/study/parts/thermal/cluster.h b/src/libs/antares/study/parts/thermal/cluster.h index 8bfa1661cf..2bfceea4fb 100644 --- a/src/libs/antares/study/parts/thermal/cluster.h +++ b/src/libs/antares/study/parts/thermal/cluster.h @@ -298,9 +298,9 @@ class ThermalCluster final : public Cluster, public std::enable_shared_from_this //! Optimize maintenance yes/no bool optimizeMaintenance = true; - //! Inter PO period (days) + //! Inter PO period (days) // Average duration between maintenance events int interPoPeriod = 365; - //! PO windows (+/- days) + //! PO windows (+/- days) // Acceptable maintenance window (+/- N days, 0 as default value) int poWindows = 0; // TODO CR27: keep this here for now // maybe create something like PreproThermal for Maintenance - and move everything there!!! diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp index be47454628..970d223549 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp @@ -12,8 +12,10 @@ void OptimizedThermalGenerator::GenerateOptimizedThermalTimeSeriesPerAllMaintena const auto& activeMaintenanceGroups = maintenanceGroupRepo.activeMaintenanceGroups(); for (const auto& entryMaintenanceGroup : activeMaintenanceGroups) { + int timeHorizon, timeStep; auto& maintenanceGroup = *(entryMaintenanceGroup.get()); calculateResidualLoad(maintenanceGroup); + std::tie(timeStep, timeHorizon) = calculateTimeHorizonAndStep(maintenanceGroup); GenerateOptimizedThermalTimeSeriesPerOneMaintenanceGroup(maintenanceGroup); } } @@ -151,6 +153,38 @@ void OptimizedThermalGenerator::calculateResidualLoad(Data::MaintenanceGroup& ma maintenanceGroup.setUsedResidualLoadTS(refValue); } +std::pair OptimizedThermalGenerator::calculateTimeHorizonAndStep( + Data::MaintenanceGroup& maintenanceGroup) +{ + std::vector averageDurationBetweenMaintenances = {}; + for (const auto& entryWeightMap : maintenanceGroup) + { + const auto& area = *(entryWeightMap.first); + for (auto it = area.thermal.list.mapping.begin(); it != area.thermal.list.mapping.end(); + ++it) + { + const auto& cluster = *(it->second); + if (cluster.doWeGenerateTS(globalThermalTSgeneration_) && cluster.optimizeMaintenance) + { + averageDurationBetweenMaintenances.push_back(cluster.interPoPeriod); + } + } + } + + // Using std::minmax_element to find min and max + auto [minIter, maxIter] = std::minmax_element(averageDurationBetweenMaintenances.begin(), + averageDurationBetweenMaintenances.end()); + + // Check if the vector is not empty + if (minIter != averageDurationBetweenMaintenances.end() + && maxIter != averageDurationBetweenMaintenances.end()) + { + return std::make_pair(*minIter, 2*(*maxIter)); + } + + return std::make_pair(0, 0); +} + void OptimizedThermalGenerator::GenerateOptimizedThermalTimeSeriesPerOneMaintenanceGroup( Data::MaintenanceGroup& maintenanceGroup) { diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index fb50ff580e..8322095afe 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -35,6 +35,7 @@ class OptimizedThermalGenerator : public GeneratorTempData // vectors in PROBLEME_ANTARES_A_RESOUDRE for new opt problem. // some methods + std::pair calculateTimeHorizonAndStep(Data::MaintenanceGroup& group); void GenerateOptimizedThermalTimeSeriesPerOneMaintenanceGroup(Data::MaintenanceGroup& group); void calculateResidualLoad(Data::MaintenanceGroup& group); void createOptimizationProblemPerCluster(const Data::Area& area, Data::ThermalCluster& cluster); From fe541946b4e5958450d005076920aa2750a64c3c Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Mon, 13 Nov 2023 17:16:51 +0100 Subject: [PATCH 078/315] calculateNumberOfMaintenances --- .../OptimizedGenerator.cpp | 12 ++++++++++++ .../optimized-thermal-generator/OptimizedGenerator.h | 1 + 2 files changed, 13 insertions(+) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp index 970d223549..2dcab04c88 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp @@ -12,14 +12,22 @@ void OptimizedThermalGenerator::GenerateOptimizedThermalTimeSeriesPerAllMaintena const auto& activeMaintenanceGroups = maintenanceGroupRepo.activeMaintenanceGroups(); for (const auto& entryMaintenanceGroup : activeMaintenanceGroups) { + // timeHorizon & timeStep are defined per one MaintenanceGroup int timeHorizon, timeStep; auto& maintenanceGroup = *(entryMaintenanceGroup.get()); + // Residual Load (or reference value) array is defined per one MaintenanceGroup calculateResidualLoad(maintenanceGroup); std::tie(timeStep, timeHorizon) = calculateTimeHorizonAndStep(maintenanceGroup); GenerateOptimizedThermalTimeSeriesPerOneMaintenanceGroup(maintenanceGroup); } } +uint OptimizedThermalGenerator::calculateNumberOfMaintenances(Data::ThermalCluster& cluster, + uint timeHorizon) +{ + return timeHorizon / cluster.interPoPeriod; // floor +} + std::array OptimizedThermalGenerator::calculateAverageTs( const Matrix& tsValue, const Matrix& tsNumbers) @@ -208,6 +216,10 @@ void OptimizedThermalGenerator::createOptimizationProblemPerCluster(const Data:: { if (cluster.doWeGenerateTS(globalThermalTSgeneration_) && cluster.optimizeMaintenance) { + // number of maintenances are defined per cluster-unit + // but are the same for all units inside the same cluster + int numberOfMaintenancesPerUnit; + numberOfMaintenancesPerUnit = calculateNumberOfMaintenances(cluster, 365); // TODO CR27: get the T-timeHorizon here - parameter or class // just playing here - this needs to go into new method - class - operator logs.info() << "CR27-INFO: This cluster is active for mnt planning: " << cluster.getFullName(); diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 8322095afe..4c794acb08 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -36,6 +36,7 @@ class OptimizedThermalGenerator : public GeneratorTempData // some methods std::pair calculateTimeHorizonAndStep(Data::MaintenanceGroup& group); + uint calculateNumberOfMaintenances(Data::ThermalCluster& cluster, uint timeHorizon); void GenerateOptimizedThermalTimeSeriesPerOneMaintenanceGroup(Data::MaintenanceGroup& group); void calculateResidualLoad(Data::MaintenanceGroup& group); void createOptimizationProblemPerCluster(const Data::Area& area, Data::ThermalCluster& cluster); From bda47a40e30d2ca8904b769830fcf5fb29f3cdf5 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Mon, 13 Nov 2023 17:54:10 +0100 Subject: [PATCH 079/315] calculateMaintenanceGroupENSandSpillageCost --- .../OptimizedGenerator.cpp | 32 +++++++++++++++++-- .../OptimizedGenerator.h | 1 + 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp index 2dcab04c88..bdf8959573 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp @@ -12,11 +12,14 @@ void OptimizedThermalGenerator::GenerateOptimizedThermalTimeSeriesPerAllMaintena const auto& activeMaintenanceGroups = maintenanceGroupRepo.activeMaintenanceGroups(); for (const auto& entryMaintenanceGroup : activeMaintenanceGroups) { - // timeHorizon & timeStep are defined per one MaintenanceGroup + // timeHorizon, timeStep ENS and Spillage are defined per one MaintenanceGroup int timeHorizon, timeStep; + double ensCost, spillCost; auto& maintenanceGroup = *(entryMaintenanceGroup.get()); - // Residual Load (or reference value) array is defined per one MaintenanceGroup + // Residual Load (or reference value) array is defined per one MaintenanceGroup calculateResidualLoad(maintenanceGroup); + std::tie(ensCost, spillCost) + = calculateMaintenanceGroupENSandSpillageCost(maintenanceGroup); std::tie(timeStep, timeHorizon) = calculateTimeHorizonAndStep(maintenanceGroup); GenerateOptimizedThermalTimeSeriesPerOneMaintenanceGroup(maintenanceGroup); } @@ -193,6 +196,31 @@ std::pair OptimizedThermalGenerator::calculateTimeHorizonAndStep( return std::make_pair(0, 0); } +std::pair OptimizedThermalGenerator::calculateMaintenanceGroupENSandSpillageCost( + Data::MaintenanceGroup& maintenanceGroup) +{ + std::vector ensVector = {}; + std::vector spillageVector = {}; + for (const auto& entryWeightMap : maintenanceGroup) + { + const auto& area = *(entryWeightMap.first); + ensVector.push_back(area.thermal.unsuppliedEnergyCost); + spillageVector.push_back(area.thermal.spilledEnergyCost); + } + + // Using std::minmax_element to find min and max + auto ens = std::min_element(ensVector.begin(), ensVector.end()); + auto spill = std::min_element(spillageVector.begin(), spillageVector.end()); + + // Check if the vector is not empty + if (ens != ensVector.end() && spill != spillageVector.end()) + { + return std::make_pair(*ens, *spill); + } + + return std::make_pair(0, 0); +} + void OptimizedThermalGenerator::GenerateOptimizedThermalTimeSeriesPerOneMaintenanceGroup( Data::MaintenanceGroup& maintenanceGroup) { diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 4c794acb08..e00f4705df 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -36,6 +36,7 @@ class OptimizedThermalGenerator : public GeneratorTempData // some methods std::pair calculateTimeHorizonAndStep(Data::MaintenanceGroup& group); + std::pair calculateMaintenanceGroupENSandSpillageCost(Data::MaintenanceGroup& group); uint calculateNumberOfMaintenances(Data::ThermalCluster& cluster, uint timeHorizon); void GenerateOptimizedThermalTimeSeriesPerOneMaintenanceGroup(Data::MaintenanceGroup& group); void calculateResidualLoad(Data::MaintenanceGroup& group); From bb314028e2ca535ec2055be0afbba0ad6316bfef Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Mon, 13 Nov 2023 19:39:02 +0100 Subject: [PATCH 080/315] calculateMaxUnitOutput & calculateDailySums --- .../OptimizedGenerator.cpp | 42 +++++++++++++++++++ .../OptimizedGenerator.h | 4 +- 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp index bdf8959573..89d60ccd92 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp @@ -4,6 +4,8 @@ #include "OptimizedGenerator.h" +#include + namespace Antares::Solver::TSGenerator { @@ -15,9 +17,11 @@ void OptimizedThermalGenerator::GenerateOptimizedThermalTimeSeriesPerAllMaintena // timeHorizon, timeStep ENS and Spillage are defined per one MaintenanceGroup int timeHorizon, timeStep; double ensCost, spillCost; + std::array residualLoadDailyValues; auto& maintenanceGroup = *(entryMaintenanceGroup.get()); // Residual Load (or reference value) array is defined per one MaintenanceGroup calculateResidualLoad(maintenanceGroup); + residualLoadDailyValues = calculateDailySums(maintenanceGroup.getUsedResidualLoadTS()); std::tie(ensCost, spillCost) = calculateMaintenanceGroupENSandSpillageCost(maintenanceGroup); std::tie(timeStep, timeHorizon) = calculateTimeHorizonAndStep(maintenanceGroup); @@ -125,6 +129,43 @@ std::array OptimizedThermalGenerator::calculateAverageRe } } +std::array OptimizedThermalGenerator::calculateDailySums( + const std::array& hourlyValues) +{ + std::array dailyValues; + auto hours_iter = hourlyValues.begin(); + + for (double& day_sum : dailyValues) + { + day_sum = std::accumulate(hours_iter, hours_iter + 24, 0.0); + hours_iter += 24; + } + + return dailyValues; +} + +std::array OptimizedThermalGenerator::calculateMaxUnitOutput( + Data::ThermalCluster& cluster) +{ + std::array maxOutputDailyValues = {}; + std::array maxOutputHourlyValues = {}; + + // transfer to array + for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) + { + maxOutputHourlyValues[row] + = cluster.modulation[Data::ThermalModulation::thermalModulationCapacity][row]; + } + + maxOutputDailyValues = calculateDailySums(maxOutputHourlyValues); + // multiply by per unit power (nominal capacity) + for (double& num : maxOutputDailyValues) + { + num *= cluster.nominalCapacity; + } + return maxOutputDailyValues; +} + void OptimizedThermalGenerator::calculateResidualLoad(Data::MaintenanceGroup& maintenanceGroup) { // create reference value arrays @@ -248,6 +289,7 @@ void OptimizedThermalGenerator::createOptimizationProblemPerCluster(const Data:: // but are the same for all units inside the same cluster int numberOfMaintenancesPerUnit; numberOfMaintenancesPerUnit = calculateNumberOfMaintenances(cluster, 365); // TODO CR27: get the T-timeHorizon here - parameter or class + std::array maxUnitOutput = calculateMaxUnitOutput(cluster); // just playing here - this needs to go into new method - class - operator logs.info() << "CR27-INFO: This cluster is active for mnt planning: " << cluster.getFullName(); diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index e00f4705df..a92f46518a 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -49,7 +49,9 @@ class OptimizedThermalGenerator : public GeneratorTempData const Data::Area& area); std::array calculateAverageRenewableTsClusters(const Data::Area& area); std::array calculateAverageRenewableTs(const Data::Area& area); - + std::array calculateDailySums( + const std::array& hourlyValues); + std::array calculateMaxUnitOutput(Data::ThermalCluster& cluster); // variables Data::MaintenanceGroupRepository& maintenanceGroupRepo; bool globalThermalTSgeneration_; From d1a891f80f2e0e458d30cef5001e4738ed0145d3 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Mon, 13 Nov 2023 19:46:18 +0100 Subject: [PATCH 081/315] calculateAverageMaintenanceDuration - TODO --- .../optimized-thermal-generator/OptimizedGenerator.cpp | 7 +++++++ .../optimized-thermal-generator/OptimizedGenerator.h | 1 + 2 files changed, 8 insertions(+) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp index 89d60ccd92..ea77314fab 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp @@ -35,6 +35,11 @@ uint OptimizedThermalGenerator::calculateNumberOfMaintenances(Data::ThermalClust return timeHorizon / cluster.interPoPeriod; // floor } +uint OptimizedThermalGenerator::calculateAverageMaintenanceDuration(Data::ThermalCluster& cluster) +{ + return 0.0; // TODO CR27: Ask Hugo +} + std::array OptimizedThermalGenerator::calculateAverageTs( const Matrix& tsValue, const Matrix& tsNumbers) @@ -288,7 +293,9 @@ void OptimizedThermalGenerator::createOptimizationProblemPerCluster(const Data:: // number of maintenances are defined per cluster-unit // but are the same for all units inside the same cluster int numberOfMaintenancesPerUnit; + int averageMaintenanceDuration; numberOfMaintenancesPerUnit = calculateNumberOfMaintenances(cluster, 365); // TODO CR27: get the T-timeHorizon here - parameter or class + averageMaintenanceDuration = calculateAverageMaintenanceDuration(cluster); std::array maxUnitOutput = calculateMaxUnitOutput(cluster); // just playing here - this needs to go into new method - class - operator logs.info() << "CR27-INFO: This cluster is active for mnt planning: " diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index a92f46518a..98c9d1ec9c 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -38,6 +38,7 @@ class OptimizedThermalGenerator : public GeneratorTempData std::pair calculateTimeHorizonAndStep(Data::MaintenanceGroup& group); std::pair calculateMaintenanceGroupENSandSpillageCost(Data::MaintenanceGroup& group); uint calculateNumberOfMaintenances(Data::ThermalCluster& cluster, uint timeHorizon); + uint calculateAverageMaintenanceDuration(Data::ThermalCluster& cluster); void GenerateOptimizedThermalTimeSeriesPerOneMaintenanceGroup(Data::MaintenanceGroup& group); void calculateResidualLoad(Data::MaintenanceGroup& group); void createOptimizationProblemPerCluster(const Data::Area& area, Data::ThermalCluster& cluster); From c672bdf92b77fa9bf2664750cdddda6adbe34814 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Mon, 13 Nov 2023 20:19:11 +0100 Subject: [PATCH 082/315] calculateAverageMaintenanceDuration implement --- .../OptimizedGenerator.cpp | 10 +++++-- .../OptimizedGenerator.h | 30 ++++++++++++------- 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp index ea77314fab..c0c84631e6 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp @@ -37,7 +37,13 @@ uint OptimizedThermalGenerator::calculateNumberOfMaintenances(Data::ThermalClust uint OptimizedThermalGenerator::calculateAverageMaintenanceDuration(Data::ThermalCluster& cluster) { - return 0.0; // TODO CR27: Ask Hugo + double sum = 0.0; + for (std::size_t row = 0; row < DAYS_PER_YEAR; ++row) + { + sum += cluster.prepro->data[Data::PreproThermal::poDuration][row]; + } + + return sum / static_cast(DAYS_PER_YEAR); } std::array OptimizedThermalGenerator::calculateAverageTs( @@ -295,7 +301,7 @@ void OptimizedThermalGenerator::createOptimizationProblemPerCluster(const Data:: int numberOfMaintenancesPerUnit; int averageMaintenanceDuration; numberOfMaintenancesPerUnit = calculateNumberOfMaintenances(cluster, 365); // TODO CR27: get the T-timeHorizon here - parameter or class - averageMaintenanceDuration = calculateAverageMaintenanceDuration(cluster); + averageMaintenanceDuration = calculateAverageMaintenanceDuration(cluster); // this will floor the double value !! std::array maxUnitOutput = calculateMaxUnitOutput(cluster); // just playing here - this needs to go into new method - class - operator logs.info() << "CR27-INFO: This cluster is active for mnt planning: " diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 98c9d1ec9c..1f60947466 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -34,25 +34,35 @@ class OptimizedThermalGenerator : public GeneratorTempData void allocateProblem(); // this one should be called in constructor. It basically resets all the // vectors in PROBLEME_ANTARES_A_RESOUDRE for new opt problem. - // some methods - std::pair calculateTimeHorizonAndStep(Data::MaintenanceGroup& group); - std::pair calculateMaintenanceGroupENSandSpillageCost(Data::MaintenanceGroup& group); - uint calculateNumberOfMaintenances(Data::ThermalCluster& cluster, uint timeHorizon); - uint calculateAverageMaintenanceDuration(Data::ThermalCluster& cluster); + // optimization problem - methods void GenerateOptimizedThermalTimeSeriesPerOneMaintenanceGroup(Data::MaintenanceGroup& group); - void calculateResidualLoad(Data::MaintenanceGroup& group); void createOptimizationProblemPerCluster(const Data::Area& area, Data::ThermalCluster& cluster); + + // calculate parameters methods - per maintenance group + std::pair calculateTimeHorizonAndStep(Data::MaintenanceGroup& group); + std::pair calculateMaintenanceGroupENSandSpillageCost( + Data::MaintenanceGroup& group); + void calculateResidualLoad(Data::MaintenanceGroup& group); + + // calculate parameters methods - per cluster + uint calculateNumberOfMaintenances(Data::ThermalCluster& cluster, uint timeHorizon); + uint calculateAverageMaintenanceDuration(Data::ThermalCluster& cluster); + std::array calculateMaxUnitOutput(Data::ThermalCluster& cluster); + + // auxillary functions + std::array calculateDailySums( + const std::array& hourlyValues); std::array calculateAverageTs(const Matrix& tsValue, const Matrix& tsNumbers); + + // calculate Average time-series functions std::array calculateAverageLoadTs(const Data::Area& area); std::array calculateAverageRorTs(const Data::Area& area); + std::array calculateAverageRenewableTs(const Data::Area& area); std::array calculateAverageRenewableTsAggregated( const Data::Area& area); std::array calculateAverageRenewableTsClusters(const Data::Area& area); - std::array calculateAverageRenewableTs(const Data::Area& area); - std::array calculateDailySums( - const std::array& hourlyValues); - std::array calculateMaxUnitOutput(Data::ThermalCluster& cluster); + // variables Data::MaintenanceGroupRepository& maintenanceGroupRepo; bool globalThermalTSgeneration_; From 6af2a8e610da6968582e5a24f54227145de95490 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Mon, 13 Nov 2023 20:28:57 +0100 Subject: [PATCH 083/315] re-arrange methods for better readability --- .../OptimizedGenerator.cpp | 401 +++++++++--------- 1 file changed, 204 insertions(+), 197 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp index c0c84631e6..182c30dc5c 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp @@ -8,7 +8,7 @@ namespace Antares::Solver::TSGenerator { - +// optimization problem - methods void OptimizedThermalGenerator::GenerateOptimizedThermalTimeSeriesPerAllMaintenanceGroups() { const auto& activeMaintenanceGroups = maintenanceGroupRepo.activeMaintenanceGroups(); @@ -29,152 +29,125 @@ void OptimizedThermalGenerator::GenerateOptimizedThermalTimeSeriesPerAllMaintena } } -uint OptimizedThermalGenerator::calculateNumberOfMaintenances(Data::ThermalCluster& cluster, - uint timeHorizon) -{ - return timeHorizon / cluster.interPoPeriod; // floor -} - -uint OptimizedThermalGenerator::calculateAverageMaintenanceDuration(Data::ThermalCluster& cluster) +void OptimizedThermalGenerator::GenerateOptimizedThermalTimeSeriesPerOneMaintenanceGroup( + Data::MaintenanceGroup& maintenanceGroup) { - double sum = 0.0; - for (std::size_t row = 0; row < DAYS_PER_YEAR; ++row) + // loop through the elements of weightMap weights_ + for (const auto& entryWeightMap : maintenanceGroup) { - sum += cluster.prepro->data[Data::PreproThermal::poDuration][row]; + const auto& area = *(entryWeightMap.first); + // loop through the thermal clusters inside the area + for (auto it = area.thermal.list.mapping.begin(); it != area.thermal.list.mapping.end(); + ++it) + { + auto& cluster = *(it->second); + createOptimizationProblemPerCluster(area, cluster); + ++pProgression; + } } - - return sum / static_cast(DAYS_PER_YEAR); } -std::array OptimizedThermalGenerator::calculateAverageTs( - const Matrix& tsValue, - const Matrix& tsNumbers) +void OptimizedThermalGenerator::createOptimizationProblemPerCluster(const Data::Area& area, + Data::ThermalCluster& cluster) { - // define array - std::array averageTs = {}; - // calculate sum - for (std::size_t year = 0; year < tsNumbers.height; ++year) + if (cluster.doWeGenerateTS(globalThermalTSgeneration_) && cluster.optimizeMaintenance) { - for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) + // number of maintenances are defined per cluster-unit + // but are the same for all units inside the same cluster + int numberOfMaintenancesPerUnit; + int averageMaintenanceDuration; + numberOfMaintenancesPerUnit = calculateNumberOfMaintenances( + cluster, 365); // TODO CR27: get the T-timeHorizon here - parameter or class + averageMaintenanceDuration + = calculateAverageMaintenanceDuration(cluster); // this will floor the double value !! + std::array maxUnitOutput = calculateMaxUnitOutput(cluster); + // just playing here - this needs to go into new method - class - operator + logs.info() << "CR27-INFO: This cluster is active for mnt planning: " + << cluster.getFullName(); + + if (!cluster.prepro) { - averageTs[row] += tsValue[tsNumbers[0][year]][row]; + logs.error() << "Cluster: " << area.name << '/' << cluster.name() + << ": The timeseries will not be regenerated. All data " + "related to the ts-generator for " + << "'thermal' have been released."; } - } - // calculate mean - for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) - { - averageTs[row] = averageTs[row] / tsNumbers.height; - } - // return - return averageTs; -} -std::array OptimizedThermalGenerator::calculateAverageLoadTs(const Data::Area& area) -{ - // we assume ready-make TS - (pre-check exist for this!) - const auto tsValues = area.load.series.timeSeries; - const auto tsNumbers = area.load.series.timeseriesNumbers; - return calculateAverageTs(tsValues, tsNumbers); -} + assert(cluster.prepro); -std::array OptimizedThermalGenerator::calculateAverageRorTs( - const Data::Area& area) -{ - const auto tsValues = area.hydro.series->ror.timeSeries; - auto tsNumbers = area.hydro.series->ror.timeseriesNumbers; - return calculateAverageTs(tsValues, tsNumbers); -} + if (0 == cluster.unitCount || 0 == cluster.nominalCapacity || nbThermalTimeseries == 0) + { + cluster.series.timeSeries.reset(1, 8760); + } + else + { + cluster.series.timeSeries.reset(nbThermalTimeseries, 8760); + cluster.series.timeSeries.fill(777.); + } -std::array OptimizedThermalGenerator::calculateAverageRenewableTsAggregated( - const Data::Area& area) -{ - std::array averageTsSolar - = calculateAverageTs(area.solar.series.timeSeries, area.solar.series.timeseriesNumbers); - std::array averageTsWind - = calculateAverageTs(area.wind.series.timeSeries, area.wind.series.timeseriesNumbers); + if (archive) + writeResultsToDisk(area, cluster); - std::array averageTsRenewable = {}; - for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) - { - averageTsRenewable[row] = (averageTsSolar[row] + averageTsWind[row]); + // end playing } - return averageTsRenewable; } -std::array OptimizedThermalGenerator::calculateAverageRenewableTsClusters( - const Data::Area& area) +// calculate parameters methods - per maintenance group +std::pair OptimizedThermalGenerator::calculateTimeHorizonAndStep( + Data::MaintenanceGroup& maintenanceGroup) { - std::array averageTsRenewable = {}; - for (const auto& entryCluster : area.renewable.clusters) + std::vector averageDurationBetweenMaintenances = {}; + for (const auto& entryWeightMap : maintenanceGroup) { - auto& cluster = *entryCluster; - // this is not even necessary - because area.renewable.clusters returns list of only ENABLED - // clusters - // but let's keep it for now - if (!cluster.enabled) - continue; - auto tmpArrayPerCluster - = calculateAverageTs(cluster.series.timeSeries, cluster.series.timeseriesNumbers); - for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) + const auto& area = *(entryWeightMap.first); + for (auto it = area.thermal.list.mapping.begin(); it != area.thermal.list.mapping.end(); + ++it) { - if (cluster.tsMode == Data::RenewableCluster::productionFactor) - averageTsRenewable[row] - += tmpArrayPerCluster[row] * cluster.unitCount * cluster.nominalCapacity; - else - averageTsRenewable[row] += tmpArrayPerCluster[row]; + const auto& cluster = *(it->second); + if (cluster.doWeGenerateTS(globalThermalTSgeneration_) && cluster.optimizeMaintenance) + { + averageDurationBetweenMaintenances.push_back(cluster.interPoPeriod); + } } } - return averageTsRenewable; -} - -std::array OptimizedThermalGenerator::calculateAverageRenewableTs( - const Data::Area& area) -{ - if (study.parameters.renewableGeneration.isAggregated()) - { - return calculateAverageRenewableTsAggregated(area); - } - else // clusters it is - { - return calculateAverageRenewableTsClusters(area); - } -} -std::array OptimizedThermalGenerator::calculateDailySums( - const std::array& hourlyValues) -{ - std::array dailyValues; - auto hours_iter = hourlyValues.begin(); + // Using std::minmax_element to find min and max + auto [minIter, maxIter] = std::minmax_element(averageDurationBetweenMaintenances.begin(), + averageDurationBetweenMaintenances.end()); - for (double& day_sum : dailyValues) + // Check if the vector is not empty + if (minIter != averageDurationBetweenMaintenances.end() + && maxIter != averageDurationBetweenMaintenances.end()) { - day_sum = std::accumulate(hours_iter, hours_iter + 24, 0.0); - hours_iter += 24; + return std::make_pair(*minIter, 2 * (*maxIter)); } - return dailyValues; + return std::make_pair(0, 0); } -std::array OptimizedThermalGenerator::calculateMaxUnitOutput( - Data::ThermalCluster& cluster) +std::pair OptimizedThermalGenerator::calculateMaintenanceGroupENSandSpillageCost( + Data::MaintenanceGroup& maintenanceGroup) { - std::array maxOutputDailyValues = {}; - std::array maxOutputHourlyValues = {}; - - // transfer to array - for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) + std::vector ensVector = {}; + std::vector spillageVector = {}; + for (const auto& entryWeightMap : maintenanceGroup) { - maxOutputHourlyValues[row] - = cluster.modulation[Data::ThermalModulation::thermalModulationCapacity][row]; + const auto& area = *(entryWeightMap.first); + ensVector.push_back(area.thermal.unsuppliedEnergyCost); + spillageVector.push_back(area.thermal.spilledEnergyCost); } - maxOutputDailyValues = calculateDailySums(maxOutputHourlyValues); - // multiply by per unit power (nominal capacity) - for (double& num : maxOutputDailyValues) + // Using std::minmax_element to find min and max + auto ens = std::min_element(ensVector.begin(), ensVector.end()); + auto spill = std::min_element(spillageVector.begin(), spillageVector.end()); + + // Check if the vector is not empty + if (ens != ensVector.end() && spill != spillageVector.end()) { - num *= cluster.nominalCapacity; + return std::make_pair(*ens, *spill); } - return maxOutputDailyValues; + + return std::make_pair(0, 0); } void OptimizedThermalGenerator::calculateResidualLoad(Data::MaintenanceGroup& maintenanceGroup) @@ -216,121 +189,155 @@ void OptimizedThermalGenerator::calculateResidualLoad(Data::MaintenanceGroup& ma maintenanceGroup.setUsedResidualLoadTS(refValue); } -std::pair OptimizedThermalGenerator::calculateTimeHorizonAndStep( - Data::MaintenanceGroup& maintenanceGroup) +// calculate parameters methods - per cluster +uint OptimizedThermalGenerator::calculateNumberOfMaintenances(Data::ThermalCluster& cluster, + uint timeHorizon) { - std::vector averageDurationBetweenMaintenances = {}; - for (const auto& entryWeightMap : maintenanceGroup) - { - const auto& area = *(entryWeightMap.first); - for (auto it = area.thermal.list.mapping.begin(); it != area.thermal.list.mapping.end(); - ++it) - { - const auto& cluster = *(it->second); - if (cluster.doWeGenerateTS(globalThermalTSgeneration_) && cluster.optimizeMaintenance) - { - averageDurationBetweenMaintenances.push_back(cluster.interPoPeriod); - } - } - } - - // Using std::minmax_element to find min and max - auto [minIter, maxIter] = std::minmax_element(averageDurationBetweenMaintenances.begin(), - averageDurationBetweenMaintenances.end()); + return timeHorizon / cluster.interPoPeriod; // floor +} - // Check if the vector is not empty - if (minIter != averageDurationBetweenMaintenances.end() - && maxIter != averageDurationBetweenMaintenances.end()) +uint OptimizedThermalGenerator::calculateAverageMaintenanceDuration(Data::ThermalCluster& cluster) +{ + double sum = 0.0; + for (std::size_t row = 0; row < DAYS_PER_YEAR; ++row) { - return std::make_pair(*minIter, 2*(*maxIter)); + sum += cluster.prepro->data[Data::PreproThermal::poDuration][row]; } - return std::make_pair(0, 0); + return sum / static_cast(DAYS_PER_YEAR); } -std::pair OptimizedThermalGenerator::calculateMaintenanceGroupENSandSpillageCost( - Data::MaintenanceGroup& maintenanceGroup) +std::array OptimizedThermalGenerator::calculateMaxUnitOutput( + Data::ThermalCluster& cluster) { - std::vector ensVector = {}; - std::vector spillageVector = {}; - for (const auto& entryWeightMap : maintenanceGroup) + std::array maxOutputDailyValues = {}; + std::array maxOutputHourlyValues = {}; + + // transfer to array + for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) { - const auto& area = *(entryWeightMap.first); - ensVector.push_back(area.thermal.unsuppliedEnergyCost); - spillageVector.push_back(area.thermal.spilledEnergyCost); + maxOutputHourlyValues[row] + = cluster.modulation[Data::ThermalModulation::thermalModulationCapacity][row]; } - // Using std::minmax_element to find min and max - auto ens = std::min_element(ensVector.begin(), ensVector.end()); - auto spill = std::min_element(spillageVector.begin(), spillageVector.end()); + maxOutputDailyValues = calculateDailySums(maxOutputHourlyValues); + // multiply by per unit power (nominal capacity) + for (double& num : maxOutputDailyValues) + { + num *= cluster.nominalCapacity; + } + return maxOutputDailyValues; +} - // Check if the vector is not empty - if (ens != ensVector.end() && spill != spillageVector.end()) +// auxillary functions +std::array OptimizedThermalGenerator::calculateDailySums( + const std::array& hourlyValues) +{ + std::array dailyValues; + auto hours_iter = hourlyValues.begin(); + + for (double& day_sum : dailyValues) { - return std::make_pair(*ens, *spill); + day_sum = std::accumulate(hours_iter, hours_iter + 24, 0.0); + hours_iter += 24; } - return std::make_pair(0, 0); + return dailyValues; } -void OptimizedThermalGenerator::GenerateOptimizedThermalTimeSeriesPerOneMaintenanceGroup( - Data::MaintenanceGroup& maintenanceGroup) +std::array OptimizedThermalGenerator::calculateAverageTs( + const Matrix& tsValue, + const Matrix& tsNumbers) { - // loop through the elements of weightMap weights_ - for (const auto& entryWeightMap : maintenanceGroup) + // define array + std::array averageTs = {}; + // calculate sum + for (std::size_t year = 0; year < tsNumbers.height; ++year) { - const auto& area = *(entryWeightMap.first); - // loop through the thermal clusters inside the area - for (auto it = area.thermal.list.mapping.begin(); it != area.thermal.list.mapping.end(); - ++it) + for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) { - auto& cluster = *(it->second); - createOptimizationProblemPerCluster(area, cluster); - ++pProgression; + averageTs[row] += tsValue[tsNumbers[0][year]][row]; } } + // calculate mean + for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) + { + averageTs[row] = averageTs[row] / tsNumbers.height; + } + // return + return averageTs; } -void OptimizedThermalGenerator::createOptimizationProblemPerCluster(const Data::Area& area, - Data::ThermalCluster& cluster) +// calculate Average time-series functions +std::array OptimizedThermalGenerator::calculateAverageLoadTs( + const Data::Area& area) { - if (cluster.doWeGenerateTS(globalThermalTSgeneration_) && cluster.optimizeMaintenance) - { - // number of maintenances are defined per cluster-unit - // but are the same for all units inside the same cluster - int numberOfMaintenancesPerUnit; - int averageMaintenanceDuration; - numberOfMaintenancesPerUnit = calculateNumberOfMaintenances(cluster, 365); // TODO CR27: get the T-timeHorizon here - parameter or class - averageMaintenanceDuration = calculateAverageMaintenanceDuration(cluster); // this will floor the double value !! - std::array maxUnitOutput = calculateMaxUnitOutput(cluster); - // just playing here - this needs to go into new method - class - operator - logs.info() << "CR27-INFO: This cluster is active for mnt planning: " - << cluster.getFullName(); + // we assume ready-make TS - (pre-check exist for this!) + const auto tsValues = area.load.series.timeSeries; + const auto tsNumbers = area.load.series.timeseriesNumbers; + return calculateAverageTs(tsValues, tsNumbers); +} - if (!cluster.prepro) - { - logs.error() << "Cluster: " << area.name << '/' << cluster.name() - << ": The timeseries will not be regenerated. All data " - "related to the ts-generator for " - << "'thermal' have been released."; - } +std::array OptimizedThermalGenerator::calculateAverageRorTs( + const Data::Area& area) +{ + const auto tsValues = area.hydro.series->ror.timeSeries; + auto tsNumbers = area.hydro.series->ror.timeseriesNumbers; + return calculateAverageTs(tsValues, tsNumbers); +} - assert(cluster.prepro); +std::array OptimizedThermalGenerator::calculateAverageRenewableTsAggregated( + const Data::Area& area) +{ + std::array averageTsSolar + = calculateAverageTs(area.solar.series.timeSeries, area.solar.series.timeseriesNumbers); + std::array averageTsWind + = calculateAverageTs(area.wind.series.timeSeries, area.wind.series.timeseriesNumbers); - if (0 == cluster.unitCount || 0 == cluster.nominalCapacity || nbThermalTimeseries == 0) - { - cluster.series.timeSeries.reset(1, 8760); - } - else + std::array averageTsRenewable = {}; + for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) + { + averageTsRenewable[row] = (averageTsSolar[row] + averageTsWind[row]); + } + return averageTsRenewable; +} + +std::array OptimizedThermalGenerator::calculateAverageRenewableTsClusters( + const Data::Area& area) +{ + std::array averageTsRenewable = {}; + for (const auto& entryCluster : area.renewable.clusters) + { + auto& cluster = *entryCluster; + // this is not even necessary - because area.renewable.clusters returns list of only ENABLED + // clusters + // but let's keep it for now + if (!cluster.enabled) + continue; + auto tmpArrayPerCluster + = calculateAverageTs(cluster.series.timeSeries, cluster.series.timeseriesNumbers); + for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) { - cluster.series.timeSeries.reset(nbThermalTimeseries, 8760); - cluster.series.timeSeries.fill(777.); + if (cluster.tsMode == Data::RenewableCluster::productionFactor) + averageTsRenewable[row] + += tmpArrayPerCluster[row] * cluster.unitCount * cluster.nominalCapacity; + else + averageTsRenewable[row] += tmpArrayPerCluster[row]; } + } + return averageTsRenewable; +} - if (archive) - writeResultsToDisk(area, cluster); - - // end playing +std::array OptimizedThermalGenerator::calculateAverageRenewableTs( + const Data::Area& area) +{ + if (study.parameters.renewableGeneration.isAggregated()) + { + return calculateAverageRenewableTsAggregated(area); + } + else // clusters it is + { + return calculateAverageRenewableTsClusters(area); } } From f480e3246278803faf2bbfff34ed5ea1c2c7fc06 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Mon, 13 Nov 2023 21:18:37 +0100 Subject: [PATCH 084/315] calculateUnit[Latest/Earliest]StartOfFirstMaintenance --- .../OptimizedGenerator.cpp | 204 +++++++++++------- .../OptimizedGenerator.h | 8 + 2 files changed, 129 insertions(+), 83 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp index 182c30dc5c..6ade21d8f5 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp @@ -5,6 +5,7 @@ #include "OptimizedGenerator.h" #include +#include namespace Antares::Solver::TSGenerator { @@ -61,6 +62,8 @@ void OptimizedThermalGenerator::createOptimizationProblemPerCluster(const Data:: averageMaintenanceDuration = calculateAverageMaintenanceDuration(cluster); // this will floor the double value !! std::array maxUnitOutput = calculateMaxUnitOutput(cluster); + uint earliestStartOfFirstMaintenance = calculateUnitEarliestStartOfFirstMaintenance(cluster, averageMaintenanceDuration, 8); + uint latestStartOfFirstMaintenance = calculateUnitLatestStartOfFirstMaintenance(cluster, averageMaintenanceDuration, 8); // just playing here - this needs to go into new method - class - operator logs.info() << "CR27-INFO: This cluster is active for mnt planning: " << cluster.getFullName(); @@ -229,116 +232,151 @@ std::array OptimizedThermalGenerator::calculateMaxUnitOut return maxOutputDailyValues; } -// auxillary functions -std::array OptimizedThermalGenerator::calculateDailySums( - const std::array& hourlyValues) +// calculate parameters methods - per cluster-Unit +uint OptimizedThermalGenerator::calculateUnitEarliestStartOfFirstMaintenance( + Data::ThermalCluster& cluster, + int avrMntDuration, + uint unitIndex) { - std::array dailyValues; - auto hours_iter = hourlyValues.begin(); - - for (double& day_sum : dailyValues) + if (unitIndex < cluster.daysSinceLastMaintenance.size()) { - day_sum = std::accumulate(hours_iter, hours_iter + 24, 0.0); - hours_iter += 24; + return std::max( + avrMntDuration - cluster.daysSinceLastMaintenance[unitIndex] - cluster.poWindows, 0); + } + else + { + logs.error() << "Cluster: " << cluster.getFullName() + << " does not have unit: " << unitIndex; + return 0; } - - return dailyValues; } -std::array OptimizedThermalGenerator::calculateAverageTs( - const Matrix& tsValue, - const Matrix& tsNumbers) +uint OptimizedThermalGenerator::calculateUnitLatestStartOfFirstMaintenance( + Data::ThermalCluster& cluster, + int avrMntDuration, + uint unitIndex) { - // define array - std::array averageTs = {}; - // calculate sum - for (std::size_t year = 0; year < tsNumbers.height; ++year) + if (unitIndex < cluster.daysSinceLastMaintenance.size()) { - for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) - { - averageTs[row] += tsValue[tsNumbers[0][year]][row]; - } + return std::max( + avrMntDuration - cluster.daysSinceLastMaintenance[unitIndex] + cluster.poWindows, 0); } - // calculate mean - for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) + else { - averageTs[row] = averageTs[row] / tsNumbers.height; + logs.error() << "Cluster: " << cluster.getFullName() + << " does not have unit: " << unitIndex; + return 0; } - // return - return averageTs; } -// calculate Average time-series functions -std::array OptimizedThermalGenerator::calculateAverageLoadTs( - const Data::Area& area) -{ - // we assume ready-make TS - (pre-check exist for this!) - const auto tsValues = area.load.series.timeSeries; - const auto tsNumbers = area.load.series.timeseriesNumbers; - return calculateAverageTs(tsValues, tsNumbers); -} + // auxillary functions + std::array OptimizedThermalGenerator::calculateDailySums( + const std::array& hourlyValues) + { + std::array dailyValues; + auto hours_iter = hourlyValues.begin(); -std::array OptimizedThermalGenerator::calculateAverageRorTs( - const Data::Area& area) -{ - const auto tsValues = area.hydro.series->ror.timeSeries; - auto tsNumbers = area.hydro.series->ror.timeseriesNumbers; - return calculateAverageTs(tsValues, tsNumbers); -} + for (double& day_sum : dailyValues) + { + day_sum = std::accumulate(hours_iter, hours_iter + 24, 0.0); + hours_iter += 24; + } -std::array OptimizedThermalGenerator::calculateAverageRenewableTsAggregated( - const Data::Area& area) -{ - std::array averageTsSolar - = calculateAverageTs(area.solar.series.timeSeries, area.solar.series.timeseriesNumbers); - std::array averageTsWind - = calculateAverageTs(area.wind.series.timeSeries, area.wind.series.timeseriesNumbers); + return dailyValues; + } - std::array averageTsRenewable = {}; - for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) + std::array OptimizedThermalGenerator::calculateAverageTs( + const Matrix& tsValue, const Matrix& tsNumbers) + { + // define array + std::array averageTs = {}; + // calculate sum + for (std::size_t year = 0; year < tsNumbers.height; ++year) + { + for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) + { + averageTs[row] += tsValue[tsNumbers[0][year]][row]; + } + } + // calculate mean + for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) + { + averageTs[row] = averageTs[row] / tsNumbers.height; + } + // return + return averageTs; + } + + // calculate Average time-series functions + std::array OptimizedThermalGenerator::calculateAverageLoadTs( + const Data::Area& area) { - averageTsRenewable[row] = (averageTsSolar[row] + averageTsWind[row]); + // we assume ready-make TS - (pre-check exist for this!) + const auto tsValues = area.load.series.timeSeries; + const auto tsNumbers = area.load.series.timeseriesNumbers; + return calculateAverageTs(tsValues, tsNumbers); } - return averageTsRenewable; -} -std::array OptimizedThermalGenerator::calculateAverageRenewableTsClusters( - const Data::Area& area) -{ - std::array averageTsRenewable = {}; - for (const auto& entryCluster : area.renewable.clusters) + std::array OptimizedThermalGenerator::calculateAverageRorTs( + const Data::Area& area) + { + const auto tsValues = area.hydro.series->ror.timeSeries; + auto tsNumbers = area.hydro.series->ror.timeseriesNumbers; + return calculateAverageTs(tsValues, tsNumbers); + } + + std::array + OptimizedThermalGenerator::calculateAverageRenewableTsAggregated(const Data::Area& area) { - auto& cluster = *entryCluster; - // this is not even necessary - because area.renewable.clusters returns list of only ENABLED - // clusters - // but let's keep it for now - if (!cluster.enabled) - continue; - auto tmpArrayPerCluster - = calculateAverageTs(cluster.series.timeSeries, cluster.series.timeseriesNumbers); + std::array averageTsSolar + = calculateAverageTs(area.solar.series.timeSeries, area.solar.series.timeseriesNumbers); + std::array averageTsWind + = calculateAverageTs(area.wind.series.timeSeries, area.wind.series.timeseriesNumbers); + + std::array averageTsRenewable = {}; for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) { - if (cluster.tsMode == Data::RenewableCluster::productionFactor) - averageTsRenewable[row] - += tmpArrayPerCluster[row] * cluster.unitCount * cluster.nominalCapacity; - else - averageTsRenewable[row] += tmpArrayPerCluster[row]; + averageTsRenewable[row] = (averageTsSolar[row] + averageTsWind[row]); } + return averageTsRenewable; } - return averageTsRenewable; -} -std::array OptimizedThermalGenerator::calculateAverageRenewableTs( - const Data::Area& area) -{ - if (study.parameters.renewableGeneration.isAggregated()) + std::array + OptimizedThermalGenerator::calculateAverageRenewableTsClusters(const Data::Area& area) { - return calculateAverageRenewableTsAggregated(area); + std::array averageTsRenewable = {}; + for (const auto& entryCluster : area.renewable.clusters) + { + auto& cluster = *entryCluster; + // this is not even necessary - because area.renewable.clusters returns list of only + // ENABLED clusters but let's keep it for now + if (!cluster.enabled) + continue; + auto tmpArrayPerCluster + = calculateAverageTs(cluster.series.timeSeries, cluster.series.timeseriesNumbers); + for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) + { + if (cluster.tsMode == Data::RenewableCluster::productionFactor) + averageTsRenewable[row] + += tmpArrayPerCluster[row] * cluster.unitCount * cluster.nominalCapacity; + else + averageTsRenewable[row] += tmpArrayPerCluster[row]; + } + } + return averageTsRenewable; } - else // clusters it is + + std::array OptimizedThermalGenerator::calculateAverageRenewableTs( + const Data::Area& area) { - return calculateAverageRenewableTsClusters(area); + if (study.parameters.renewableGeneration.isAggregated()) + { + return calculateAverageRenewableTsAggregated(area); + } + else // clusters it is + { + return calculateAverageRenewableTsClusters(area); + } } -} } // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 1f60947466..aeddac8386 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -49,6 +49,14 @@ class OptimizedThermalGenerator : public GeneratorTempData uint calculateAverageMaintenanceDuration(Data::ThermalCluster& cluster); std::array calculateMaxUnitOutput(Data::ThermalCluster& cluster); + // calculate parameters methods - per cluster-Unit + uint calculateUnitEarliestStartOfFirstMaintenance(Data::ThermalCluster& cluster, + int avrMntDuration, + uint unitIndex); + uint calculateUnitLatestStartOfFirstMaintenance(Data::ThermalCluster& cluster, + int avrMntDuration, + uint unitIndex); + // auxillary functions std::array calculateDailySums( const std::array& hourlyValues); From 41563d6e912f98512b4e357a6465de0cd95cd809 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Mon, 13 Nov 2023 21:21:25 +0100 Subject: [PATCH 085/315] clang format --- .../OptimizedGenerator.cpp | 177 +++++++++--------- 1 file changed, 90 insertions(+), 87 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp index 6ade21d8f5..2ed9fbccb4 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp @@ -62,8 +62,10 @@ void OptimizedThermalGenerator::createOptimizationProblemPerCluster(const Data:: averageMaintenanceDuration = calculateAverageMaintenanceDuration(cluster); // this will floor the double value !! std::array maxUnitOutput = calculateMaxUnitOutput(cluster); - uint earliestStartOfFirstMaintenance = calculateUnitEarliestStartOfFirstMaintenance(cluster, averageMaintenanceDuration, 8); - uint latestStartOfFirstMaintenance = calculateUnitLatestStartOfFirstMaintenance(cluster, averageMaintenanceDuration, 8); + uint earliestStartOfFirstMaintenance + = calculateUnitEarliestStartOfFirstMaintenance(cluster, averageMaintenanceDuration, 8); + uint latestStartOfFirstMaintenance + = calculateUnitLatestStartOfFirstMaintenance(cluster, averageMaintenanceDuration, 8); // just playing here - this needs to go into new method - class - operator logs.info() << "CR27-INFO: This cluster is active for mnt planning: " << cluster.getFullName(); @@ -269,114 +271,115 @@ uint OptimizedThermalGenerator::calculateUnitLatestStartOfFirstMaintenance( } } - // auxillary functions - std::array OptimizedThermalGenerator::calculateDailySums( - const std::array& hourlyValues) - { - std::array dailyValues; - auto hours_iter = hourlyValues.begin(); - - for (double& day_sum : dailyValues) - { - day_sum = std::accumulate(hours_iter, hours_iter + 24, 0.0); - hours_iter += 24; - } +// auxillary functions +std::array OptimizedThermalGenerator::calculateDailySums( + const std::array& hourlyValues) +{ + std::array dailyValues; + auto hours_iter = hourlyValues.begin(); - return dailyValues; + for (double& day_sum : dailyValues) + { + day_sum = std::accumulate(hours_iter, hours_iter + 24, 0.0); + hours_iter += 24; } - std::array OptimizedThermalGenerator::calculateAverageTs( - const Matrix& tsValue, const Matrix& tsNumbers) + return dailyValues; +} + +std::array OptimizedThermalGenerator::calculateAverageTs( + const Matrix& tsValue, + const Matrix& tsNumbers) +{ + // define array + std::array averageTs = {}; + // calculate sum + for (std::size_t year = 0; year < tsNumbers.height; ++year) { - // define array - std::array averageTs = {}; - // calculate sum - for (std::size_t year = 0; year < tsNumbers.height; ++year) - { - for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) - { - averageTs[row] += tsValue[tsNumbers[0][year]][row]; - } - } - // calculate mean for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) { - averageTs[row] = averageTs[row] / tsNumbers.height; + averageTs[row] += tsValue[tsNumbers[0][year]][row]; } - // return - return averageTs; } - - // calculate Average time-series functions - std::array OptimizedThermalGenerator::calculateAverageLoadTs( - const Data::Area& area) + // calculate mean + for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) { - // we assume ready-make TS - (pre-check exist for this!) - const auto tsValues = area.load.series.timeSeries; - const auto tsNumbers = area.load.series.timeseriesNumbers; - return calculateAverageTs(tsValues, tsNumbers); + averageTs[row] = averageTs[row] / tsNumbers.height; } + // return + return averageTs; +} + +// calculate Average time-series functions +std::array OptimizedThermalGenerator::calculateAverageLoadTs( + const Data::Area& area) +{ + // we assume ready-make TS - (pre-check exist for this!) + const auto tsValues = area.load.series.timeSeries; + const auto tsNumbers = area.load.series.timeseriesNumbers; + return calculateAverageTs(tsValues, tsNumbers); +} + +std::array OptimizedThermalGenerator::calculateAverageRorTs( + const Data::Area& area) +{ + const auto tsValues = area.hydro.series->ror.timeSeries; + auto tsNumbers = area.hydro.series->ror.timeseriesNumbers; + return calculateAverageTs(tsValues, tsNumbers); +} - std::array OptimizedThermalGenerator::calculateAverageRorTs( - const Data::Area& area) +std::array OptimizedThermalGenerator::calculateAverageRenewableTsAggregated( + const Data::Area& area) +{ + std::array averageTsSolar + = calculateAverageTs(area.solar.series.timeSeries, area.solar.series.timeseriesNumbers); + std::array averageTsWind + = calculateAverageTs(area.wind.series.timeSeries, area.wind.series.timeseriesNumbers); + + std::array averageTsRenewable = {}; + for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) { - const auto tsValues = area.hydro.series->ror.timeSeries; - auto tsNumbers = area.hydro.series->ror.timeseriesNumbers; - return calculateAverageTs(tsValues, tsNumbers); + averageTsRenewable[row] = (averageTsSolar[row] + averageTsWind[row]); } + return averageTsRenewable; +} - std::array - OptimizedThermalGenerator::calculateAverageRenewableTsAggregated(const Data::Area& area) +std::array OptimizedThermalGenerator::calculateAverageRenewableTsClusters( + const Data::Area& area) +{ + std::array averageTsRenewable = {}; + for (const auto& entryCluster : area.renewable.clusters) { - std::array averageTsSolar - = calculateAverageTs(area.solar.series.timeSeries, area.solar.series.timeseriesNumbers); - std::array averageTsWind - = calculateAverageTs(area.wind.series.timeSeries, area.wind.series.timeseriesNumbers); - - std::array averageTsRenewable = {}; + auto& cluster = *entryCluster; + // this is not even necessary - because area.renewable.clusters returns list of only + // ENABLED clusters but let's keep it for now + if (!cluster.enabled) + continue; + auto tmpArrayPerCluster + = calculateAverageTs(cluster.series.timeSeries, cluster.series.timeseriesNumbers); for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) { - averageTsRenewable[row] = (averageTsSolar[row] + averageTsWind[row]); + if (cluster.tsMode == Data::RenewableCluster::productionFactor) + averageTsRenewable[row] + += tmpArrayPerCluster[row] * cluster.unitCount * cluster.nominalCapacity; + else + averageTsRenewable[row] += tmpArrayPerCluster[row]; } - return averageTsRenewable; } + return averageTsRenewable; +} - std::array - OptimizedThermalGenerator::calculateAverageRenewableTsClusters(const Data::Area& area) +std::array OptimizedThermalGenerator::calculateAverageRenewableTs( + const Data::Area& area) +{ + if (study.parameters.renewableGeneration.isAggregated()) { - std::array averageTsRenewable = {}; - for (const auto& entryCluster : area.renewable.clusters) - { - auto& cluster = *entryCluster; - // this is not even necessary - because area.renewable.clusters returns list of only - // ENABLED clusters but let's keep it for now - if (!cluster.enabled) - continue; - auto tmpArrayPerCluster - = calculateAverageTs(cluster.series.timeSeries, cluster.series.timeseriesNumbers); - for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) - { - if (cluster.tsMode == Data::RenewableCluster::productionFactor) - averageTsRenewable[row] - += tmpArrayPerCluster[row] * cluster.unitCount * cluster.nominalCapacity; - else - averageTsRenewable[row] += tmpArrayPerCluster[row]; - } - } - return averageTsRenewable; + return calculateAverageRenewableTsAggregated(area); } - - std::array OptimizedThermalGenerator::calculateAverageRenewableTs( - const Data::Area& area) + else // clusters it is { - if (study.parameters.renewableGeneration.isAggregated()) - { - return calculateAverageRenewableTsAggregated(area); - } - else // clusters it is - { - return calculateAverageRenewableTsClusters(area); - } + return calculateAverageRenewableTsClusters(area); } +} } // namespace Antares::Solver::TSGenerator From aa07321f6a586f55360c49370795e438d9651033 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 14 Nov 2023 12:38:54 +0100 Subject: [PATCH 086/315] in addition to inheritance, lets juts make OptimizedThermalGenerator friend class of GeneratorTempData -- there is just too many private stuff to transfer to private --- .../randomized-thermal-generator/RandomizedGenerator.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/solver/ts-generator/randomized-thermal-generator/RandomizedGenerator.h b/src/solver/ts-generator/randomized-thermal-generator/RandomizedGenerator.h index 0e7a90a0d4..11c00a3941 100644 --- a/src/solver/ts-generator/randomized-thermal-generator/RandomizedGenerator.h +++ b/src/solver/ts-generator/randomized-thermal-generator/RandomizedGenerator.h @@ -16,6 +16,8 @@ namespace Antares::Solver::TSGenerator class GeneratorTempData { + friend class OptimizedThermalGenerator; + public: GeneratorTempData(Data::Study& study, Solver::Progression::Task& progr, IResultWriter& writer); @@ -34,13 +36,11 @@ class GeneratorTempData bool derated; - Solver::Progression::Task& pProgression; - - // I need these two functions for inheritance +private: void writeResultsToDisk(const Data::Area& area, const Data::ThermalCluster& cluster); + int durationGenerator(Data::ThermalLaw law, int expec, double volat, double a, double b); -private: template void prepareIndispoFromLaw(Data::ThermalLaw law, double volatility, @@ -74,6 +74,7 @@ class GeneratorTempData double PPOW[366][102]; String pTempFilename; + Solver::Progression::Task& pProgression; IResultWriter& pWriter; }; From afcd24122a47d1b662bd90766b4c255f0ae5cbef Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 14 Nov 2023 12:59:46 +0100 Subject: [PATCH 087/315] refactor - create separate generator for each mnt group - easier to make it work in parallel later --- .../OptimizedGenerator.cpp | 59 ++++++++----------- .../OptimizedGenerator.h | 18 +++--- src/solver/ts-generator/thermal.cpp | 14 +++-- 3 files changed, 42 insertions(+), 49 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp index 2ed9fbccb4..f14e3b0e39 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp @@ -10,31 +10,20 @@ namespace Antares::Solver::TSGenerator { // optimization problem - methods -void OptimizedThermalGenerator::GenerateOptimizedThermalTimeSeriesPerAllMaintenanceGroups() +void OptimizedThermalGenerator::GenerateOptimizedThermalTimeSeries() { - const auto& activeMaintenanceGroups = maintenanceGroupRepo.activeMaintenanceGroups(); - for (const auto& entryMaintenanceGroup : activeMaintenanceGroups) - { - // timeHorizon, timeStep ENS and Spillage are defined per one MaintenanceGroup - int timeHorizon, timeStep; - double ensCost, spillCost; - std::array residualLoadDailyValues; - auto& maintenanceGroup = *(entryMaintenanceGroup.get()); - // Residual Load (or reference value) array is defined per one MaintenanceGroup - calculateResidualLoad(maintenanceGroup); - residualLoadDailyValues = calculateDailySums(maintenanceGroup.getUsedResidualLoadTS()); - std::tie(ensCost, spillCost) - = calculateMaintenanceGroupENSandSpillageCost(maintenanceGroup); - std::tie(timeStep, timeHorizon) = calculateTimeHorizonAndStep(maintenanceGroup); - GenerateOptimizedThermalTimeSeriesPerOneMaintenanceGroup(maintenanceGroup); - } -} + // timeHorizon, timeStep ENS and Spillage are defined per one MaintenanceGroup + int timeHorizon, timeStep; + double ensCost, spillCost; + std::array residualLoadDailyValues; + // Residual Load (or reference value) array is defined per one MaintenanceGroup + calculateResidualLoad(); + residualLoadDailyValues = calculateDailySums(maintenanceGroup_.getUsedResidualLoadTS()); + std::tie(ensCost, spillCost) = calculateMaintenanceGroupENSandSpillageCost(); + std::tie(timeStep, timeHorizon) = calculateTimeHorizonAndStep(); -void OptimizedThermalGenerator::GenerateOptimizedThermalTimeSeriesPerOneMaintenanceGroup( - Data::MaintenanceGroup& maintenanceGroup) -{ // loop through the elements of weightMap weights_ - for (const auto& entryWeightMap : maintenanceGroup) + for (const auto& entryWeightMap : maintenanceGroup_) { const auto& area = *(entryWeightMap.first); // loop through the thermal clusters inside the area @@ -62,10 +51,10 @@ void OptimizedThermalGenerator::createOptimizationProblemPerCluster(const Data:: averageMaintenanceDuration = calculateAverageMaintenanceDuration(cluster); // this will floor the double value !! std::array maxUnitOutput = calculateMaxUnitOutput(cluster); - uint earliestStartOfFirstMaintenance - = calculateUnitEarliestStartOfFirstMaintenance(cluster, averageMaintenanceDuration, 8); - uint latestStartOfFirstMaintenance - = calculateUnitLatestStartOfFirstMaintenance(cluster, averageMaintenanceDuration, 8); + // uint earliestStartOfFirstMaintenance + // = calculateUnitEarliestStartOfFirstMaintenance(cluster, averageMaintenanceDuration, 8); + // uint latestStartOfFirstMaintenance + // = calculateUnitLatestStartOfFirstMaintenance(cluster, averageMaintenanceDuration, 8); // just playing here - this needs to go into new method - class - operator logs.info() << "CR27-INFO: This cluster is active for mnt planning: " << cluster.getFullName(); @@ -98,11 +87,10 @@ void OptimizedThermalGenerator::createOptimizationProblemPerCluster(const Data:: } // calculate parameters methods - per maintenance group -std::pair OptimizedThermalGenerator::calculateTimeHorizonAndStep( - Data::MaintenanceGroup& maintenanceGroup) +std::pair OptimizedThermalGenerator::calculateTimeHorizonAndStep() { std::vector averageDurationBetweenMaintenances = {}; - for (const auto& entryWeightMap : maintenanceGroup) + for (const auto& entryWeightMap : maintenanceGroup_) { const auto& area = *(entryWeightMap.first); for (auto it = area.thermal.list.mapping.begin(); it != area.thermal.list.mapping.end(); @@ -130,12 +118,11 @@ std::pair OptimizedThermalGenerator::calculateTimeHorizonAndStep( return std::make_pair(0, 0); } -std::pair OptimizedThermalGenerator::calculateMaintenanceGroupENSandSpillageCost( - Data::MaintenanceGroup& maintenanceGroup) +std::pair OptimizedThermalGenerator::calculateMaintenanceGroupENSandSpillageCost() { std::vector ensVector = {}; std::vector spillageVector = {}; - for (const auto& entryWeightMap : maintenanceGroup) + for (const auto& entryWeightMap : maintenanceGroup_) { const auto& area = *(entryWeightMap.first); ensVector.push_back(area.thermal.unsuppliedEnergyCost); @@ -155,7 +142,7 @@ std::pair OptimizedThermalGenerator::calculateMaintenanceGroupEN return std::make_pair(0, 0); } -void OptimizedThermalGenerator::calculateResidualLoad(Data::MaintenanceGroup& maintenanceGroup) +void OptimizedThermalGenerator::calculateResidualLoad() { // create reference value arrays std::array refValueLoad = {}; @@ -164,14 +151,14 @@ void OptimizedThermalGenerator::calculateResidualLoad(Data::MaintenanceGroup& ma std::array refValue = {}; // for phase II - if (maintenanceGroup.type() == Data::MaintenanceGroup::typeTimeserie) + if (maintenanceGroup_.type() == Data::MaintenanceGroup::typeTimeserie) { // read user defined ts - userProvidedResidualLoadTS_ with getter - phase-II return; } // loop through the elements of weightMap weights_ - for (const auto& entryWeightMap : maintenanceGroup) + for (const auto& entryWeightMap : maintenanceGroup_) { const auto& area = *(entryWeightMap.first); const auto weights = (entryWeightMap.second); @@ -191,7 +178,7 @@ void OptimizedThermalGenerator::calculateResidualLoad(Data::MaintenanceGroup& ma for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) refValue[row] = refValueLoad[row] - refValueRor[row] - refValueRenewable[row]; // set ResidualLoadTS - maintenanceGroup.setUsedResidualLoadTS(refValue); + maintenanceGroup_.setUsedResidualLoadTS(refValue); } // calculate parameters methods - per cluster diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index aeddac8386..595c8d28a1 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -34,15 +34,13 @@ class OptimizedThermalGenerator : public GeneratorTempData void allocateProblem(); // this one should be called in constructor. It basically resets all the // vectors in PROBLEME_ANTARES_A_RESOUDRE for new opt problem. - // optimization problem - methods - void GenerateOptimizedThermalTimeSeriesPerOneMaintenanceGroup(Data::MaintenanceGroup& group); + // optimization problem - methods - private void createOptimizationProblemPerCluster(const Data::Area& area, Data::ThermalCluster& cluster); // calculate parameters methods - per maintenance group - std::pair calculateTimeHorizonAndStep(Data::MaintenanceGroup& group); - std::pair calculateMaintenanceGroupENSandSpillageCost( - Data::MaintenanceGroup& group); - void calculateResidualLoad(Data::MaintenanceGroup& group); + std::pair calculateTimeHorizonAndStep(); + std::pair calculateMaintenanceGroupENSandSpillageCost(); + void calculateResidualLoad(); // calculate parameters methods - per cluster uint calculateNumberOfMaintenances(Data::ThermalCluster& cluster, uint timeHorizon); @@ -72,18 +70,19 @@ class OptimizedThermalGenerator : public GeneratorTempData std::array calculateAverageRenewableTsClusters(const Data::Area& area); // variables - Data::MaintenanceGroupRepository& maintenanceGroupRepo; + Data::MaintenanceGroup& maintenanceGroup_; bool globalThermalTSgeneration_; public: void run(); // calls private optimization problem construction methods explicit OptimizedThermalGenerator(Data::Study& study, + Data::MaintenanceGroup& maintenanceGroup, uint year, bool globalThermalTSgeneration, Solver::Progression::Task& progr, IResultWriter& writer) : - GeneratorTempData(study, progr, writer), maintenanceGroupRepo(study.maintenanceGroups) + GeneratorTempData(study, progr, writer), maintenanceGroup_(maintenanceGroup) { currentYear = year; globalThermalTSgeneration_ = globalThermalTSgeneration; @@ -94,7 +93,8 @@ class OptimizedThermalGenerator : public GeneratorTempData ~OptimizedThermalGenerator() = default; - void GenerateOptimizedThermalTimeSeriesPerAllMaintenanceGroups(); + // optimization problem - methods - public + void GenerateOptimizedThermalTimeSeries(); }; } // namespace Antares::Solver::TSGenerator \ No newline at end of file diff --git a/src/solver/ts-generator/thermal.cpp b/src/solver/ts-generator/thermal.cpp index fd25b0fa66..7994f3801b 100644 --- a/src/solver/ts-generator/thermal.cpp +++ b/src/solver/ts-generator/thermal.cpp @@ -73,7 +73,8 @@ bool GenerateOptimizedThermalTimeSeries(Data::Study& study, { // optimized planning should only be called once. // Due to possible thermal refresh span we can end up here more than once - but just ignore it - // even if we set in Scenario playlist that year-1 should be skipped, we will execute this properly + // even if we set in Scenario playlist that year-1 should be skipped, we will execute this + // properly if (year != 0) return true; @@ -81,9 +82,14 @@ bool GenerateOptimizedThermalTimeSeries(Data::Study& study, logs.info() << "Generating optimized thermal time-series"; Solver::Progression::Task progression(study, year, Solver::Progression::sectTSGThermal); - auto generator - = OptimizedThermalGenerator(study, year, globalThermalTSgeneration, progression, writer); - generator.GenerateOptimizedThermalTimeSeriesPerAllMaintenanceGroups(); + const auto& activeMaintenanceGroups = study.maintenanceGroups.activeMaintenanceGroups(); + for (const auto& entryMaintenanceGroup : activeMaintenanceGroups) + { + auto& maintenanceGroup = *(entryMaintenanceGroup.get()); + auto generator = OptimizedThermalGenerator( + study, maintenanceGroup, year, globalThermalTSgeneration, progression, writer); + generator.GenerateOptimizedThermalTimeSeries(); + } return true; } From 75f2b847ab9b1f53172841f6df8ca34e8a796036 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 14 Nov 2023 13:15:08 +0100 Subject: [PATCH 088/315] refactor - setMaintenanceGroupParameters --- .../OptimizedGenerator.cpp | 21 ++++++++++--------- .../OptimizedGenerator.h | 6 ++++++ 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp index f14e3b0e39..0ede989c63 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp @@ -12,16 +12,7 @@ namespace Antares::Solver::TSGenerator // optimization problem - methods void OptimizedThermalGenerator::GenerateOptimizedThermalTimeSeries() { - // timeHorizon, timeStep ENS and Spillage are defined per one MaintenanceGroup - int timeHorizon, timeStep; - double ensCost, spillCost; - std::array residualLoadDailyValues; - // Residual Load (or reference value) array is defined per one MaintenanceGroup - calculateResidualLoad(); - residualLoadDailyValues = calculateDailySums(maintenanceGroup_.getUsedResidualLoadTS()); - std::tie(ensCost, spillCost) = calculateMaintenanceGroupENSandSpillageCost(); - std::tie(timeStep, timeHorizon) = calculateTimeHorizonAndStep(); - + setMaintenanceGroupParameters(); // loop through the elements of weightMap weights_ for (const auto& entryWeightMap : maintenanceGroup_) { @@ -87,6 +78,16 @@ void OptimizedThermalGenerator::createOptimizationProblemPerCluster(const Data:: } // calculate parameters methods - per maintenance group +void OptimizedThermalGenerator::setMaintenanceGroupParameters() +{ + // timeHorizon, timeStep ENS and Spillage are defined per one MaintenanceGroup + // Residual Load (or reference value) array is defined per one MaintenanceGroup + calculateResidualLoad(); + residualLoadDailyValues_ = calculateDailySums(maintenanceGroup_.getUsedResidualLoadTS()); + std::tie(ensCost_, spillCost_) = calculateMaintenanceGroupENSandSpillageCost(); + std::tie(timeStep_, timeHorizon_) = calculateTimeHorizonAndStep(); +} + std::pair OptimizedThermalGenerator::calculateTimeHorizonAndStep() { std::vector averageDurationBetweenMaintenances = {}; diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 595c8d28a1..13d9b34d00 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -38,6 +38,7 @@ class OptimizedThermalGenerator : public GeneratorTempData void createOptimizationProblemPerCluster(const Data::Area& area, Data::ThermalCluster& cluster); // calculate parameters methods - per maintenance group + void setMaintenanceGroupParameters(); std::pair calculateTimeHorizonAndStep(); std::pair calculateMaintenanceGroupENSandSpillageCost(); void calculateResidualLoad(); @@ -72,6 +73,11 @@ class OptimizedThermalGenerator : public GeneratorTempData // variables Data::MaintenanceGroup& maintenanceGroup_; bool globalThermalTSgeneration_; + int timeHorizon_; + int timeStep_; + double ensCost_; + double spillCost_; + std::array residualLoadDailyValues_; public: void run(); // calls private optimization problem construction methods From d71fb085463599bc772efffedaa9b43bc0d39684 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 14 Nov 2023 13:20:46 +0100 Subject: [PATCH 089/315] update call to calculateNumberOfMaintenances --- .../optimized-thermal-generator/OptimizedGenerator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp index 0ede989c63..b83ddaf598 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp @@ -38,7 +38,7 @@ void OptimizedThermalGenerator::createOptimizationProblemPerCluster(const Data:: int numberOfMaintenancesPerUnit; int averageMaintenanceDuration; numberOfMaintenancesPerUnit = calculateNumberOfMaintenances( - cluster, 365); // TODO CR27: get the T-timeHorizon here - parameter or class + cluster, timeHorizon_); averageMaintenanceDuration = calculateAverageMaintenanceDuration(cluster); // this will floor the double value !! std::array maxUnitOutput = calculateMaxUnitOutput(cluster); From 97f097230b2f77027003b37ba31d8ed74fda189f Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 14 Nov 2023 15:41:22 +0100 Subject: [PATCH 090/315] add checks before loops - add loops per scenario nad per length --- .../OptimizedGenerator.cpp | 102 ++++++++++++++++++ .../OptimizedGenerator.h | 10 +- 2 files changed, 110 insertions(+), 2 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp index b83ddaf598..1e0c42f419 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp @@ -13,6 +13,68 @@ namespace Antares::Solver::TSGenerator void OptimizedThermalGenerator::GenerateOptimizedThermalTimeSeries() { setMaintenanceGroupParameters(); + if (!checkMaintenanceGroupParameters()) + return; + + // loop through all scenarios + for (std::size_t scenarioIndex = 0; scenarioIndex < scenarioNumber_; ++scenarioIndex) + { + int optPrbTimeStart = 0; + int optPrbTimeEnd = timeHorizon_; + + // loop till the end of scenario length + while (optPrbTimeStart <= scenarioLength_ * DAYS_PER_YEAR) + { + createOptimizationProblemPerGroup(optPrbTimeStart, optPrbTimeEnd); + // do the preparation for the new optimization process here + // Do the optimization here + // ... + // do the optimization post-processing here & + // do the writing off the result here + + // Update the time values for the next iteration + optPrbTimeStart += timeStep_; + optPrbTimeEnd += timeStep_; + } + } +} + +void OptimizedThermalGenerator::createOptimizationProblemPerGroup(int optProblemStart, + int optProblemEnd) +{ + // TODO CR27: create methods - each line separate method - maybe new/separate class ??@!! + // group methods by var/bounds/cost/constraint in separate *.h and *.cpp files + + // create VARIABLES per day - ENS[t], Spill[t] + // - we just need optProblemStart and optProblemEnd for that + + // create VARIABLES per day and per cluster-unit - P[t][u] + + // create VARIABLES per day, per cluster-unit and per maintenance - s[t][u][m] & e[t][u][m] + + // BOUNDS per each day - bounds-per-each-day[t] - ENS[t] >= 0, Spill[t] >= 0 + + // BOUNDS per day and per each unit - bounds-per-each-day+unit[t][u] - P[t][u] >= 0 + + // BOUNDS per day, per each unit and per each mnt - bounds-per-each-day+unit+mnt[t][u][m] + // - s[t][u][m]-> [0, 1] and e[t][u][m]-> [0, 1] + + // create OBJECTIVE FUNCTION - sum through [t] and sum through [u] + + // load balance CONSTRAINTS - constraint-per-each-day[t] - we have sum through [u] inside of it + + // CONSTRAINTS per units - constraint-per-each-unit[t-fixed][u][m-fixed] + + // CONSTRAINTS per units and per maintenance - constraint-per-each-unit+mnt[t-fixed=0/T][u][m] + + // CONSTRAINTS per days, per units and per maintenance - constraint-per-each-day+unit+mnt[t][u][m] + + // CONSTRAINTS per days and per units - constraint-per-each-day+unit[t][u][m-sum per m] + + // solve problem + + // reset problem structure + // loop through the elements of weightMap weights_ for (const auto& entryWeightMap : maintenanceGroup_) { @@ -88,6 +150,26 @@ void OptimizedThermalGenerator::setMaintenanceGroupParameters() std::tie(timeStep_, timeHorizon_) = calculateTimeHorizonAndStep(); } +bool OptimizedThermalGenerator::checkMaintenanceGroupParameters() +{ + if (timeStep_ == 0) + { + logs.info() << "Maintenance group: " << maintenanceGroup_.name() + << ": The timeseries generation will be skiped: timeStep = 0. It is possible " + "that the maintenance group has no clusters or the cluster data is wrong"; + return false; + } + if (timeHorizon_ == 0) + { + logs.info() + << "Maintenance group: " << maintenanceGroup_.name() + << ": The timeseries generation will be skiped: timeHorizon = 0. It is possible " + "that the maintenance group has no clusters or the cluster data is wrong"; + return false; + } + return true; +} + std::pair OptimizedThermalGenerator::calculateTimeHorizonAndStep() { std::vector averageDurationBetweenMaintenances = {}; @@ -298,6 +380,26 @@ std::array OptimizedThermalGenerator::calculateAverageTs return averageTs; } +bool OptimizedThermalGenerator::checkClusterData(const Data::Area& area, + Data::ThermalCluster& cluster) +{ + if (!cluster.prepro) + { + logs.error() << "Cluster: " << area.name << '/' << cluster.name() + << ": The timeseries will not be regenerated. All data " + "related to the ts-generator for " + << "'thermal' have been released."; + return false; + } + + if (0 == cluster.unitCount || 0 == cluster.nominalCapacity) + { + cluster.series.timeSeries.reset(1, 8760); + return false; + } + return true; +} + // calculate Average time-series functions std::array OptimizedThermalGenerator::calculateAverageLoadTs( const Data::Area& area) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 13d9b34d00..3109d2245f 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -35,10 +35,12 @@ class OptimizedThermalGenerator : public GeneratorTempData // vectors in PROBLEME_ANTARES_A_RESOUDRE for new opt problem. // optimization problem - methods - private + void createOptimizationProblemPerGroup(int start, int end); void createOptimizationProblemPerCluster(const Data::Area& area, Data::ThermalCluster& cluster); // calculate parameters methods - per maintenance group void setMaintenanceGroupParameters(); + bool checkMaintenanceGroupParameters(); std::pair calculateTimeHorizonAndStep(); std::pair calculateMaintenanceGroupENSandSpillageCost(); void calculateResidualLoad(); @@ -61,6 +63,7 @@ class OptimizedThermalGenerator : public GeneratorTempData const std::array& hourlyValues); std::array calculateAverageTs(const Matrix& tsValue, const Matrix& tsNumbers); + bool checkClusterData(const Data::Area& area, Data::ThermalCluster& cluster); // calculate Average time-series functions std::array calculateAverageLoadTs(const Data::Area& area); @@ -73,6 +76,8 @@ class OptimizedThermalGenerator : public GeneratorTempData // variables Data::MaintenanceGroup& maintenanceGroup_; bool globalThermalTSgeneration_; + int scenarioLength_; + int scenarioNumber_; int timeHorizon_; int timeStep_; double ensCost_; @@ -92,8 +97,9 @@ class OptimizedThermalGenerator : public GeneratorTempData { currentYear = year; globalThermalTSgeneration_ = globalThermalTSgeneration; - nbThermalTimeseries = study.parameters.maintenancePlanning.getScenarioLength() - * study.parameters.maintenancePlanning.getScenarioNumber(); + scenarioLength_ = study.parameters.maintenancePlanning.getScenarioLength(); + scenarioNumber_ = study.parameters.maintenancePlanning.getScenarioNumber(); + nbThermalTimeseries = scenarioLength_ * scenarioNumber_; // allocateProblem(); } From 492d8c8e5bf61f5db1bd1d8828209dd14aa7f506 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 14 Nov 2023 16:27:07 +0100 Subject: [PATCH 091/315] clean --- .../optimized-thermal-generator/OptimizedGenerator.cpp | 1 + src/solver/ts-generator/thermal.cpp | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp index 1e0c42f419..b0f7df9816 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp @@ -167,6 +167,7 @@ bool OptimizedThermalGenerator::checkMaintenanceGroupParameters() "that the maintenance group has no clusters or the cluster data is wrong"; return false; } + // add some more check here if necessary! return true; } diff --git a/src/solver/ts-generator/thermal.cpp b/src/solver/ts-generator/thermal.cpp index 7994f3801b..8259d8e77e 100644 --- a/src/solver/ts-generator/thermal.cpp +++ b/src/solver/ts-generator/thermal.cpp @@ -40,7 +40,7 @@ bool GenerateRandomizedThermalTimeSeries(Data::Study& study, { logs.info(); logs.info() << "Generating randomized thermal time-series"; - Solver::Progression::Task progression(study, year, Solver::Progression::sectTSGThermal); // TMP.INFO CR27: parallel work ??!! - NO + Solver::Progression::Task progression(study, year, Solver::Progression::sectTSGThermal); auto* generator = new GeneratorTempData(study, progression, writer); @@ -52,7 +52,7 @@ bool GenerateRandomizedThermalTimeSeries(Data::Study& study, { auto& cluster = *(it->second); - if (cluster.doWeGenerateTS(globalThermalTSgeneration) && refreshTSonCurrentYear) // TMP.INFO CR27: we decide here for each cluster whether we generate TS or not - We need to get rid of refreshTSonCurrentYear - not important for mnt-planning - doWeGenerateTS is still ok to use! + if (cluster.doWeGenerateTS(globalThermalTSgeneration) && refreshTSonCurrentYear) { (*generator)(area, cluster); } From be54e64f4c394f7beec13109e993c12939f62233 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 14 Nov 2023 17:56:34 +0100 Subject: [PATCH 092/315] create opt problem formulation structure files --- src/solver/ts-generator/CMakeLists.txt | 7 +++ .../CreateVariables.cpp | 40 +++++++++++++ .../OptimizedGenerator.cpp | 35 +---------- .../OptimizedGenerator.h | 28 ++++++--- .../ResetProblem.cpp | 14 +++++ .../SetProblemConstraints.cpp | 33 +++++++++++ .../SetProblemCost.cpp | 15 +++++ .../SetVariableBounds.cpp | 58 +++++++++++++++++++ .../SolveProbem.cpp | 25 ++++++++ 9 files changed, 216 insertions(+), 39 deletions(-) create mode 100644 src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp create mode 100644 src/solver/ts-generator/optimized-thermal-generator/ResetProblem.cpp create mode 100644 src/solver/ts-generator/optimized-thermal-generator/SetProblemConstraints.cpp create mode 100644 src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp create mode 100644 src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp create mode 100644 src/solver/ts-generator/optimized-thermal-generator/SolveProbem.cpp diff --git a/src/solver/ts-generator/CMakeLists.txt b/src/solver/ts-generator/CMakeLists.txt index 75846dde21..b401f671a2 100644 --- a/src/solver/ts-generator/CMakeLists.txt +++ b/src/solver/ts-generator/CMakeLists.txt @@ -17,6 +17,13 @@ set(SRC_OPTIMIZEDGENERATORS optimized-thermal-generator/pre-scenario-builder.cpp optimized-thermal-generator/OptimizedGenerator.h optimized-thermal-generator/OptimizedGenerator.cpp + optimized-thermal-generator/CreateVariables.cpp + optimized-thermal-generator/SetVariableBounds.cpp + optimized-thermal-generator/SetProblemConstraints.cpp + optimized-thermal-generator/SetProblemCost.cpp + optimized-thermal-generator/ResetProblem.cpp + optimized-thermal-generator/SolveProbem.cpp + ) source_group("ts-generator\\optimized-thermal-generator" FILES ${SRC_OPTIMIZEDGENERATORS}) diff --git a/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp b/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp new file mode 100644 index 0000000000..24651c8380 --- /dev/null +++ b/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp @@ -0,0 +1,40 @@ +// +// Created by milos on 14/11/23. +// + +#include "OptimizedGenerator.h" + +namespace Antares::Solver::TSGenerator +{ +void OptimizedThermalGenerator::buildProblemVariables() +{ + countVariables(); + buildEnsAndSpillageVariables(); + buildUnitPowerOutputVariables(); + buildStartEndMntVariables(); +} + +void OptimizedThermalGenerator::countVariables() +{ + return; +} + +// create VARIABLES per day - ENS[t], Spill[t] +void OptimizedThermalGenerator::buildEnsAndSpillageVariables() +{ + return; +} + +// create VARIABLES per day and per cluster-unit - P[t][u] +void OptimizedThermalGenerator::buildUnitPowerOutputVariables() +{ + return; +} + +// create VARIABLES per day, per cluster-unit and per maintenance - s[t][u][m] & e[t][u][m] +void OptimizedThermalGenerator::buildStartEndMntVariables() +{ + return; +} + +} // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp index b0f7df9816..79f283c3a2 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp @@ -42,39 +42,9 @@ void OptimizedThermalGenerator::GenerateOptimizedThermalTimeSeries() void OptimizedThermalGenerator::createOptimizationProblemPerGroup(int optProblemStart, int optProblemEnd) { - // TODO CR27: create methods - each line separate method - maybe new/separate class ??@!! - // group methods by var/bounds/cost/constraint in separate *.h and *.cpp files - - // create VARIABLES per day - ENS[t], Spill[t] - // - we just need optProblemStart and optProblemEnd for that - - // create VARIABLES per day and per cluster-unit - P[t][u] - - // create VARIABLES per day, per cluster-unit and per maintenance - s[t][u][m] & e[t][u][m] - - // BOUNDS per each day - bounds-per-each-day[t] - ENS[t] >= 0, Spill[t] >= 0 - - // BOUNDS per day and per each unit - bounds-per-each-day+unit[t][u] - P[t][u] >= 0 - - // BOUNDS per day, per each unit and per each mnt - bounds-per-each-day+unit+mnt[t][u][m] - // - s[t][u][m]-> [0, 1] and e[t][u][m]-> [0, 1] - - // create OBJECTIVE FUNCTION - sum through [t] and sum through [u] - - // load balance CONSTRAINTS - constraint-per-each-day[t] - we have sum through [u] inside of it - - // CONSTRAINTS per units - constraint-per-each-unit[t-fixed][u][m-fixed] - - // CONSTRAINTS per units and per maintenance - constraint-per-each-unit+mnt[t-fixed=0/T][u][m] - - // CONSTRAINTS per days, per units and per maintenance - constraint-per-each-day+unit+mnt[t][u][m] - - // CONSTRAINTS per days and per units - constraint-per-each-day+unit[t][u][m-sum per m] - - // solve problem - - // reset problem structure + runOptimizationProblem(); + // just playing here - will ue this loops later for opt problem formulation // loop through the elements of weightMap weights_ for (const auto& entryWeightMap : maintenanceGroup_) { @@ -88,6 +58,7 @@ void OptimizedThermalGenerator::createOptimizationProblemPerGroup(int optProblem ++pProgression; } } + // end play } void OptimizedThermalGenerator::createOptimizationProblemPerCluster(const Data::Area& area, diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 3109d2245f..bf61ea8b8b 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -24,15 +24,31 @@ class OptimizedThermalGenerator : public GeneratorTempData // define here variables/structures that will help us build optimization problem // optimization problem construction methods - void calculateParameters(); void buildProblemVariables(); + void countVariables(); + void buildEnsAndSpillageVariables(); + void buildUnitPowerOutputVariables(); + void buildStartEndMntVariables(); + void setVariableBounds(); - void buildProblemConstraintsLHS(); - void buildProblemConstraintsRHS(); + void setEnsAndSpillageBounds(); + void setUnitPowerOutputBounds(); + void setStartEndMntBounds(); + void setFirstMntStartBounds(); + void setAllMntMustStartBounds(); + + void buildProblemConstraints(); + void buildLoadBalanceConstraints(); + void setStartEndMntLogicConstraints(); + void setMaxUnitOutputConstraints(); + // void buildProblemConstraintsRHS(); // let's do LHS & RHS in one go. Easier!? + void setProblemCost(); void solveProblem(); - void allocateProblem(); // this one should be called in constructor. It basically resets all the - // vectors in PROBLEME_ANTARES_A_RESOUDRE for new opt problem. + void resetProblem(); + + void runOptimizationProblem(); + // optimization problem - methods - private void createOptimizationProblemPerGroup(int start, int end); @@ -85,8 +101,6 @@ class OptimizedThermalGenerator : public GeneratorTempData std::array residualLoadDailyValues_; public: - void run(); // calls private optimization problem construction methods - explicit OptimizedThermalGenerator(Data::Study& study, Data::MaintenanceGroup& maintenanceGroup, uint year, diff --git a/src/solver/ts-generator/optimized-thermal-generator/ResetProblem.cpp b/src/solver/ts-generator/optimized-thermal-generator/ResetProblem.cpp new file mode 100644 index 0000000000..37f836700d --- /dev/null +++ b/src/solver/ts-generator/optimized-thermal-generator/ResetProblem.cpp @@ -0,0 +1,14 @@ +// +// Created by milos on 14/11/23. +// + +#include "OptimizedGenerator.h" + +namespace Antares::Solver::TSGenerator +{ +void OptimizedThermalGenerator::resetProblem() +{ + return; +} + +} // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/SetProblemConstraints.cpp b/src/solver/ts-generator/optimized-thermal-generator/SetProblemConstraints.cpp new file mode 100644 index 0000000000..7c09f6c45b --- /dev/null +++ b/src/solver/ts-generator/optimized-thermal-generator/SetProblemConstraints.cpp @@ -0,0 +1,33 @@ +// +// Created by milos on 14/11/23. +// + +#include "OptimizedGenerator.h" + +namespace Antares::Solver::TSGenerator +{ +void OptimizedThermalGenerator::buildProblemConstraints() +{ + buildLoadBalanceConstraints(); + setStartEndMntLogicConstraints(); + setMaxUnitOutputConstraints(); +} + +// load balance CONSTRAINTS - constraint-per-each-day[t] - we have sum through [u] inside of it +void OptimizedThermalGenerator::buildLoadBalanceConstraints() +{ + return; +} + +// CONSTRAINTS per days, per units and per maintenance - constraint-per-each-day+unit+mnt[t][u][m] +void OptimizedThermalGenerator::setStartEndMntLogicConstraints() +{ + return; +} +// CONSTRAINTS per days and per units - constraint-per-each-day+unit[t][u][m-sum per m] +void OptimizedThermalGenerator::setMaxUnitOutputConstraints() +{ + return; +} + +} // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp b/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp new file mode 100644 index 0000000000..70a5b68e0d --- /dev/null +++ b/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp @@ -0,0 +1,15 @@ +// +// Created by milos on 14/11/23. +// + +#include "OptimizedGenerator.h" + +namespace Antares::Solver::TSGenerator +{ +// create OBJECTIVE FUNCTION - sum through [t] and sum through [u] +void OptimizedThermalGenerator::setProblemCost() +{ + return; +} + +} // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp b/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp new file mode 100644 index 0000000000..e46c80308b --- /dev/null +++ b/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp @@ -0,0 +1,58 @@ +// +// Created by milos on 14/11/23. +// + +#include "OptimizedGenerator.h" + +namespace Antares::Solver::TSGenerator +{ +void OptimizedThermalGenerator::setVariableBounds() +{ + setEnsAndSpillageBounds(); + setUnitPowerOutputBounds(); + setStartEndMntBounds(); + setFirstMntStartBounds(); + setAllMntMustStartBounds(); +} + +// BOUNDS per each day - bounds-per-each-day[t] - ENS[t] >= 0, Spill[t] >= 0 +void OptimizedThermalGenerator::setEnsAndSpillageBounds() +{ + return; +} + +// BOUNDS per day and per each unit - bounds-per-each-day+unit[t][u] - P[t][u] >= 0 +void OptimizedThermalGenerator::setUnitPowerOutputBounds() +{ + return; +} + +// BOUNDS per day, per each unit and per each mnt - bounds-per-each-day+unit+mnt[t][u][m] +// - s[t][u][m]-> [0, 1] and e[t][u][m]-> [0, 1] +void OptimizedThermalGenerator::setStartEndMntBounds() +{ + return; +} + +// TODO CR27: see if to make this bound or constraint - +// it is definitely easier to do set it as a fix bound - +// but the solver might go crazy - as for adq.patch + +// BOUNDS/CONSTRAINTS per units - constraint-per-each-unit[t-fixed][u][m-fixed] +// first maintenance must start between tauLower and tauUpper +// start[tauLower-1][u][1] = 0 +// start[tauUpper][u][1] = 1 +void OptimizedThermalGenerator::setFirstMntStartBounds() +{ + return; +} + +// BOUNDS/CONSTRAINTS per units and per maintenance - constraint-per-each-unit+mnt[t-fixed=0/T][u][m] +// end[0][u][q] = 0 // no maintenance can end in first day +// start[T][u][q] = 1 // T - end Day (simulation end) // all maintenance must start till last day +void OptimizedThermalGenerator::setAllMntMustStartBounds() +{ + return; +} + +} // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/SolveProbem.cpp b/src/solver/ts-generator/optimized-thermal-generator/SolveProbem.cpp new file mode 100644 index 0000000000..cf51648c72 --- /dev/null +++ b/src/solver/ts-generator/optimized-thermal-generator/SolveProbem.cpp @@ -0,0 +1,25 @@ +// +// Created by milos on 14/11/23. +// + +#include "OptimizedGenerator.h" + +namespace Antares::Solver::TSGenerator +{ +// call all methods +void OptimizedThermalGenerator::runOptimizationProblem() +{ + buildProblemVariables(); + setVariableBounds(); + buildProblemConstraints(); + setProblemCost(); + solveProblem(); + resetProblem(); +} +// retrieve and check the results if optimization was successful +void OptimizedThermalGenerator::solveProblem() +{ + return; +} + +} // namespace Antares::Solver::TSGenerator From 99dabaad1501a5b5eb8c0ee96c5b5231af5b14b6 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 14 Nov 2023 18:39:23 +0100 Subject: [PATCH 093/315] refactor - class OptProblemSettings --- src/solver/ts-generator/CMakeLists.txt | 1 + .../AuxillaryStructures.h | 19 +++++++++++++ .../OptimizedGenerator.cpp | 27 +++++++++---------- .../OptimizedGenerator.h | 5 ++-- 4 files changed, 35 insertions(+), 17 deletions(-) create mode 100644 src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h diff --git a/src/solver/ts-generator/CMakeLists.txt b/src/solver/ts-generator/CMakeLists.txt index b401f671a2..340994beaa 100644 --- a/src/solver/ts-generator/CMakeLists.txt +++ b/src/solver/ts-generator/CMakeLists.txt @@ -13,6 +13,7 @@ source_group("ts-generator\\randomized-thermal-generator" FILES ${SRC_RANDOMIZED # Optimized-thermal-ts-generator # set(SRC_OPTIMIZEDGENERATORS + optimized-thermal-generator/AuxillaryStructures.h optimized-thermal-generator/pre-scenario-builder.h optimized-thermal-generator/pre-scenario-builder.cpp optimized-thermal-generator/OptimizedGenerator.h diff --git a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h new file mode 100644 index 0000000000..58b1995a1d --- /dev/null +++ b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h @@ -0,0 +1,19 @@ +// +// Created by milos on 14/11/23. +// + +//#include "OptimizedGenerator.h" + +namespace Antares::Solver::TSGenerator +{ + +class OptProblemSettings final +{ +public: + OptProblemSettings() = default; + + int optProblemStartTime; + int optProblemEndTime; +}; + +} // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp index 79f283c3a2..a51e05b3f7 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp @@ -19,31 +19,28 @@ void OptimizedThermalGenerator::GenerateOptimizedThermalTimeSeries() // loop through all scenarios for (std::size_t scenarioIndex = 0; scenarioIndex < scenarioNumber_; ++scenarioIndex) { - int optPrbTimeStart = 0; - int optPrbTimeEnd = timeHorizon_; - + OptProblemSettings optSett; + optSett.optProblemStartTime = 0; + optSett.optProblemEndTime = timeHorizon_; // loop till the end of scenario length - while (optPrbTimeStart <= scenarioLength_ * DAYS_PER_YEAR) + while (optSett.optProblemStartTime <= scenarioLength_ * DAYS_PER_YEAR) { - createOptimizationProblemPerGroup(optPrbTimeStart, optPrbTimeEnd); - // do the preparation for the new optimization process here - // Do the optimization here - // ... - // do the optimization post-processing here & - // do the writing off the result here + createOptimizationProblemPerGroup(optSett); // Update the time values for the next iteration - optPrbTimeStart += timeStep_; - optPrbTimeEnd += timeStep_; + optSett.optProblemStartTime += timeStep_; + optSett.optProblemEndTime += timeStep_; } } } -void OptimizedThermalGenerator::createOptimizationProblemPerGroup(int optProblemStart, - int optProblemEnd) +void OptimizedThermalGenerator::createOptimizationProblemPerGroup(OptProblemSettings& optSett) { runOptimizationProblem(); - + // ... + // do the optimization post-processing here & + // do the writing off the result here + // just playing here - will ue this loops later for opt problem formulation // loop through the elements of weightMap weights_ for (const auto& entryWeightMap : maintenanceGroup_) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index bf61ea8b8b..c4d73135dd 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -5,8 +5,9 @@ #pragma once #include "../randomized-thermal-generator/RandomizedGenerator.h" -#include "../../../libs/antares/study/maintenance_planning/MaintenanceGroupRepository.h" +//#include "../../../libs/antares/study/maintenance_planning/MaintenanceGroupRepository.h" #include "../../../libs/antares/study/maintenance_planning/MaintenanceGroup.h" +#include "AuxillaryStructures.h" namespace Antares::Solver::TSGenerator { @@ -51,7 +52,7 @@ class OptimizedThermalGenerator : public GeneratorTempData // optimization problem - methods - private - void createOptimizationProblemPerGroup(int start, int end); + void createOptimizationProblemPerGroup(OptProblemSettings& optSett); void createOptimizationProblemPerCluster(const Data::Area& area, Data::ThermalCluster& cluster); // calculate parameters methods - per maintenance group From 7c0dd5b8b0bc51d1385996aa5a7ffdd5161a804d Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 14 Nov 2023 18:58:11 +0100 Subject: [PATCH 094/315] add auxillary method dayOfTheYear --- .../optimized-thermal-generator/OptimizedGenerator.cpp | 9 +++++++-- .../optimized-thermal-generator/OptimizedGenerator.h | 3 ++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp index a51e05b3f7..138e205ca1 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp @@ -34,13 +34,13 @@ void OptimizedThermalGenerator::GenerateOptimizedThermalTimeSeries() } } -void OptimizedThermalGenerator::createOptimizationProblemPerGroup(OptProblemSettings& optSett) +void OptimizedThermalGenerator::createOptimizationProblemPerGroup(const OptProblemSettings& optSett) { runOptimizationProblem(); // ... // do the optimization post-processing here & // do the writing off the result here - + // just playing here - will ue this loops later for opt problem formulation // loop through the elements of weightMap weights_ for (const auto& entryWeightMap : maintenanceGroup_) @@ -369,6 +369,11 @@ bool OptimizedThermalGenerator::checkClusterData(const Data::Area& area, return true; } +int OptimizedThermalGenerator::dayOfTheYear(int optimizationDay) +{ + return optimizationDay % DAYS_PER_YEAR; +} + // calculate Average time-series functions std::array OptimizedThermalGenerator::calculateAverageLoadTs( const Data::Area& area) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index c4d73135dd..df6877d371 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -52,7 +52,7 @@ class OptimizedThermalGenerator : public GeneratorTempData // optimization problem - methods - private - void createOptimizationProblemPerGroup(OptProblemSettings& optSett); + void createOptimizationProblemPerGroup(const OptProblemSettings& optSett); void createOptimizationProblemPerCluster(const Data::Area& area, Data::ThermalCluster& cluster); // calculate parameters methods - per maintenance group @@ -81,6 +81,7 @@ class OptimizedThermalGenerator : public GeneratorTempData std::array calculateAverageTs(const Matrix& tsValue, const Matrix& tsNumbers); bool checkClusterData(const Data::Area& area, Data::ThermalCluster& cluster); + int dayOfTheYear(int optimizationDay); // calculate Average time-series functions std::array calculateAverageLoadTs(const Data::Area& area); From 28cf562fad78a95afe82432f7c07e8643a0e486d Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 14 Nov 2023 18:59:19 +0100 Subject: [PATCH 095/315] clean --- .../optimized-thermal-generator/OptimizedGenerator.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index df6877d371..a672e20ecd 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -5,7 +5,6 @@ #pragma once #include "../randomized-thermal-generator/RandomizedGenerator.h" -//#include "../../../libs/antares/study/maintenance_planning/MaintenanceGroupRepository.h" #include "../../../libs/antares/study/maintenance_planning/MaintenanceGroup.h" #include "AuxillaryStructures.h" From 30a492e159c11e76ee62e7aa51aaabc0ad832528 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 14 Nov 2023 20:15:49 +0100 Subject: [PATCH 096/315] create OptimizationProblemVariableIndexes --- .../AuxillaryStructures.h | 36 +++++++++++++++++-- .../OptimizedGenerator.cpp | 10 ++++++ .../OptimizedGenerator.h | 1 + 3 files changed, 45 insertions(+), 2 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h index 58b1995a1d..4386e7f139 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h +++ b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h @@ -2,8 +2,6 @@ // Created by milos on 14/11/23. // -//#include "OptimizedGenerator.h" - namespace Antares::Solver::TSGenerator { @@ -16,4 +14,38 @@ class OptProblemSettings final int optProblemEndTime; }; +struct OptimizationProblemVariableIndexesPerUnit +{ + int P; // index of P[t][u] variable + + // number of elements in the vector is total number of maintenances of unit + std::vector start; // index of s[t][u][m] variable + std::vector end; // index of e[t][u][m] variable +}; + +struct OptimizationProblemVariableIndexesPerCluster +{ + // number of elements in the vector is total number of units in cluster + std::vector unit; +}; + +struct OptimizationProblemVariableIndexesPerArea +{ + // number of elements in the vector is total number of clusters in area + std::vector cluster; +}; + +struct OptimizationProblemVariableIndexesPerDay +{ + int Ens; // index of ENS[t] variable + int Spill; // index of Spillage[t] variable + // number of elements in the vector is total number of areas in optimization problem + std::vector area; +}; +struct OptimizationProblemVariableIndexes +{ + // number of elements in the vector is total number of days in optimization problem + std::vector day; +}; + } // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp index 138e205ca1..b4f0be8995 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp @@ -55,6 +55,16 @@ void OptimizedThermalGenerator::createOptimizationProblemPerGroup(const OptProbl ++pProgression; } } + + indexes.day.push_back(OptimizationProblemVariableIndexesPerDay()); + indexes.day[0].Ens = 1; + indexes.day[0].Spill = 2; + indexes.day[0].area.push_back(OptimizationProblemVariableIndexesPerArea()); + indexes.day[0].area[0].cluster.push_back(OptimizationProblemVariableIndexesPerCluster()); + indexes.day[0].area[0].cluster[0].unit.push_back(OptimizationProblemVariableIndexesPerUnit()); + indexes.day[0].area[0].cluster[0].unit[0].P = 100; + indexes.day[0].area[0].cluster[0].unit[0].start.push_back(55); + indexes.day[0].area[0].cluster[0].unit[0].end.push_back(155); // end play } diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index a672e20ecd..e9b6e71ad8 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -100,6 +100,7 @@ class OptimizedThermalGenerator : public GeneratorTempData double ensCost_; double spillCost_; std::array residualLoadDailyValues_; + OptimizationProblemVariableIndexes indexes; public: explicit OptimizedThermalGenerator(Data::Study& study, From d1383f4cb3e41272ad16542adb57ef5340a90fbf Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 14 Nov 2023 21:53:34 +0100 Subject: [PATCH 097/315] improve checks --- .../OptimizedGenerator.cpp | 22 ++++++++++++++----- .../OptimizedGenerator.h | 4 +--- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp index b4f0be8995..ea64218ad7 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp @@ -134,7 +134,8 @@ bool OptimizedThermalGenerator::checkMaintenanceGroupParameters() { logs.info() << "Maintenance group: " << maintenanceGroup_.name() << ": The timeseries generation will be skiped: timeStep = 0. It is possible " - "that the maintenance group has no clusters or the cluster data is wrong"; + "that the maintenance group has no clusters designated for maintenance " + "planning or, at least one cluster has interPoPeriod = 0"; return false; } if (timeHorizon_ == 0) @@ -142,7 +143,8 @@ bool OptimizedThermalGenerator::checkMaintenanceGroupParameters() logs.info() << "Maintenance group: " << maintenanceGroup_.name() << ": The timeseries generation will be skiped: timeHorizon = 0. It is possible " - "that the maintenance group has no clusters or the cluster data is wrong"; + "that the maintenance group has no clusters designated for maintenance " + "planning or, at all cluster have interPoPeriod = 0"; return false; } // add some more check here if necessary! @@ -247,6 +249,17 @@ void OptimizedThermalGenerator::calculateResidualLoad() uint OptimizedThermalGenerator::calculateNumberOfMaintenances(Data::ThermalCluster& cluster, uint timeHorizon) { + // timeHorizon cannot be 0. The whole maintenance group would be skipped if this happened + // on the other hand interPoPeriod can be 0. So we say at least 2 maintenance if this happens + uint minNumberOfMaintenances = 2; + if (cluster.interPoPeriod == 0) + { + logs.warning() << "Cluster: " << cluster.getFullName() + << "has interPoPeriod = 0. Number of maintenances for all units inside this " + "cluster will be set to 2"; + return minNumberOfMaintenances; + } + return timeHorizon / cluster.interPoPeriod; // floor } @@ -359,12 +372,11 @@ std::array OptimizedThermalGenerator::calculateAverageTs return averageTs; } -bool OptimizedThermalGenerator::checkClusterData(const Data::Area& area, - Data::ThermalCluster& cluster) +bool OptimizedThermalGenerator::checkClusterData(Data::ThermalCluster& cluster) { if (!cluster.prepro) { - logs.error() << "Cluster: " << area.name << '/' << cluster.name() + logs.error() << "Cluster: " << cluster.getFullName() << ": The timeseries will not be regenerated. All data " "related to the ts-generator for " << "'thermal' have been released."; diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index e9b6e71ad8..921e411a5c 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -21,8 +21,6 @@ class OptimizedThermalGenerator : public GeneratorTempData Question: can we still use struct PROBLEME_ANTARES_A_RESOUDRE ?! - no we use MPSolver class */ - // define here variables/structures that will help us build optimization problem - // optimization problem construction methods void buildProblemVariables(); void countVariables(); @@ -79,7 +77,7 @@ class OptimizedThermalGenerator : public GeneratorTempData const std::array& hourlyValues); std::array calculateAverageTs(const Matrix& tsValue, const Matrix& tsNumbers); - bool checkClusterData(const Data::Area& area, Data::ThermalCluster& cluster); + bool checkClusterData(Data::ThermalCluster& cluster); int dayOfTheYear(int optimizationDay); // calculate Average time-series functions From 0c2834b7e238e8d8a7c55a7b25d82d57d78f5d7d Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Thu, 16 Nov 2023 23:59:22 +0100 Subject: [PATCH 098/315] earliest/latest start of the first maintenance TODO --- .../optimized-thermal-generator/OptimizedGenerator.cpp | 8 +++++--- .../optimized-thermal-generator/OptimizedGenerator.h | 4 ++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp index ea64218ad7..22514bd7b0 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp @@ -7,6 +7,7 @@ #include #include +const uint minNumberOfMaintenances = 2; namespace Antares::Solver::TSGenerator { // optimization problem - methods @@ -251,7 +252,6 @@ uint OptimizedThermalGenerator::calculateNumberOfMaintenances(Data::ThermalClust { // timeHorizon cannot be 0. The whole maintenance group would be skipped if this happened // on the other hand interPoPeriod can be 0. So we say at least 2 maintenance if this happens - uint minNumberOfMaintenances = 2; if (cluster.interPoPeriod == 0) { logs.warning() << "Cluster: " << cluster.getFullName() @@ -297,11 +297,12 @@ std::array OptimizedThermalGenerator::calculateMaxUnitOut } // calculate parameters methods - per cluster-Unit -uint OptimizedThermalGenerator::calculateUnitEarliestStartOfFirstMaintenance( +int OptimizedThermalGenerator::calculateUnitEarliestStartOfFirstMaintenance( Data::ThermalCluster& cluster, int avrMntDuration, uint unitIndex) { + // earliest start of the first maintenance of unit u (beginning of the window, can be negative): // TODO CR27: Ask Hugo?! if (unitIndex < cluster.daysSinceLastMaintenance.size()) { return std::max( @@ -315,11 +316,12 @@ uint OptimizedThermalGenerator::calculateUnitEarliestStartOfFirstMaintenance( } } -uint OptimizedThermalGenerator::calculateUnitLatestStartOfFirstMaintenance( +int OptimizedThermalGenerator::calculateUnitLatestStartOfFirstMaintenance( Data::ThermalCluster& cluster, int avrMntDuration, uint unitIndex) { + // latest start of the first maintenance of unit u (end of the window, must be positive): if (unitIndex < cluster.daysSinceLastMaintenance.size()) { return std::max( diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 921e411a5c..b56e64271a 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -65,10 +65,10 @@ class OptimizedThermalGenerator : public GeneratorTempData std::array calculateMaxUnitOutput(Data::ThermalCluster& cluster); // calculate parameters methods - per cluster-Unit - uint calculateUnitEarliestStartOfFirstMaintenance(Data::ThermalCluster& cluster, + int calculateUnitEarliestStartOfFirstMaintenance(Data::ThermalCluster& cluster, int avrMntDuration, uint unitIndex); - uint calculateUnitLatestStartOfFirstMaintenance(Data::ThermalCluster& cluster, + int calculateUnitLatestStartOfFirstMaintenance(Data::ThermalCluster& cluster, int avrMntDuration, uint unitIndex); From 95cba2ed3783095fbf113df1a517d22534ec6609 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Fri, 17 Nov 2023 10:24:51 +0100 Subject: [PATCH 099/315] add static - minNumberOfMaintenances --- .../optimized-thermal-generator/OptimizedGenerator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp index 22514bd7b0..8c83d2a6af 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp @@ -7,7 +7,7 @@ #include #include -const uint minNumberOfMaintenances = 2; +static const uint minNumberOfMaintenances = 2; namespace Antares::Solver::TSGenerator { // optimization problem - methods From 878a41b46d1f9d91672df579b172b8edf2c46120 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Fri, 17 Nov 2023 11:15:30 +0100 Subject: [PATCH 100/315] fix calculateUnit[Earliest/Latest]StartOfFirstMaintenance methods --- .../OptimizedGenerator.cpp | 22 ++++++++++++++----- .../OptimizedGenerator.h | 10 +++------ 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp index 8c83d2a6af..168fb319ba 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp @@ -8,6 +8,7 @@ #include static const uint minNumberOfMaintenances = 2; + namespace Antares::Solver::TSGenerator { // optimization problem - methods @@ -299,14 +300,18 @@ std::array OptimizedThermalGenerator::calculateMaxUnitOut // calculate parameters methods - per cluster-Unit int OptimizedThermalGenerator::calculateUnitEarliestStartOfFirstMaintenance( Data::ThermalCluster& cluster, - int avrMntDuration, uint unitIndex) { - // earliest start of the first maintenance of unit u (beginning of the window, can be negative): // TODO CR27: Ask Hugo?! + // earliest start of the first maintenance of unit u (beginning of the window, can be negative): + // let it return negative value - if it returns negative value we wont implement constraint: + // s[tauLower-1][u][1] = 0 + // TODO CR27: if the approach above breaks the solver + // we force the start of the first maintenance to be after day=0 + // s[fixed = 0][u][1] = 0 if (unitIndex < cluster.daysSinceLastMaintenance.size()) { - return std::max( - avrMntDuration - cluster.daysSinceLastMaintenance[unitIndex] - cluster.poWindows, 0); + return (cluster.interPoPeriod - cluster.daysSinceLastMaintenance[unitIndex] + - cluster.poWindows); } else { @@ -318,14 +323,19 @@ int OptimizedThermalGenerator::calculateUnitEarliestStartOfFirstMaintenance( int OptimizedThermalGenerator::calculateUnitLatestStartOfFirstMaintenance( Data::ThermalCluster& cluster, - int avrMntDuration, uint unitIndex) { // latest start of the first maintenance of unit u (end of the window, must be positive): if (unitIndex < cluster.daysSinceLastMaintenance.size()) { + // this cannot be negative: + // cluster.interPoPeriod - cluster.daysSinceLastMaintenance[unitIndex] - is always positive + // or zero + // cluster.poWindows is positive or zero + // so std::max is not necessary but I will keep it for now return std::max( - avrMntDuration - cluster.daysSinceLastMaintenance[unitIndex] + cluster.poWindows, 0); + cluster.interPoPeriod - cluster.daysSinceLastMaintenance[unitIndex] + cluster.poWindows, + 0); } else { diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index b56e64271a..30f5b0e711 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -18,7 +18,7 @@ class OptimizedThermalGenerator : public GeneratorTempData in adq-patch we re-used existing structure(s) for helping us define an optimization problem -> like: struct CORRESPONDANCES_DES_VARIABLES. unfortunately here we have to create our own help-structure if we need one - Question: can we still use struct PROBLEME_ANTARES_A_RESOUDRE ?! - no we use MPSolver class + Question: can we still use struct PROBLEME_ANTARES_A_RESOUDRE ?! - no we use MPSolver and MPVariable class */ // optimization problem construction methods @@ -65,12 +65,8 @@ class OptimizedThermalGenerator : public GeneratorTempData std::array calculateMaxUnitOutput(Data::ThermalCluster& cluster); // calculate parameters methods - per cluster-Unit - int calculateUnitEarliestStartOfFirstMaintenance(Data::ThermalCluster& cluster, - int avrMntDuration, - uint unitIndex); - int calculateUnitLatestStartOfFirstMaintenance(Data::ThermalCluster& cluster, - int avrMntDuration, - uint unitIndex); + int calculateUnitEarliestStartOfFirstMaintenance(Data::ThermalCluster& cluster, uint unitIndex); + int calculateUnitLatestStartOfFirstMaintenance(Data::ThermalCluster& cluster, uint unitIndex); // auxillary functions std::array calculateDailySums( From 1ad0802c400643913305bf50737f92f393282fa5 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Fri, 17 Nov 2023 11:32:39 +0100 Subject: [PATCH 101/315] clean --- .../optimized-thermal-generator/OptimizedGenerator.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp index 168fb319ba..6f011ffa96 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp @@ -85,9 +85,9 @@ void OptimizedThermalGenerator::createOptimizationProblemPerCluster(const Data:: = calculateAverageMaintenanceDuration(cluster); // this will floor the double value !! std::array maxUnitOutput = calculateMaxUnitOutput(cluster); // uint earliestStartOfFirstMaintenance - // = calculateUnitEarliestStartOfFirstMaintenance(cluster, averageMaintenanceDuration, 8); + // = calculateUnitEarliestStartOfFirstMaintenance(cluster, 8); // uint latestStartOfFirstMaintenance - // = calculateUnitLatestStartOfFirstMaintenance(cluster, averageMaintenanceDuration, 8); + // = calculateUnitLatestStartOfFirstMaintenance(cluster, 8); // just playing here - this needs to go into new method - class - operator logs.info() << "CR27-INFO: This cluster is active for mnt planning: " << cluster.getFullName(); From d1a6ba9167bcf89432714d1bf5d0327495c40071 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Fri, 17 Nov 2023 13:43:21 +0100 Subject: [PATCH 102/315] initialize MILP solver called CBC (ortools family) --- src/solver/ts-generator/CMakeLists.txt | 1 + .../OptimizedGenerator.cpp | 25 +++++++++++++-- .../OptimizedGenerator.h | 31 ++++++++++++++++--- 3 files changed, 51 insertions(+), 6 deletions(-) diff --git a/src/solver/ts-generator/CMakeLists.txt b/src/solver/ts-generator/CMakeLists.txt index 340994beaa..4e7cabf28f 100644 --- a/src/solver/ts-generator/CMakeLists.txt +++ b/src/solver/ts-generator/CMakeLists.txt @@ -77,4 +77,5 @@ target_link_libraries(antares-solver-ts-generator array benchmarking Antares::study + utils #ortools-utils, not Antares::utils ) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp index 6f011ffa96..12d167dd08 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp @@ -7,10 +7,31 @@ #include #include -static const uint minNumberOfMaintenances = 2; - namespace Antares::Solver::TSGenerator { +// initialize solver +void OptimizedThermalGenerator::initSolver() +{ + try + { + solver = MPSolver::CreateSolver(mntPlSolverName); + + if (!solver) + { + std::string msg_to_throw = "Solver " + mntPlSolverName + " not found. \n"; + msg_to_throw += "Please make sure that your OR-Tools install supports solver " + + mntPlSolverName + "."; + + throw Antares::Data::AssertionError(msg_to_throw); + } + } + catch (...) + { + Antares::logs.error() << "Solver creation failed."; + throw; + } +} + // optimization problem - methods void OptimizedThermalGenerator::GenerateOptimizedThermalTimeSeries() { diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 30f5b0e711..d4a0f44f87 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -4,9 +4,16 @@ #pragma once +#include "ortools/linear_solver/linear_solver.h" #include "../randomized-thermal-generator/RandomizedGenerator.h" #include "../../../libs/antares/study/maintenance_planning/MaintenanceGroup.h" #include "AuxillaryStructures.h" +#include + +static const std::string mntPlSolverName = "cbc"; +static const uint minNumberOfMaintenances = 2; + +using namespace operations_research; namespace Antares::Solver::TSGenerator { @@ -18,10 +25,20 @@ class OptimizedThermalGenerator : public GeneratorTempData in adq-patch we re-used existing structure(s) for helping us define an optimization problem -> like: struct CORRESPONDANCES_DES_VARIABLES. unfortunately here we have to create our own help-structure if we need one - Question: can we still use struct PROBLEME_ANTARES_A_RESOUDRE ?! - no we use MPSolver and MPVariable class + Question: can we still use struct PROBLEME_ANTARES_A_RESOUDRE ?! - + no we use: + class MPSolver + class MPConstraint; + class MPObjective; + class MPSolverInterface; + class MPSolverParameters; + class MPVariable; */ // optimization problem construction methods + + void initSolver(); + void buildProblemVariables(); void countVariables(); void buildEnsAndSpillageVariables(); @@ -47,7 +64,6 @@ class OptimizedThermalGenerator : public GeneratorTempData void runOptimizationProblem(); - // optimization problem - methods - private void createOptimizationProblemPerGroup(const OptProblemSettings& optSett); void createOptimizationProblemPerCluster(const Data::Area& area, Data::ThermalCluster& cluster); @@ -96,6 +112,9 @@ class OptimizedThermalGenerator : public GeneratorTempData std::array residualLoadDailyValues_; OptimizationProblemVariableIndexes indexes; + // Declare an MPSolver pointer + MPSolver* solver; + public: explicit OptimizedThermalGenerator(Data::Study& study, Data::MaintenanceGroup& maintenanceGroup, @@ -110,10 +129,14 @@ class OptimizedThermalGenerator : public GeneratorTempData scenarioLength_ = study.parameters.maintenancePlanning.getScenarioLength(); scenarioNumber_ = study.parameters.maintenancePlanning.getScenarioNumber(); nbThermalTimeseries = scenarioLength_ * scenarioNumber_; - // allocateProblem(); + // initiate a solver + initSolver(); } - ~OptimizedThermalGenerator() = default; + ~OptimizedThermalGenerator() + { + delete solver; + } // optimization problem - methods - public void GenerateOptimizedThermalTimeSeries(); From 6402aa4e5ec869f6f2cd15d385500e55846ed703 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Fri, 17 Nov 2023 14:18:39 +0100 Subject: [PATCH 103/315] refactor/fix OptimizedThermalGenerator destructor --- .../OptimizedGenerator.h | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index d4a0f44f87..8c7bfbf6cd 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -112,8 +112,13 @@ class OptimizedThermalGenerator : public GeneratorTempData std::array residualLoadDailyValues_; OptimizationProblemVariableIndexes indexes; - // Declare an MPSolver pointer - MPSolver* solver; + /* + Declare an MPSolver pointer + No need to manually delete it using delete. + When using MPSolver::CreateSolver, the solver should handle its own memory and cleanup upon + destruction. + */ + MPSolver* solver = nullptr; public: explicit OptimizedThermalGenerator(Data::Study& study, @@ -133,10 +138,7 @@ class OptimizedThermalGenerator : public GeneratorTempData initSolver(); } - ~OptimizedThermalGenerator() - { - delete solver; - } + ~OptimizedThermalGenerator() = default; // optimization problem - methods - public void GenerateOptimizedThermalTimeSeries(); From d30f13273b45e268b7c03afb63c87fc850c66ff3 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Fri, 17 Nov 2023 14:44:23 +0100 Subject: [PATCH 104/315] refactor initialize MPSolver - which one is better - maybe revert to old one? --- .../OptimizedGenerator.cpp | 23 ------------------- .../OptimizedGenerator.h | 17 +++++--------- 2 files changed, 6 insertions(+), 34 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp index 12d167dd08..0f567ec33b 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp @@ -9,29 +9,6 @@ namespace Antares::Solver::TSGenerator { -// initialize solver -void OptimizedThermalGenerator::initSolver() -{ - try - { - solver = MPSolver::CreateSolver(mntPlSolverName); - - if (!solver) - { - std::string msg_to_throw = "Solver " + mntPlSolverName + " not found. \n"; - msg_to_throw += "Please make sure that your OR-Tools install supports solver " - + mntPlSolverName + "."; - - throw Antares::Data::AssertionError(msg_to_throw); - } - } - catch (...) - { - Antares::logs.error() << "Solver creation failed."; - throw; - } -} - // optimization problem - methods void OptimizedThermalGenerator::GenerateOptimizedThermalTimeSeries() { diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 8c7bfbf6cd..1f85bae7a4 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -10,7 +10,7 @@ #include "AuxillaryStructures.h" #include -static const std::string mntPlSolverName = "cbc"; +// static const std::string mntPlSolverName = "cbc"; static const uint minNumberOfMaintenances = 2; using namespace operations_research; @@ -112,13 +112,8 @@ class OptimizedThermalGenerator : public GeneratorTempData std::array residualLoadDailyValues_; OptimizationProblemVariableIndexes indexes; - /* - Declare an MPSolver pointer - No need to manually delete it using delete. - When using MPSolver::CreateSolver, the solver should handle its own memory and cleanup upon - destruction. - */ - MPSolver* solver = nullptr; + // MPSolver instance + MPSolver solver; public: explicit OptimizedThermalGenerator(Data::Study& study, @@ -127,15 +122,15 @@ class OptimizedThermalGenerator : public GeneratorTempData bool globalThermalTSgeneration, Solver::Progression::Task& progr, IResultWriter& writer) : - GeneratorTempData(study, progr, writer), maintenanceGroup_(maintenanceGroup) + GeneratorTempData(study, progr, writer), + maintenanceGroup_(maintenanceGroup), + solver(MPSolver("MaintenancePlanning", MPSolver::CBC_MIXED_INTEGER_PROGRAMMING)) { currentYear = year; globalThermalTSgeneration_ = globalThermalTSgeneration; scenarioLength_ = study.parameters.maintenancePlanning.getScenarioLength(); scenarioNumber_ = study.parameters.maintenancePlanning.getScenarioNumber(); nbThermalTimeseries = scenarioLength_ * scenarioNumber_; - // initiate a solver - initSolver(); } ~OptimizedThermalGenerator() = default; From 8d0c7d7351c66bfe2ebb92fc7342e92110c8ff9f Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Fri, 17 Nov 2023 15:05:47 +0100 Subject: [PATCH 105/315] add solver infinity to the OptimizedThermalGenerator --- .../optimized-thermal-generator/OptimizedGenerator.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 1f85bae7a4..6abada27e9 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -114,6 +114,7 @@ class OptimizedThermalGenerator : public GeneratorTempData // MPSolver instance MPSolver solver; + double infinity; public: explicit OptimizedThermalGenerator(Data::Study& study, @@ -131,6 +132,7 @@ class OptimizedThermalGenerator : public GeneratorTempData scenarioLength_ = study.parameters.maintenancePlanning.getScenarioLength(); scenarioNumber_ = study.parameters.maintenancePlanning.getScenarioNumber(); nbThermalTimeseries = scenarioLength_ * scenarioNumber_; + infinity = solver.infinity(); } ~OptimizedThermalGenerator() = default; From 3dc34276cd308891e27834af273f7acd3caf2d87 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Fri, 17 Nov 2023 15:21:58 +0100 Subject: [PATCH 106/315] clean --- .../OptimizedGenerator.h | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 6abada27e9..a6ba3dd588 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -21,24 +21,7 @@ namespace Antares::Solver::TSGenerator class OptimizedThermalGenerator : public GeneratorTempData { private: - /* - in adq-patch we re-used existing structure(s) for helping us define an optimization problem -> - like: struct CORRESPONDANCES_DES_VARIABLES. - unfortunately here we have to create our own help-structure if we need one - Question: can we still use struct PROBLEME_ANTARES_A_RESOUDRE ?! - - no we use: - class MPSolver - class MPConstraint; - class MPObjective; - class MPSolverInterface; - class MPSolverParameters; - class MPVariable; - */ - // optimization problem construction methods - - void initSolver(); - void buildProblemVariables(); void countVariables(); void buildEnsAndSpillageVariables(); @@ -56,7 +39,6 @@ class OptimizedThermalGenerator : public GeneratorTempData void buildLoadBalanceConstraints(); void setStartEndMntLogicConstraints(); void setMaxUnitOutputConstraints(); - // void buildProblemConstraintsRHS(); // let's do LHS & RHS in one go. Easier!? void setProblemCost(); void solveProblem(); From a1b657aa87c9b8a5f6a35b0671fc51721364226d Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Fri, 17 Nov 2023 15:39:11 +0100 Subject: [PATCH 107/315] test CBC solver on dummy MILP case - works! --- .../CreateVariables.cpp | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp b/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp index 24651c8380..de791e2468 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp @@ -16,6 +16,60 @@ void OptimizedThermalGenerator::buildProblemVariables() void OptimizedThermalGenerator::countVariables() { + /* + TEST optimization + minimize: + * 3x - y + subject to: + * 1.5 x + 2 y >= 12 + * 0 <= x <= 3 + * 0 <= y <= 5 + * x - linear variable + * y - integer variable + */ + + // Define variables and at the same time Boundaries + /* + The bounds of a variable once set cannot be directly modified in OR-Tools. + However, you can create a new variable with the desired bounds and + constraints and use it in your optimization problem. + */ + MPVariable* const x = solver.MakeNumVar(0.0, 3.0, "x"); + MPVariable* const y = solver.MakeIntVar(0.0, 5.0, "y"); + + // Define constraints + // TODO CR27: we need to make vector of shared pointers to MPVariable so we can access them in different files + MPConstraint* const ct = solver.MakeRowConstraint(12.0, infinity, "ct"); + ct->SetCoefficient(x, 1.5); + ct->SetCoefficient(y, 2.0); + + // Define objective function + MPObjective* const objective = solver.MutableObjective(); + objective->SetCoefficient(x, 3); + objective->SetCoefficient(y, -1); + objective->SetMinimization(); + + // Count the number of variables in the solver + int numVariables = solver.NumVariables(); + // Count the number of constraints in the solver + int numConstraints = solver.NumConstraints(); + + // Solve the problem + const MPSolver::ResultStatus result_status = solver.Solve(); + + if (result_status != MPSolver::OPTIMAL) { + // If not optimal, print that optimization failed + logs.info()<< "The problem does not have an optimal solution.\n"; + return; + } + // Access and print the results + printf("Optimal objective value = %.2f\n", objective->Value()); + printf("x = %.2f\n", x->solution_value()); + printf("y = %.2f\n", y->solution_value()); + + // Clear the solver to reset it for the new problem + solver.Clear(); + return; } From cae2b529d8d6f93618bcacfe2dfe891d789036cc Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Fri, 17 Nov 2023 15:52:58 +0100 Subject: [PATCH 108/315] add some instructions comments --- .../optimized-thermal-generator/CreateVariables.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp b/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp index de791e2468..6b18d380d1 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp @@ -29,13 +29,11 @@ void OptimizedThermalGenerator::countVariables() */ // Define variables and at the same time Boundaries - /* - The bounds of a variable once set cannot be directly modified in OR-Tools. - However, you can create a new variable with the desired bounds and - constraints and use it in your optimization problem. - */ - MPVariable* const x = solver.MakeNumVar(0.0, 3.0, "x"); - MPVariable* const y = solver.MakeIntVar(0.0, 5.0, "y"); + MPVariable* x = solver.MakeNumVar(0.0, 3.0, "x"); + MPVariable* y = solver.MakeIntVar(0.0, 5.0, "y"); + + // redefine lower bound - just do not make x - constant + x->SetLB(1.5); // Define constraints // TODO CR27: we need to make vector of shared pointers to MPVariable so we can access them in different files From 55b0641c4ffbbf1666942a1551822ad0326e76fc Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Mon, 20 Nov 2023 11:28:43 +0100 Subject: [PATCH 109/315] access/set MPSolver parameters --- .../optimized-thermal-generator/OptimizedGenerator.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index a6ba3dd588..98cde24ee1 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -114,6 +114,18 @@ class OptimizedThermalGenerator : public GeneratorTempData scenarioLength_ = study.parameters.maintenancePlanning.getScenarioLength(); scenarioNumber_ = study.parameters.maintenancePlanning.getScenarioNumber(); nbThermalTimeseries = scenarioLength_ * scenarioNumber_; + + // Solver Settings + // MP solver parameters / TODD CR27: do we change this - + // I would keep it on default values for the time being + + // Access solver parameters + MPSolverParameters params; + // Set parameter values + // params.SetIntegerParam(MPSolverParameters::SCALING, 0); + // params.SetIntegerParam(MPSolverParameters::PRESOLVE, 0); + + // set solver infinity infinity = solver.infinity(); } From 510c659a97e0a748f42925f6ac6c008cbae38550 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Mon, 20 Nov 2023 13:11:41 +0100 Subject: [PATCH 110/315] redefine OptimizationProblemVariables struct create ens & spill variables --- .../AuxillaryStructures.h | 38 +++++++++++-------- .../CreateVariables.cpp | 32 ++++++++++++---- .../OptimizedGenerator.cpp | 24 ++++-------- .../OptimizedGenerator.h | 12 +++--- .../SolveProbem.cpp | 4 +- 5 files changed, 62 insertions(+), 48 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h index 4386e7f139..553affc439 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h +++ b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h @@ -2,6 +2,12 @@ // Created by milos on 14/11/23. // +#pragma once + +#include "OptimizedGenerator.h" + +using namespace operations_research; + namespace Antares::Solver::TSGenerator { @@ -10,42 +16,42 @@ class OptProblemSettings final public: OptProblemSettings() = default; - int optProblemStartTime; - int optProblemEndTime; + int firstDay; + int lastDay; }; -struct OptimizationProblemVariableIndexesPerUnit +struct OptimizationProblemVariablesPerUnit { - int P; // index of P[t][u] variable + MPVariable* P = nullptr;; // index of P[t][u] variable // number of elements in the vector is total number of maintenances of unit - std::vector start; // index of s[t][u][m] variable - std::vector end; // index of e[t][u][m] variable + std::vector start; // index of s[t][u][m] variable + std::vector end; // index of e[t][u][m] variable }; -struct OptimizationProblemVariableIndexesPerCluster +struct OptimizationProblemVariablesPerCluster { // number of elements in the vector is total number of units in cluster - std::vector unit; + std::vector unit; }; -struct OptimizationProblemVariableIndexesPerArea +struct OptimizationProblemVariablesPerArea { // number of elements in the vector is total number of clusters in area - std::vector cluster; + std::vector cluster; }; -struct OptimizationProblemVariableIndexesPerDay +struct OptimizationProblemVariablesPerDay { - int Ens; // index of ENS[t] variable - int Spill; // index of Spillage[t] variable + MPVariable* Ens = nullptr; // index of ENS[t] variable + MPVariable* Spill = nullptr;; // index of Spillage[t] variable // number of elements in the vector is total number of areas in optimization problem - std::vector area; + std::vector area; }; -struct OptimizationProblemVariableIndexes +struct OptimizationProblemVariables { // number of elements in the vector is total number of days in optimization problem - std::vector day; + std::vector day; }; } // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp b/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp index 6b18d380d1..95e8f97e56 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp @@ -6,12 +6,12 @@ namespace Antares::Solver::TSGenerator { -void OptimizedThermalGenerator::buildProblemVariables() +void OptimizedThermalGenerator::buildProblemVariables(const OptProblemSettings& optSett) { countVariables(); - buildEnsAndSpillageVariables(); - buildUnitPowerOutputVariables(); - buildStartEndMntVariables(); + buildEnsAndSpillageVariables(optSett); + buildUnitPowerOutputVariables(optSett); + buildStartEndMntVariables(optSett); } void OptimizedThermalGenerator::countVariables() @@ -72,19 +72,37 @@ void OptimizedThermalGenerator::countVariables() } // create VARIABLES per day - ENS[t], Spill[t] -void OptimizedThermalGenerator::buildEnsAndSpillageVariables() +void OptimizedThermalGenerator::buildEnsAndSpillageVariables(const OptProblemSettings& optSett) { + for (int day = optSett.firstDay; day < optSett.lastDay; ++day) + { + // fill the variable structure + var.day.push_back(OptimizationProblemVariablesPerDay()); + } + + for (int day = optSett.firstDay; day < optSett.lastDay; ++day) + { + // add ENS variables + var.day[day].Ens = solver.MakeNumVar(0.0, infinity, "ENS_day_" + std::to_string(day)); + } + + for (int day = optSett.firstDay; day < optSett.lastDay; ++day) + { + // add Spillage variables + var.day[day].Spill = solver.MakeNumVar(0.0, infinity, "Spill_day_" + std::to_string(day)); + } + return; } // create VARIABLES per day and per cluster-unit - P[t][u] -void OptimizedThermalGenerator::buildUnitPowerOutputVariables() +void OptimizedThermalGenerator::buildUnitPowerOutputVariables(const OptProblemSettings& optSett) { return; } // create VARIABLES per day, per cluster-unit and per maintenance - s[t][u][m] & e[t][u][m] -void OptimizedThermalGenerator::buildStartEndMntVariables() +void OptimizedThermalGenerator::buildStartEndMntVariables(const OptProblemSettings& optSett) { return; } diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp index 0f567ec33b..3778f142bc 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp @@ -20,23 +20,23 @@ void OptimizedThermalGenerator::GenerateOptimizedThermalTimeSeries() for (std::size_t scenarioIndex = 0; scenarioIndex < scenarioNumber_; ++scenarioIndex) { OptProblemSettings optSett; - optSett.optProblemStartTime = 0; - optSett.optProblemEndTime = timeHorizon_; + optSett.firstDay = 0; + optSett.lastDay = timeHorizon_; // loop till the end of scenario length - while (optSett.optProblemStartTime <= scenarioLength_ * DAYS_PER_YEAR) + while (optSett.firstDay <= scenarioLength_ * DAYS_PER_YEAR) { createOptimizationProblemPerGroup(optSett); // Update the time values for the next iteration - optSett.optProblemStartTime += timeStep_; - optSett.optProblemEndTime += timeStep_; + optSett.firstDay += timeStep_; + optSett.lastDay += timeStep_; } } } void OptimizedThermalGenerator::createOptimizationProblemPerGroup(const OptProblemSettings& optSett) { - runOptimizationProblem(); + runOptimizationProblem(optSett); // ... // do the optimization post-processing here & // do the writing off the result here @@ -55,16 +55,6 @@ void OptimizedThermalGenerator::createOptimizationProblemPerGroup(const OptProbl ++pProgression; } } - - indexes.day.push_back(OptimizationProblemVariableIndexesPerDay()); - indexes.day[0].Ens = 1; - indexes.day[0].Spill = 2; - indexes.day[0].area.push_back(OptimizationProblemVariableIndexesPerArea()); - indexes.day[0].area[0].cluster.push_back(OptimizationProblemVariableIndexesPerCluster()); - indexes.day[0].area[0].cluster[0].unit.push_back(OptimizationProblemVariableIndexesPerUnit()); - indexes.day[0].area[0].cluster[0].unit[0].P = 100; - indexes.day[0].area[0].cluster[0].unit[0].start.push_back(55); - indexes.day[0].area[0].cluster[0].unit[0].end.push_back(155); // end play } @@ -144,7 +134,7 @@ bool OptimizedThermalGenerator::checkMaintenanceGroupParameters() << "Maintenance group: " << maintenanceGroup_.name() << ": The timeseries generation will be skiped: timeHorizon = 0. It is possible " "that the maintenance group has no clusters designated for maintenance " - "planning or, at all cluster have interPoPeriod = 0"; + "planning or, all cluster have interPoPeriod = 0"; return false; } // add some more check here if necessary! diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 98cde24ee1..435930af7b 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -22,11 +22,11 @@ class OptimizedThermalGenerator : public GeneratorTempData { private: // optimization problem construction methods - void buildProblemVariables(); + void buildProblemVariables(const OptProblemSettings& optSett); void countVariables(); - void buildEnsAndSpillageVariables(); - void buildUnitPowerOutputVariables(); - void buildStartEndMntVariables(); + void buildEnsAndSpillageVariables(const OptProblemSettings& optSett); + void buildUnitPowerOutputVariables(const OptProblemSettings& optSett); + void buildStartEndMntVariables(const OptProblemSettings& optSett); void setVariableBounds(); void setEnsAndSpillageBounds(); @@ -44,7 +44,7 @@ class OptimizedThermalGenerator : public GeneratorTempData void solveProblem(); void resetProblem(); - void runOptimizationProblem(); + void runOptimizationProblem(const OptProblemSettings& optSett); // optimization problem - methods - private void createOptimizationProblemPerGroup(const OptProblemSettings& optSett); @@ -92,7 +92,7 @@ class OptimizedThermalGenerator : public GeneratorTempData double ensCost_; double spillCost_; std::array residualLoadDailyValues_; - OptimizationProblemVariableIndexes indexes; + OptimizationProblemVariables var; // MPSolver instance MPSolver solver; diff --git a/src/solver/ts-generator/optimized-thermal-generator/SolveProbem.cpp b/src/solver/ts-generator/optimized-thermal-generator/SolveProbem.cpp index cf51648c72..6ce65b60a5 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/SolveProbem.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/SolveProbem.cpp @@ -7,9 +7,9 @@ namespace Antares::Solver::TSGenerator { // call all methods -void OptimizedThermalGenerator::runOptimizationProblem() +void OptimizedThermalGenerator::runOptimizationProblem(const OptProblemSettings& optSett) { - buildProblemVariables(); + buildProblemVariables(optSett); setVariableBounds(); buildProblemConstraints(); setProblemCost(); From daadbd905a4efbdb0b3243a25bd666b19a82c1c6 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Mon, 20 Nov 2023 13:13:16 +0100 Subject: [PATCH 111/315] ens & spill variable bounds --- .../optimized-thermal-generator/SetVariableBounds.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp b/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp index e46c80308b..426b98fdcc 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp @@ -18,6 +18,7 @@ void OptimizedThermalGenerator::setVariableBounds() // BOUNDS per each day - bounds-per-each-day[t] - ENS[t] >= 0, Spill[t] >= 0 void OptimizedThermalGenerator::setEnsAndSpillageBounds() { + // no need for this - defined when creating the Ens & Spill variables return; } From adf76572b5d41b9967d59a1aac9512aae056f3cb Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Mon, 20 Nov 2023 13:15:19 +0100 Subject: [PATCH 112/315] typo --- .../optimized-thermal-generator/OptimizedGenerator.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp index 3778f142bc..b0547db5ae 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp @@ -125,7 +125,7 @@ bool OptimizedThermalGenerator::checkMaintenanceGroupParameters() logs.info() << "Maintenance group: " << maintenanceGroup_.name() << ": The timeseries generation will be skiped: timeStep = 0. It is possible " "that the maintenance group has no clusters designated for maintenance " - "planning or, at least one cluster has interPoPeriod = 0"; + "planning, or at least one cluster has interPoPeriod = 0"; return false; } if (timeHorizon_ == 0) @@ -134,7 +134,7 @@ bool OptimizedThermalGenerator::checkMaintenanceGroupParameters() << "Maintenance group: " << maintenanceGroup_.name() << ": The timeseries generation will be skiped: timeHorizon = 0. It is possible " "that the maintenance group has no clusters designated for maintenance " - "planning or, all cluster have interPoPeriod = 0"; + "planning, or all clusters have interPoPeriod = 0"; return false; } // add some more check here if necessary! From a9c7b7a59b067313fa91abeb894d97889ccc75d9 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Mon, 20 Nov 2023 16:39:07 +0100 Subject: [PATCH 113/315] redefine OptimizationProblemVariables --- .../optimized-thermal-generator/AuxillaryStructures.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h index 553affc439..cf96673d93 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h +++ b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h @@ -5,6 +5,7 @@ #pragma once #include "OptimizedGenerator.h" +#include "../../../src/libs/antares/study/area/area.h" using namespace operations_research; @@ -32,21 +33,21 @@ struct OptimizationProblemVariablesPerUnit struct OptimizationProblemVariablesPerCluster { // number of elements in the vector is total number of units in cluster - std::vector unit; + std::vector unitMap; }; struct OptimizationProblemVariablesPerArea { - // number of elements in the vector is total number of clusters in area - std::vector cluster; + // number of elements in the map is total number of clusters in area + std::map clusterMap; }; struct OptimizationProblemVariablesPerDay { MPVariable* Ens = nullptr; // index of ENS[t] variable MPVariable* Spill = nullptr;; // index of Spillage[t] variable - // number of elements in the vector is total number of areas in optimization problem - std::vector area; + // number of elements in the map is total number of areas in optimization problem + std::map areaMap; }; struct OptimizationProblemVariables { From 469f0b845f8de9bc2dc3e5efcc5029d42779c5b1 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Mon, 20 Nov 2023 16:39:24 +0100 Subject: [PATCH 114/315] reset problem --- .../ts-generator/optimized-thermal-generator/ResetProblem.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/solver/ts-generator/optimized-thermal-generator/ResetProblem.cpp b/src/solver/ts-generator/optimized-thermal-generator/ResetProblem.cpp index 37f836700d..f22758c230 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/ResetProblem.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/ResetProblem.cpp @@ -8,6 +8,9 @@ namespace Antares::Solver::TSGenerator { void OptimizedThermalGenerator::resetProblem() { + // Clear the solver to reset it for the new problem + solver.Clear(); + var.day.clear(); return; } From b6379c8921287a2e75f69eb6ccf3a87142365ffb Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Mon, 20 Nov 2023 16:40:43 +0100 Subject: [PATCH 115/315] refactor + create P[t][u] variables + print out variables for debug --- .../CreateVariables.cpp | 102 ++++++++++++++++-- .../OptimizedGenerator.cpp | 5 +- .../OptimizedGenerator.h | 3 +- 3 files changed, 98 insertions(+), 12 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp b/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp index 95e8f97e56..707ed245e8 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp @@ -12,6 +12,7 @@ void OptimizedThermalGenerator::buildProblemVariables(const OptProblemSettings& buildEnsAndSpillageVariables(optSett); buildUnitPowerOutputVariables(optSett); buildStartEndMntVariables(optSett); + printAllVariables(); } void OptimizedThermalGenerator::countVariables() @@ -36,7 +37,6 @@ void OptimizedThermalGenerator::countVariables() x->SetLB(1.5); // Define constraints - // TODO CR27: we need to make vector of shared pointers to MPVariable so we can access them in different files MPConstraint* const ct = solver.MakeRowConstraint(12.0, infinity, "ct"); ct->SetCoefficient(x, 1.5); ct->SetCoefficient(y, 2.0); @@ -55,9 +55,10 @@ void OptimizedThermalGenerator::countVariables() // Solve the problem const MPSolver::ResultStatus result_status = solver.Solve(); - if (result_status != MPSolver::OPTIMAL) { + if (result_status != MPSolver::OPTIMAL) + { // If not optimal, print that optimization failed - logs.info()<< "The problem does not have an optimal solution.\n"; + logs.info() << "The problem does not have an optimal solution.\n"; return; } // Access and print the results @@ -74,22 +75,24 @@ void OptimizedThermalGenerator::countVariables() // create VARIABLES per day - ENS[t], Spill[t] void OptimizedThermalGenerator::buildEnsAndSpillageVariables(const OptProblemSettings& optSett) { - for (int day = optSett.firstDay; day < optSett.lastDay; ++day) + for (int day = 0; day < timeHorizon_; ++day) { // fill the variable structure var.day.push_back(OptimizationProblemVariablesPerDay()); } - for (int day = optSett.firstDay; day < optSett.lastDay; ++day) + for (int day = 0; day < timeHorizon_; ++day) { // add ENS variables - var.day[day].Ens = solver.MakeNumVar(0.0, infinity, "ENS_day_" + std::to_string(day)); + var.day[day].Ens = solver.MakeNumVar( + 0.0, infinity, "ENS_[" + std::to_string(day + optSett.firstDay) + "]"); } - for (int day = optSett.firstDay; day < optSett.lastDay; ++day) + for (int day = 0; day < timeHorizon_; ++day) { // add Spillage variables - var.day[day].Spill = solver.MakeNumVar(0.0, infinity, "Spill_day_" + std::to_string(day)); + var.day[day].Spill = solver.MakeNumVar( + 0.0, infinity, "Spill_[" + std::to_string(day + optSett.firstDay) + "]"); } return; @@ -98,6 +101,78 @@ void OptimizedThermalGenerator::buildEnsAndSpillageVariables(const OptProblemSet // create VARIABLES per day and per cluster-unit - P[t][u] void OptimizedThermalGenerator::buildUnitPowerOutputVariables(const OptProblemSettings& optSett) { + // loop per day - structure already filled in + for (int day = 0; day < timeHorizon_; ++day) + { + // loop per area inside maintenance group - fill in the structure + for (const auto& entryWeightMap : maintenanceGroup_) + { + const auto& area = *(entryWeightMap.first); + auto& areaVariables = var.day[day].areaMap; + areaVariables[&area] = OptimizationProblemVariablesPerArea(); + + // loop per thermal clusters inside the area - fill in the structure + for (auto it = area.thermal.list.mapping.begin(); it != area.thermal.list.mapping.end(); + ++it) + { + const auto& cluster = *(it->second); + + if (!checkClusterExist(cluster)) + continue; + // we do not check if cluster.optimizeMaintenance = true here + // we add all the clusters Power inside maintenance group + + auto& clusterVariables = areaVariables[&area].clusterMap; + clusterVariables[&cluster] = OptimizationProblemVariablesPerCluster(); + + // loop per unit inside the cluster - fill in the structure + for (int unit = 0; unit < cluster.unitCount; ++unit) + { + clusterVariables[&cluster].unitMap.push_back( + OptimizationProblemVariablesPerUnit()); + } + } + } + } + + // loop per day - structure already filled in + for (int day = 0; day < timeHorizon_; ++day) + { + // loop per area inside maintenance group - fill in the structure + for (const auto& entryWeightMap : maintenanceGroup_) + { + const auto& area = *(entryWeightMap.first); + auto& areaVariables = var.day[day].areaMap; + + // loop per thermal clusters inside the area - fill in the structure + for (auto it = area.thermal.list.mapping.begin(); it != area.thermal.list.mapping.end(); + ++it) + { + const auto& cluster = *(it->second); + + if (!checkClusterExist(cluster)) + continue; + // we do not check if cluster.optimizeMaintenance = true here + // we add all the clusters Power inside maintenance group + + auto& clusterVariables = areaVariables[&area].clusterMap; + + // loop per unit inside the cluster - fill in the structure + for (int unit = 0; unit < cluster.unitCount; ++unit) + { + // add P[t][u] variables + clusterVariables[&cluster].unitMap[unit].P = solver.MakeNumVar( + 0.0, + infinity, + "P_[" + std::to_string(day + optSett.firstDay) + "][" + + cluster.getFullName().to() + "." + std::to_string(unit) + "]" + + ); + } + } + } + } + return; } @@ -107,4 +182,15 @@ void OptimizedThermalGenerator::buildStartEndMntVariables(const OptProblemSettin return; } +void OptimizedThermalGenerator::printAllVariables() +{ + for (MPVariable* const variable : solver.variables()) + { + std::cout << "Variable: " << variable->name() << ", " + << "Lower bound: " << variable->lb() << ", " + << "Upper bound: " << variable->ub() << std::endl; + } + return; +} + } // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp index b0547db5ae..368804c46f 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp @@ -23,7 +23,7 @@ void OptimizedThermalGenerator::GenerateOptimizedThermalTimeSeries() optSett.firstDay = 0; optSett.lastDay = timeHorizon_; // loop till the end of scenario length - while (optSett.firstDay <= scenarioLength_ * DAYS_PER_YEAR) + while (optSett.firstDay < scenarioLength_ * DAYS_PER_YEAR) { createOptimizationProblemPerGroup(optSett); @@ -372,7 +372,7 @@ std::array OptimizedThermalGenerator::calculateAverageTs return averageTs; } -bool OptimizedThermalGenerator::checkClusterData(Data::ThermalCluster& cluster) +bool OptimizedThermalGenerator::checkClusterExist(const Data::ThermalCluster& cluster) { if (!cluster.prepro) { @@ -385,7 +385,6 @@ bool OptimizedThermalGenerator::checkClusterData(Data::ThermalCluster& cluster) if (0 == cluster.unitCount || 0 == cluster.nominalCapacity) { - cluster.series.timeSeries.reset(1, 8760); return false; } return true; diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 435930af7b..76f9b8e7f3 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -27,6 +27,7 @@ class OptimizedThermalGenerator : public GeneratorTempData void buildEnsAndSpillageVariables(const OptProblemSettings& optSett); void buildUnitPowerOutputVariables(const OptProblemSettings& optSett); void buildStartEndMntVariables(const OptProblemSettings& optSett); + void printAllVariables(); // for debug purpose only! void setVariableBounds(); void setEnsAndSpillageBounds(); @@ -71,7 +72,7 @@ class OptimizedThermalGenerator : public GeneratorTempData const std::array& hourlyValues); std::array calculateAverageTs(const Matrix& tsValue, const Matrix& tsNumbers); - bool checkClusterData(Data::ThermalCluster& cluster); + bool checkClusterExist(const Data::ThermalCluster& cluster); int dayOfTheYear(int optimizationDay); // calculate Average time-series functions From d5e6a4a534430664c45a8ed623cbeeedc296b1b7 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Mon, 20 Nov 2023 17:19:09 +0100 Subject: [PATCH 116/315] refactor calculateNumberOfMaintenances --- .../optimized-thermal-generator/OptimizedGenerator.cpp | 2 +- .../optimized-thermal-generator/OptimizedGenerator.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp index 368804c46f..d3ad912c6f 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp @@ -236,7 +236,7 @@ void OptimizedThermalGenerator::calculateResidualLoad() } // calculate parameters methods - per cluster -uint OptimizedThermalGenerator::calculateNumberOfMaintenances(Data::ThermalCluster& cluster, +uint OptimizedThermalGenerator::calculateNumberOfMaintenances(const Data::ThermalCluster& cluster, uint timeHorizon) { // timeHorizon cannot be 0. The whole maintenance group would be skipped if this happened diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 76f9b8e7f3..ce2137454b 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -59,7 +59,7 @@ class OptimizedThermalGenerator : public GeneratorTempData void calculateResidualLoad(); // calculate parameters methods - per cluster - uint calculateNumberOfMaintenances(Data::ThermalCluster& cluster, uint timeHorizon); + uint calculateNumberOfMaintenances(const Data::ThermalCluster& cluster, uint timeHorizon); uint calculateAverageMaintenanceDuration(Data::ThermalCluster& cluster); std::array calculateMaxUnitOutput(Data::ThermalCluster& cluster); From 8d768f4810b6abb15ddfc7bffa69524bc5288109 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Mon, 20 Nov 2023 17:30:14 +0100 Subject: [PATCH 117/315] create start & end variables --- .../CreateVariables.cpp | 82 +++++++++++++++---- 1 file changed, 67 insertions(+), 15 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp b/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp index 707ed245e8..d63e0952c2 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp @@ -117,10 +117,10 @@ void OptimizedThermalGenerator::buildUnitPowerOutputVariables(const OptProblemSe { const auto& cluster = *(it->second); - if (!checkClusterExist(cluster)) - continue; // we do not check if cluster.optimizeMaintenance = true here // we add all the clusters Power inside maintenance group + if (!checkClusterExist(cluster)) + continue; auto& clusterVariables = areaVariables[&area].clusterMap; clusterVariables[&cluster] = OptimizationProblemVariablesPerCluster(); @@ -135,39 +135,38 @@ void OptimizedThermalGenerator::buildUnitPowerOutputVariables(const OptProblemSe } } - // loop per day - structure already filled in + // loop per day for (int day = 0; day < timeHorizon_; ++day) { - // loop per area inside maintenance group - fill in the structure + // loop per area inside maintenance group for (const auto& entryWeightMap : maintenanceGroup_) { const auto& area = *(entryWeightMap.first); auto& areaVariables = var.day[day].areaMap; - // loop per thermal clusters inside the area - fill in the structure + // loop per thermal clusters inside the area for (auto it = area.thermal.list.mapping.begin(); it != area.thermal.list.mapping.end(); ++it) { const auto& cluster = *(it->second); - if (!checkClusterExist(cluster)) - continue; // we do not check if cluster.optimizeMaintenance = true here // we add all the clusters Power inside maintenance group + if (!checkClusterExist(cluster)) + continue; auto& clusterVariables = areaVariables[&area].clusterMap; - // loop per unit inside the cluster - fill in the structure + // loop per unit inside the cluster for (int unit = 0; unit < cluster.unitCount; ++unit) { // add P[t][u] variables - clusterVariables[&cluster].unitMap[unit].P = solver.MakeNumVar( - 0.0, - infinity, - "P_[" + std::to_string(day + optSett.firstDay) + "][" - + cluster.getFullName().to() + "." + std::to_string(unit) + "]" - - ); + clusterVariables[&cluster].unitMap[unit].P + = solver.MakeNumVar(0.0, + infinity, + "P_[" + std::to_string(day + optSett.firstDay) + "][" + + cluster.getFullName().to() + "." + + std::to_string(unit) + "]"); } } } @@ -179,6 +178,59 @@ void OptimizedThermalGenerator::buildUnitPowerOutputVariables(const OptProblemSe // create VARIABLES per day, per cluster-unit and per maintenance - s[t][u][m] & e[t][u][m] void OptimizedThermalGenerator::buildStartEndMntVariables(const OptProblemSettings& optSett) { + // loop per day + for (int day = 0; day < timeHorizon_; ++day) + { + // loop per area inside maintenance group + for (const auto& entryWeightMap : maintenanceGroup_) + { + const auto& area = *(entryWeightMap.first); + auto& areaVariables = var.day[day].areaMap; + + // loop per thermal clusters inside the area + for (auto it = area.thermal.list.mapping.begin(); it != area.thermal.list.mapping.end(); + ++it) + { + const auto& cluster = *(it->second); + + // check if cluster exist, do we generate + optimizeMaintenance + // create start end variables only for these clusters + bool createStartEndVar = checkClusterExist(cluster) + && cluster.doWeGenerateTS(globalThermalTSgeneration_) + && cluster.optimizeMaintenance; + if (!createStartEndVar) + continue; + + auto& clusterVariables = areaVariables[&area].clusterMap; + int totalMntNumber = calculateNumberOfMaintenances(cluster, timeHorizon_); + + // loop per unit inside the cluster + for (int unit = 0; unit < cluster.unitCount; ++unit) + { + auto& unitVariables = clusterVariables[&cluster].unitMap; + // loop per maintenances per unit + for (int mnt = 0; mnt < totalMntNumber; ++mnt) + { + // add start[t][u][m] variables + unitVariables[unit].start.push_back(solver.MakeIntVar( + 0.0, + 1.0, + "S_[" + std::to_string(day + optSett.firstDay) + "][" + + cluster.getFullName().to() + "." + std::to_string(unit) + + "][" + std::to_string(mnt) + "]")); + + // add end[t][u][m] variables + unitVariables[unit].end.push_back(solver.MakeIntVar( + 0.0, + 1.0, + "E_[" + std::to_string(day + optSett.firstDay) + "][" + + cluster.getFullName().to() + "." + std::to_string(unit) + + "][" + std::to_string(mnt) + "]")); + } + } + } + } + } return; } From dea7b3aebc7dcbb0bb1154d18020d822c968a6a5 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Mon, 20 Nov 2023 17:31:41 +0100 Subject: [PATCH 118/315] set boundaries --- .../optimized-thermal-generator/SetVariableBounds.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp b/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp index 426b98fdcc..d6e5ff3ce2 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp @@ -25,6 +25,7 @@ void OptimizedThermalGenerator::setEnsAndSpillageBounds() // BOUNDS per day and per each unit - bounds-per-each-day+unit[t][u] - P[t][u] >= 0 void OptimizedThermalGenerator::setUnitPowerOutputBounds() { + // no need for this - defined when creating the P variables return; } @@ -32,6 +33,7 @@ void OptimizedThermalGenerator::setUnitPowerOutputBounds() // - s[t][u][m]-> [0, 1] and e[t][u][m]-> [0, 1] void OptimizedThermalGenerator::setStartEndMntBounds() { + // no need for this - defined when creating the Start & End variables return; } From 047e41bc2c7ba6cf49f3d307b9e15711eb1530f7 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Mon, 20 Nov 2023 18:18:00 +0100 Subject: [PATCH 119/315] refactor --- .../CreateVariables.cpp | 57 ++++++++++--------- .../OptimizedGenerator.h | 1 + 2 files changed, 32 insertions(+), 26 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp b/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp index d63e0952c2..40444612fd 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp @@ -8,7 +8,10 @@ namespace Antares::Solver::TSGenerator { void OptimizedThermalGenerator::buildProblemVariables(const OptProblemSettings& optSett) { + // this is now just dummy optimization problem countVariables(); + + allocateOptimizationProblemVariablesStruct(optSett); buildEnsAndSpillageVariables(optSett); buildUnitPowerOutputVariables(optSett); buildStartEndMntVariables(optSett); @@ -72,38 +75,16 @@ void OptimizedThermalGenerator::countVariables() return; } -// create VARIABLES per day - ENS[t], Spill[t] -void OptimizedThermalGenerator::buildEnsAndSpillageVariables(const OptProblemSettings& optSett) +// populate OptimizationProblemVariables struct +void OptimizedThermalGenerator::allocateOptimizationProblemVariablesStruct( + const OptProblemSettings& optSett) { + // loop per day - fill in structure for (int day = 0; day < timeHorizon_; ++day) { // fill the variable structure var.day.push_back(OptimizationProblemVariablesPerDay()); - } - for (int day = 0; day < timeHorizon_; ++day) - { - // add ENS variables - var.day[day].Ens = solver.MakeNumVar( - 0.0, infinity, "ENS_[" + std::to_string(day + optSett.firstDay) + "]"); - } - - for (int day = 0; day < timeHorizon_; ++day) - { - // add Spillage variables - var.day[day].Spill = solver.MakeNumVar( - 0.0, infinity, "Spill_[" + std::to_string(day + optSett.firstDay) + "]"); - } - - return; -} - -// create VARIABLES per day and per cluster-unit - P[t][u] -void OptimizedThermalGenerator::buildUnitPowerOutputVariables(const OptProblemSettings& optSett) -{ - // loop per day - structure already filled in - for (int day = 0; day < timeHorizon_; ++day) - { // loop per area inside maintenance group - fill in the structure for (const auto& entryWeightMap : maintenanceGroup_) { @@ -134,7 +115,31 @@ void OptimizedThermalGenerator::buildUnitPowerOutputVariables(const OptProblemSe } } } +} + +// create VARIABLES per day - ENS[t], Spill[t] +void OptimizedThermalGenerator::buildEnsAndSpillageVariables(const OptProblemSettings& optSett) +{ + for (int day = 0; day < timeHorizon_; ++day) + { + // add ENS variables + var.day[day].Ens = solver.MakeNumVar( + 0.0, infinity, "ENS_[" + std::to_string(day + optSett.firstDay) + "]"); + } + + for (int day = 0; day < timeHorizon_; ++day) + { + // add Spillage variables + var.day[day].Spill = solver.MakeNumVar( + 0.0, infinity, "Spill_[" + std::to_string(day + optSett.firstDay) + "]"); + } + return; +} + +// create VARIABLES per day and per cluster-unit - P[t][u] +void OptimizedThermalGenerator::buildUnitPowerOutputVariables(const OptProblemSettings& optSett) +{ // loop per day for (int day = 0; day < timeHorizon_; ++day) { diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index ce2137454b..36e0a24dba 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -24,6 +24,7 @@ class OptimizedThermalGenerator : public GeneratorTempData // optimization problem construction methods void buildProblemVariables(const OptProblemSettings& optSett); void countVariables(); + void allocateOptimizationProblemVariablesStruct(const OptProblemSettings& optSett); void buildEnsAndSpillageVariables(const OptProblemSettings& optSett); void buildUnitPowerOutputVariables(const OptProblemSettings& optSett); void buildStartEndMntVariables(const OptProblemSettings& optSett); From 7d5c5247d39f794a10ec45653cf8dd10632fefbd Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Mon, 20 Nov 2023 19:29:50 +0100 Subject: [PATCH 120/315] improve printAllVariables --- .../optimized-thermal-generator/CreateVariables.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp b/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp index 40444612fd..25f970e66a 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp @@ -247,6 +247,9 @@ void OptimizedThermalGenerator::printAllVariables() << "Lower bound: " << variable->lb() << ", " << "Upper bound: " << variable->ub() << std::endl; } + + std::cout << "total number of variables is: " << solver.NumVariables() << std::endl; + return; } From 49b495162160fd005a9bdc1c22b55da86adffc7d Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 21 Nov 2023 10:56:35 +0100 Subject: [PATCH 121/315] set problem cost - ens & spill + print out cost --- .../OptimizedGenerator.h | 9 +++ .../SetProblemCost.cpp | 70 +++++++++++++++++++ 2 files changed, 79 insertions(+) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 36e0a24dba..7e21b0319f 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -43,6 +43,15 @@ class OptimizedThermalGenerator : public GeneratorTempData void setMaxUnitOutputConstraints(); void setProblemCost(); + void setProblemEnsCost(MPObjective* objective); + void setProblemSpillCost(MPObjective* objective); + void setProblemPowerCost(MPObjective* objective); + void setProblemPowerCostPerGroup(); + void setProblemPowerCostPerArea(); + void setProblemPowerCostPerCluster(); + void setProblemPowerCostPerUnit(); + void printObjectiveFunction(MPObjective* objective); + void solveProblem(); void resetProblem(); diff --git a/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp b/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp index 70a5b68e0d..483a35f13d 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp @@ -7,8 +7,78 @@ namespace Antares::Solver::TSGenerator { // create OBJECTIVE FUNCTION - sum through [t] and sum through [u] +// sum[days]{ EnsCost*Ens[day] + SpillCost[day] + sum[units][ UnitCost*P[t][u] ] } void OptimizedThermalGenerator::setProblemCost() { + MPObjective* objective = solver.MutableObjective(); + + setProblemEnsCost(objective); + setProblemSpillCost(objective); + setProblemPowerCost(objective); + setProblemPowerCostPerGroup(); + setProblemPowerCostPerArea(); + setProblemPowerCostPerCluster(); + setProblemPowerCostPerUnit(); + + objective->SetMinimization(); + + printObjectiveFunction(objective); + + return; +} + +void OptimizedThermalGenerator::setProblemEnsCost(MPObjective* objective) +{ + // loop per day + for (int day = 0; day < timeHorizon_; ++day) + { + objective->SetCoefficient(var.day[day].Ens, ensCost_); + } + return; +} + +void OptimizedThermalGenerator::setProblemSpillCost(MPObjective* objective) +{ + // loop per day + for (int day = 0; day < timeHorizon_; ++day) + { + objective->SetCoefficient(var.day[day].Spill, spillCost_); + } + return; +} + +void OptimizedThermalGenerator::setProblemPowerCost(MPObjective* objective) +{ + +} + +void OptimizedThermalGenerator::setProblemPowerCostPerGroup() +{ + +} + +void OptimizedThermalGenerator::setProblemPowerCostPerArea() +{ + +} + +void OptimizedThermalGenerator::setProblemPowerCostPerCluster() +{ + +} + +void OptimizedThermalGenerator::setProblemPowerCostPerUnit() +{ + +} + +void OptimizedThermalGenerator::printObjectiveFunction(MPObjective* objective) +{ + for (MPVariable* variable : solver.variables()) + { + std::cout << variable->name() << ": " << objective->GetCoefficient(variable) << std::endl; + } + std::cout << std::endl; return; } From 29a99931dd6b0697b1b47e9ef3d736b4ca2e3d6e Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 21 Nov 2023 12:05:09 +0100 Subject: [PATCH 122/315] set problem cost - power output --- .../OptimizedGenerator.h | 16 +++- .../SetProblemCost.cpp | 78 ++++++++++++++++--- 2 files changed, 78 insertions(+), 16 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 7e21b0319f..00c95232da 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -46,10 +46,18 @@ class OptimizedThermalGenerator : public GeneratorTempData void setProblemEnsCost(MPObjective* objective); void setProblemSpillCost(MPObjective* objective); void setProblemPowerCost(MPObjective* objective); - void setProblemPowerCostPerGroup(); - void setProblemPowerCostPerArea(); - void setProblemPowerCostPerCluster(); - void setProblemPowerCostPerUnit(); + void setProblemPowerCostPerGroup(MPObjective* objective, int day); + void setProblemPowerCostPerArea(const Data::Area& area, MPObjective* objective, int day); + void setProblemPowerCostPerCluster(const Data::Area& area, + const Data::ThermalCluster& cluster, + MPObjective* objective, + int day); + void setProblemPowerCostPerUnit(const Data::Area& area, + const Data::ThermalCluster& cluster, + int unitIndex, + double powerCost, + MPObjective* objective, + int day); void printObjectiveFunction(MPObjective* objective); void solveProblem(); diff --git a/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp b/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp index 483a35f13d..6c30ee556a 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp @@ -15,10 +15,6 @@ void OptimizedThermalGenerator::setProblemCost() setProblemEnsCost(objective); setProblemSpillCost(objective); setProblemPowerCost(objective); - setProblemPowerCostPerGroup(); - setProblemPowerCostPerArea(); - setProblemPowerCostPerCluster(); - setProblemPowerCostPerUnit(); objective->SetMinimization(); @@ -49,27 +45,85 @@ void OptimizedThermalGenerator::setProblemSpillCost(MPObjective* objective) void OptimizedThermalGenerator::setProblemPowerCost(MPObjective* objective) { - + // loop per day + for (int day = 0; day < timeHorizon_; ++day) + { + setProblemPowerCostPerGroup(objective, day); + } + return; } -void OptimizedThermalGenerator::setProblemPowerCostPerGroup() +void OptimizedThermalGenerator::setProblemPowerCostPerGroup(MPObjective* objective, int day) { - + // loop per area inside maintenance group + for (const auto& entryWeightMap : maintenanceGroup_) + { + const auto& area = *(entryWeightMap.first); + setProblemPowerCostPerArea(area, objective, day); + } + return; } -void OptimizedThermalGenerator::setProblemPowerCostPerArea() +void OptimizedThermalGenerator::setProblemPowerCostPerArea(const Data::Area& area, + MPObjective* objective, + int day) { + // loop per thermal clusters inside the area + for (auto it = area.thermal.list.mapping.begin(); it != area.thermal.list.mapping.end(); ++it) + { + const auto& cluster = *(it->second); + + // we do not check if cluster.optimizeMaintenance = true here + // we add all the clusters Power inside maintenance group + if (!checkClusterExist(cluster)) + continue; + setProblemPowerCostPerCluster(area, cluster, objective, day); + } + return; } -void OptimizedThermalGenerator::setProblemPowerCostPerCluster() +void OptimizedThermalGenerator::setProblemPowerCostPerCluster(const Data::Area& area, + const Data::ThermalCluster& cluster, + MPObjective* objective, + int day) { - + /* + ** Unit cost can be directly set, + ** Or calculated using Fuel Cost, Co2 cost, Fuel Eff and V&O Cost. + + ** In second case we also need information which year it is (to choose proper TS number, and + also what hour it is) + ** we need price per day (so averaging the hourly values) + ** this is NOT calculated prior to the simulation - so if we only want to run ts-gen, we cannot + get this info just yet + ** using: + ** getMarginalCost(uint serieIndex, uint hourInTheYear) or + ** getMarketBidCost(uint hourInTheYear, uint year) + ** TODO CR27: maybe for phase-II + ** for now just disable this option but take into account the thermalModulationCost!! + */ + + // double unitPowerCost = calculateUnitPowerCost(area, cluster, day + optSett.firstDay); + double unitPowerCost = 15.4; + // loop per unit inside the cluster + for (int unit = 0; unit < cluster.unitCount; ++unit) + { + setProblemPowerCostPerUnit(area, cluster, unit, unitPowerCost, objective, day); + } + return; } -void OptimizedThermalGenerator::setProblemPowerCostPerUnit() +void OptimizedThermalGenerator::setProblemPowerCostPerUnit(const Data::Area& area, + const Data::ThermalCluster& cluster, + int unitIndex, + double cost, + MPObjective* objective, + int day) { - + objective->SetCoefficient(var.day[day].areaMap[&area].clusterMap[&cluster].unitMap[unitIndex].P, + cost); + return; } void OptimizedThermalGenerator::printObjectiveFunction(MPObjective* objective) From 0e6dacbb16c81184a513a56dc2c1ca1873e775e8 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 21 Nov 2023 12:20:30 +0100 Subject: [PATCH 123/315] refactor set objective cost - add optSett due to cluster power cost calculation --- .../OptimizedGenerator.h | 28 +++++++------ .../SetProblemCost.cpp | 39 +++++++++++-------- .../SolveProbem.cpp | 2 +- 3 files changed, 40 insertions(+), 29 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 00c95232da..42da628548 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -42,22 +42,28 @@ class OptimizedThermalGenerator : public GeneratorTempData void setStartEndMntLogicConstraints(); void setMaxUnitOutputConstraints(); - void setProblemCost(); + void setProblemCost(const OptProblemSettings& optSett); void setProblemEnsCost(MPObjective* objective); void setProblemSpillCost(MPObjective* objective); - void setProblemPowerCost(MPObjective* objective); - void setProblemPowerCostPerGroup(MPObjective* objective, int day); - void setProblemPowerCostPerArea(const Data::Area& area, MPObjective* objective, int day); - void setProblemPowerCostPerCluster(const Data::Area& area, - const Data::ThermalCluster& cluster, + void setProblemPowerCost(const OptProblemSettings& optSett, MPObjective* objective); + void setProblemPowerCostPerGroup(const OptProblemSettings& optSett, + MPObjective* objective, + int day); + void setProblemPowerCostPerArea(const OptProblemSettings& optSett, + MPObjective* objective, + int day, + const Data::Area& area); + void setProblemPowerCostPerCluster(const OptProblemSettings& optSett, MPObjective* objective, - int day); - void setProblemPowerCostPerUnit(const Data::Area& area, + int day, + const Data::Area& area, + const Data::ThermalCluster& cluster); + void setProblemPowerCostPerUnit(MPObjective* objective, + int day, + const Data::Area& area, const Data::ThermalCluster& cluster, int unitIndex, - double powerCost, - MPObjective* objective, - int day); + double powerCost); void printObjectiveFunction(MPObjective* objective); void solveProblem(); diff --git a/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp b/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp index 6c30ee556a..de8e9a1f3a 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp @@ -8,13 +8,13 @@ namespace Antares::Solver::TSGenerator { // create OBJECTIVE FUNCTION - sum through [t] and sum through [u] // sum[days]{ EnsCost*Ens[day] + SpillCost[day] + sum[units][ UnitCost*P[t][u] ] } -void OptimizedThermalGenerator::setProblemCost() +void OptimizedThermalGenerator::setProblemCost(const OptProblemSettings& optSett) { MPObjective* objective = solver.MutableObjective(); setProblemEnsCost(objective); setProblemSpillCost(objective); - setProblemPowerCost(objective); + setProblemPowerCost(optSett, objective); objective->SetMinimization(); @@ -43,30 +43,34 @@ void OptimizedThermalGenerator::setProblemSpillCost(MPObjective* objective) return; } -void OptimizedThermalGenerator::setProblemPowerCost(MPObjective* objective) +void OptimizedThermalGenerator::setProblemPowerCost(const OptProblemSettings& optSett, + MPObjective* objective) { // loop per day for (int day = 0; day < timeHorizon_; ++day) { - setProblemPowerCostPerGroup(objective, day); + setProblemPowerCostPerGroup(optSett, objective, day); } return; } -void OptimizedThermalGenerator::setProblemPowerCostPerGroup(MPObjective* objective, int day) +void OptimizedThermalGenerator::setProblemPowerCostPerGroup(const OptProblemSettings& optSett, + MPObjective* objective, + int day) { // loop per area inside maintenance group for (const auto& entryWeightMap : maintenanceGroup_) { const auto& area = *(entryWeightMap.first); - setProblemPowerCostPerArea(area, objective, day); + setProblemPowerCostPerArea(optSett, objective, day, area); } return; } -void OptimizedThermalGenerator::setProblemPowerCostPerArea(const Data::Area& area, +void OptimizedThermalGenerator::setProblemPowerCostPerArea(const OptProblemSettings& optSett, MPObjective* objective, - int day) + int day, + const Data::Area& area) { // loop per thermal clusters inside the area for (auto it = area.thermal.list.mapping.begin(); it != area.thermal.list.mapping.end(); ++it) @@ -78,15 +82,16 @@ void OptimizedThermalGenerator::setProblemPowerCostPerArea(const Data::Area& are if (!checkClusterExist(cluster)) continue; - setProblemPowerCostPerCluster(area, cluster, objective, day); + setProblemPowerCostPerCluster(optSett, objective, day, area, cluster); } return; } -void OptimizedThermalGenerator::setProblemPowerCostPerCluster(const Data::Area& area, - const Data::ThermalCluster& cluster, +void OptimizedThermalGenerator::setProblemPowerCostPerCluster(const OptProblemSettings& optSett, MPObjective* objective, - int day) + int day, + const Data::Area& area, + const Data::ThermalCluster& cluster) { /* ** Unit cost can be directly set, @@ -109,17 +114,17 @@ void OptimizedThermalGenerator::setProblemPowerCostPerCluster(const Data::Area& // loop per unit inside the cluster for (int unit = 0; unit < cluster.unitCount; ++unit) { - setProblemPowerCostPerUnit(area, cluster, unit, unitPowerCost, objective, day); + setProblemPowerCostPerUnit(objective, day, area, cluster, unit, unitPowerCost); } return; } -void OptimizedThermalGenerator::setProblemPowerCostPerUnit(const Data::Area& area, +void OptimizedThermalGenerator::setProblemPowerCostPerUnit(MPObjective* objective, + int day, + const Data::Area& area, const Data::ThermalCluster& cluster, int unitIndex, - double cost, - MPObjective* objective, - int day) + double cost) { objective->SetCoefficient(var.day[day].areaMap[&area].clusterMap[&cluster].unitMap[unitIndex].P, cost); diff --git a/src/solver/ts-generator/optimized-thermal-generator/SolveProbem.cpp b/src/solver/ts-generator/optimized-thermal-generator/SolveProbem.cpp index 6ce65b60a5..47aa359e8e 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/SolveProbem.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/SolveProbem.cpp @@ -12,7 +12,7 @@ void OptimizedThermalGenerator::runOptimizationProblem(const OptProblemSettings& buildProblemVariables(optSett); setVariableBounds(); buildProblemConstraints(); - setProblemCost(); + setProblemCost(optSett); solveProblem(); resetProblem(); } From a202e5b649d66bdf3577ca1ce86eb786232c780e Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 21 Nov 2023 12:35:01 +0100 Subject: [PATCH 124/315] calculateUnitPowerCost - structure [WIP] --- .../OptimizedGenerator.cpp | 16 ++++++++++++++++ .../OptimizedGenerator.h | 3 +++ .../SetProblemCost.cpp | 3 +-- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp index d3ad912c6f..314901f417 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp @@ -285,6 +285,22 @@ std::array OptimizedThermalGenerator::calculateMaxUnitOut return maxOutputDailyValues; } +double OptimizedThermalGenerator::calculateUnitPowerCost(const Data::Area& area, + const Data::ThermalCluster& cluster, + int day) +{ + if (cluster.costgeneration == Data::useCostTimeseries) + { + logs.warning() + << "Cluster: " << cluster.getFullName() + << " has Cost generation set to: Use cost timeseries. Option not suported yet. " + "Cost set to zero."; + return 0.; + } + // TODO CR27: return proper mean daily value + return 15.55; +} + // calculate parameters methods - per cluster-Unit int OptimizedThermalGenerator::calculateUnitEarliestStartOfFirstMaintenance( Data::ThermalCluster& cluster, diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 42da628548..5e3753e25c 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -86,6 +86,9 @@ class OptimizedThermalGenerator : public GeneratorTempData uint calculateNumberOfMaintenances(const Data::ThermalCluster& cluster, uint timeHorizon); uint calculateAverageMaintenanceDuration(Data::ThermalCluster& cluster); std::array calculateMaxUnitOutput(Data::ThermalCluster& cluster); + double calculateUnitPowerCost(const Data::Area& area, + const Data::ThermalCluster& cluster, + int day); // calculate parameters methods - per cluster-Unit int calculateUnitEarliestStartOfFirstMaintenance(Data::ThermalCluster& cluster, uint unitIndex); diff --git a/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp b/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp index de8e9a1f3a..7ff762d285 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp @@ -109,8 +109,7 @@ void OptimizedThermalGenerator::setProblemPowerCostPerCluster(const OptProblemSe ** for now just disable this option but take into account the thermalModulationCost!! */ - // double unitPowerCost = calculateUnitPowerCost(area, cluster, day + optSett.firstDay); - double unitPowerCost = 15.4; + double unitPowerCost = calculateUnitPowerCost(area, cluster, day + optSett.firstDay); // loop per unit inside the cluster for (int unit = 0; unit < cluster.unitCount; ++unit) { From 6bb6bbb74050e4de7f4c021da52585cb5f62d329 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 21 Nov 2023 12:54:07 +0100 Subject: [PATCH 125/315] create DailyClusterData structure --- .../AuxillaryStructures.h | 27 +++++++++++++++++++ .../OptimizedGenerator.cpp | 6 ++--- .../OptimizedGenerator.h | 7 ++--- .../SetProblemCost.cpp | 2 +- 4 files changed, 35 insertions(+), 7 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h index cf96673d93..e08309d03f 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h +++ b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h @@ -55,4 +55,31 @@ struct OptimizationProblemVariables std::vector day; }; +// it is better to immediately calculate and populate structures +// that will store information about: +// for each area and each cluster: +// daily arrays with info about: +// daily MaxUnitOutput and +// daily UnitPowerCost +// so inside optimization problem we just retrieve these data +// not re-calculate them over and over again + +struct DailyClusterDataPerCluster +{ + std::array maxPower; + std::array unitCost; +}; + +struct DailyClusterDataPerArea +{ + // number of elements in the map is total number of cluster in area + std::map clusterMap; +}; + +struct DailyClusterData +{ + // number of elements in the map is total number of areas in maintenance group + std::map areaMap; +}; + } // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp index 314901f417..8e75e73779 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp @@ -285,9 +285,9 @@ std::array OptimizedThermalGenerator::calculateMaxUnitOut return maxOutputDailyValues; } -double OptimizedThermalGenerator::calculateUnitPowerCost(const Data::Area& area, - const Data::ThermalCluster& cluster, - int day) +double OptimizedThermalGenerator::returnUnitPowerCost(const Data::Area& area, + const Data::ThermalCluster& cluster, + int day) { if (cluster.costgeneration == Data::useCostTimeseries) { diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 5e3753e25c..7e49cbc593 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -86,9 +86,9 @@ class OptimizedThermalGenerator : public GeneratorTempData uint calculateNumberOfMaintenances(const Data::ThermalCluster& cluster, uint timeHorizon); uint calculateAverageMaintenanceDuration(Data::ThermalCluster& cluster); std::array calculateMaxUnitOutput(Data::ThermalCluster& cluster); - double calculateUnitPowerCost(const Data::Area& area, - const Data::ThermalCluster& cluster, - int day); + double returnUnitPowerCost(const Data::Area& area, + const Data::ThermalCluster& cluster, + int day); // calculate parameters methods - per cluster-Unit int calculateUnitEarliestStartOfFirstMaintenance(Data::ThermalCluster& cluster, uint unitIndex); @@ -120,6 +120,7 @@ class OptimizedThermalGenerator : public GeneratorTempData double ensCost_; double spillCost_; std::array residualLoadDailyValues_; + DailyClusterData dailyClusterData; OptimizationProblemVariables var; // MPSolver instance diff --git a/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp b/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp index 7ff762d285..0a23cd55cb 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp @@ -109,7 +109,7 @@ void OptimizedThermalGenerator::setProblemPowerCostPerCluster(const OptProblemSe ** for now just disable this option but take into account the thermalModulationCost!! */ - double unitPowerCost = calculateUnitPowerCost(area, cluster, day + optSett.firstDay); + double unitPowerCost = returnUnitPowerCost(area, cluster, day + optSett.firstDay); // loop per unit inside the cluster for (int unit = 0; unit < cluster.unitCount; ++unit) { From 9882ff097c4dbe51f1b31758acfd4ca460978940 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 21 Nov 2023 13:22:55 +0100 Subject: [PATCH 126/315] calculateAvrUnitDailyCost [WIP] --- .../OptimizedGenerator.cpp | 44 ++++++++++++++----- .../OptimizedGenerator.h | 5 +-- .../SetProblemCost.cpp | 3 +- 3 files changed, 37 insertions(+), 15 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp index 8e75e73779..b69089419a 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp @@ -285,20 +285,42 @@ std::array OptimizedThermalGenerator::calculateMaxUnitOut return maxOutputDailyValues; } -double OptimizedThermalGenerator::returnUnitPowerCost(const Data::Area& area, - const Data::ThermalCluster& cluster, - int day) +std::array OptimizedThermalGenerator::calculateAvrUnitDailyCost( + const Data::ThermalCluster& cluster) { - if (cluster.costgeneration == Data::useCostTimeseries) + std::array avrCostDailyValues = {}; + std::array costHourlyValues = {}; + + // transfer to array + for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) { - logs.warning() - << "Cluster: " << cluster.getFullName() - << " has Cost generation set to: Use cost timeseries. Option not suported yet. " - "Cost set to zero."; - return 0.; + costHourlyValues[row] + = cluster.modulation[Data::ThermalModulation::thermalModulationMarketBid][row]; } - // TODO CR27: return proper mean daily value - return 15.55; + + avrCostDailyValues = calculateDailySums(costHourlyValues); + // multiply by per unit/cluster market bid cost + average this on 24 hours + for (double& num : avrCostDailyValues) + { + num *= cluster.marketBidCost / 24.0; + } + return avrCostDailyValues; +} + +double OptimizedThermalGenerator::returnUnitPowerCost(std::array dailyCost, + int optimizationDay) +{ + // if (cluster.costgeneration == Data::useCostTimeseries) + // { + // logs.warning() + // << "Cluster: " << cluster.getFullName() + // << " has Cost generation set to: Use cost timeseries. Option not suported yet. " + // "Cost set to zero."; + // return 0.; + // } + + int realDay = dayOfTheYear(optimizationDay); + return dailyCost[realDay]; } // calculate parameters methods - per cluster-Unit diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 7e49cbc593..fb5dcf39e8 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -86,9 +86,8 @@ class OptimizedThermalGenerator : public GeneratorTempData uint calculateNumberOfMaintenances(const Data::ThermalCluster& cluster, uint timeHorizon); uint calculateAverageMaintenanceDuration(Data::ThermalCluster& cluster); std::array calculateMaxUnitOutput(Data::ThermalCluster& cluster); - double returnUnitPowerCost(const Data::Area& area, - const Data::ThermalCluster& cluster, - int day); + std::array calculateAvrUnitDailyCost(const Data::ThermalCluster& cluster); + double returnUnitPowerCost(std::array dailyCost, int optimizationDay); // calculate parameters methods - per cluster-Unit int calculateUnitEarliestStartOfFirstMaintenance(Data::ThermalCluster& cluster, uint unitIndex); diff --git a/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp b/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp index 0a23cd55cb..0abd4464f9 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp @@ -109,7 +109,8 @@ void OptimizedThermalGenerator::setProblemPowerCostPerCluster(const OptProblemSe ** for now just disable this option but take into account the thermalModulationCost!! */ - double unitPowerCost = returnUnitPowerCost(area, cluster, day + optSett.firstDay); + auto dailyUnitPowerCost = calculateAvrUnitDailyCost(cluster); + double unitPowerCost = returnUnitPowerCost(dailyUnitPowerCost, day + optSett.firstDay); // loop per unit inside the cluster for (int unit = 0; unit < cluster.unitCount; ++unit) { From f8261910cd04775dc514a93e3e4621c868627346 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 21 Nov 2023 13:35:52 +0100 Subject: [PATCH 127/315] getters for cluster daily output and cost --- .../OptimizedGenerator.cpp | 33 ++++++++++++------- .../OptimizedGenerator.h | 4 ++- .../SetProblemCost.cpp | 3 +- 3 files changed, 26 insertions(+), 14 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp index b69089419a..7e7eef1a60 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp @@ -307,20 +307,31 @@ std::array OptimizedThermalGenerator::calculateAvrUnitDai return avrCostDailyValues; } -double OptimizedThermalGenerator::returnUnitPowerCost(std::array dailyCost, - int optimizationDay) +double OptimizedThermalGenerator::getUnitPowerCost(const Data::ThermalCluster& cluster, + int optimizationDay) { - // if (cluster.costgeneration == Data::useCostTimeseries) - // { - // logs.warning() - // << "Cluster: " << cluster.getFullName() - // << " has Cost generation set to: Use cost timeseries. Option not suported yet. " - // "Cost set to zero."; - // return 0.; - // } + if (cluster.costgeneration == Data::useCostTimeseries) + { + logs.warning() + << "Cluster: " << cluster.getFullName() + << " has Cost generation set to: Use cost timeseries. Option not suported yet. " + "Cost set to zero."; + return 0.; + } + + int realDay = dayOfTheYear(optimizationDay); + auto unitCost + = dailyClusterData.areaMap[cluster.parentArea].clusterMap[&cluster].unitCost[realDay]; + return unitCost; +} +double OptimizedThermalGenerator::getUnitPowerOutput(const Data::ThermalCluster& cluster, + int optimizationDay) +{ int realDay = dayOfTheYear(optimizationDay); - return dailyCost[realDay]; + auto unitOutput + = dailyClusterData.areaMap[cluster.parentArea].clusterMap[&cluster].maxPower[realDay]; + return unitOutput; } // calculate parameters methods - per cluster-Unit diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index fb5dcf39e8..c7f03e0dec 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -87,7 +87,9 @@ class OptimizedThermalGenerator : public GeneratorTempData uint calculateAverageMaintenanceDuration(Data::ThermalCluster& cluster); std::array calculateMaxUnitOutput(Data::ThermalCluster& cluster); std::array calculateAvrUnitDailyCost(const Data::ThermalCluster& cluster); - double returnUnitPowerCost(std::array dailyCost, int optimizationDay); + + double getUnitPowerCost(const Data::ThermalCluster& cluster, int optimizationDay); + double getUnitPowerOutput(const Data::ThermalCluster& cluster, int optimizationDay); // calculate parameters methods - per cluster-Unit int calculateUnitEarliestStartOfFirstMaintenance(Data::ThermalCluster& cluster, uint unitIndex); diff --git a/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp b/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp index 0abd4464f9..64e693a408 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp @@ -109,8 +109,7 @@ void OptimizedThermalGenerator::setProblemPowerCostPerCluster(const OptProblemSe ** for now just disable this option but take into account the thermalModulationCost!! */ - auto dailyUnitPowerCost = calculateAvrUnitDailyCost(cluster); - double unitPowerCost = returnUnitPowerCost(dailyUnitPowerCost, day + optSett.firstDay); + double unitPowerCost = getUnitPowerCost(cluster, day + optSett.firstDay); // loop per unit inside the cluster for (int unit = 0; unit < cluster.unitCount; ++unit) { From 56fb3f16b0415fb46da687a38149337f56a4a010 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 21 Nov 2023 14:22:48 +0100 Subject: [PATCH 128/315] setClusterDailyValues - not checked! --- .../OptimizedGenerator.cpp | 30 ++++++++++++++++++- .../OptimizedGenerator.h | 8 +++-- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp index 7e7eef1a60..b4beeba0f8 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp @@ -116,6 +116,7 @@ void OptimizedThermalGenerator::setMaintenanceGroupParameters() residualLoadDailyValues_ = calculateDailySums(maintenanceGroup_.getUsedResidualLoadTS()); std::tie(ensCost_, spillCost_) = calculateMaintenanceGroupENSandSpillageCost(); std::tie(timeStep_, timeHorizon_) = calculateTimeHorizonAndStep(); + setClusterDailyValues(); } bool OptimizedThermalGenerator::checkMaintenanceGroupParameters() @@ -264,7 +265,7 @@ uint OptimizedThermalGenerator::calculateAverageMaintenanceDuration(Data::Therma } std::array OptimizedThermalGenerator::calculateMaxUnitOutput( - Data::ThermalCluster& cluster) + const Data::ThermalCluster& cluster) { std::array maxOutputDailyValues = {}; std::array maxOutputHourlyValues = {}; @@ -307,6 +308,33 @@ std::array OptimizedThermalGenerator::calculateAvrUnitDai return avrCostDailyValues; } +void OptimizedThermalGenerator::setClusterDailyValues() +{ + for (const auto& entryWeightMap : maintenanceGroup_) + { + const auto& area = *(entryWeightMap.first); + auto& areaVariables = dailyClusterData.areaMap; + areaVariables[&area] = DailyClusterDataPerArea(); + // loop per thermal clusters inside the area - fill in the structure + for (auto it = area.thermal.list.mapping.begin(); it != area.thermal.list.mapping.end(); + ++it) + { + const auto& cluster = *(it->second); + + // we do not check if cluster.optimizeMaintenance = true here + // we add all the clusters Power inside maintenance group + if (!checkClusterExist(cluster)) + continue; + + auto& clusterVariables = areaVariables[&area].clusterMap; + clusterVariables[&cluster] = DailyClusterDataPerCluster(); + clusterVariables[&cluster].maxPower = calculateMaxUnitOutput(cluster); + clusterVariables[&cluster].unitCost = calculateAvrUnitDailyCost(cluster); + } + } + return; +} + double OptimizedThermalGenerator::getUnitPowerCost(const Data::ThermalCluster& cluster, int optimizationDay) { diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index c7f03e0dec..878e8baf10 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -85,8 +85,10 @@ class OptimizedThermalGenerator : public GeneratorTempData // calculate parameters methods - per cluster uint calculateNumberOfMaintenances(const Data::ThermalCluster& cluster, uint timeHorizon); uint calculateAverageMaintenanceDuration(Data::ThermalCluster& cluster); - std::array calculateMaxUnitOutput(Data::ThermalCluster& cluster); - std::array calculateAvrUnitDailyCost(const Data::ThermalCluster& cluster); + static std::array calculateMaxUnitOutput(const Data::ThermalCluster& cluster); + static std::array calculateAvrUnitDailyCost(const Data::ThermalCluster& cluster); + + void setClusterDailyValues(); double getUnitPowerCost(const Data::ThermalCluster& cluster, int optimizationDay); double getUnitPowerOutput(const Data::ThermalCluster& cluster, int optimizationDay); @@ -96,7 +98,7 @@ class OptimizedThermalGenerator : public GeneratorTempData int calculateUnitLatestStartOfFirstMaintenance(Data::ThermalCluster& cluster, uint unitIndex); // auxillary functions - std::array calculateDailySums( + static std::array calculateDailySums( const std::array& hourlyValues); std::array calculateAverageTs(const Matrix& tsValue, const Matrix& tsNumbers); From 5fa408c256c11dacd76a6a257db774b2de90105b Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 21 Nov 2023 15:15:59 +0100 Subject: [PATCH 129/315] clean & refactor + tested setClusterDailyValues-OK --- .../CreateVariables.cpp | 5 +- .../OptimizedGenerator.cpp | 70 ++++++++++++------- .../OptimizedGenerator.h | 7 +- .../SetProblemCost.cpp | 16 ----- 4 files changed, 48 insertions(+), 50 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp b/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp index 25f970e66a..44326010b5 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp @@ -11,7 +11,7 @@ void OptimizedThermalGenerator::buildProblemVariables(const OptProblemSettings& // this is now just dummy optimization problem countVariables(); - allocateOptimizationProblemVariablesStruct(optSett); + allocateOptimizationProblemVariablesStruct(); buildEnsAndSpillageVariables(optSett); buildUnitPowerOutputVariables(optSett); buildStartEndMntVariables(optSett); @@ -76,8 +76,7 @@ void OptimizedThermalGenerator::countVariables() } // populate OptimizationProblemVariables struct -void OptimizedThermalGenerator::allocateOptimizationProblemVariablesStruct( - const OptProblemSettings& optSett) +void OptimizedThermalGenerator::allocateOptimizationProblemVariablesStruct() { // loop per day - fill in structure for (int day = 0; day < timeHorizon_; ++day) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp index b4beeba0f8..256f38a50c 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp @@ -236,6 +236,33 @@ void OptimizedThermalGenerator::calculateResidualLoad() maintenanceGroup_.setUsedResidualLoadTS(refValue); } +void OptimizedThermalGenerator::setClusterDailyValues() +{ + for (const auto& entryWeightMap : maintenanceGroup_) + { + const auto& area = *(entryWeightMap.first); + auto& areaVariables = dailyClusterData.areaMap; + areaVariables[&area] = DailyClusterDataPerArea(); + // loop per thermal clusters inside the area - fill in the structure + for (auto it = area.thermal.list.mapping.begin(); it != area.thermal.list.mapping.end(); + ++it) + { + const auto& cluster = *(it->second); + + // we do not check if cluster.optimizeMaintenance = true here + // we add all the clusters Power inside maintenance group + if (!checkClusterExist(cluster)) + continue; + + auto& clusterVariables = areaVariables[&area].clusterMap; + clusterVariables[&cluster] = DailyClusterDataPerCluster(); + clusterVariables[&cluster].maxPower = calculateMaxUnitOutput(cluster); + clusterVariables[&cluster].unitCost = calculateAvrUnitDailyCost(cluster); + } + } + return; +} + // calculate parameters methods - per cluster uint OptimizedThermalGenerator::calculateNumberOfMaintenances(const Data::ThermalCluster& cluster, uint timeHorizon) @@ -308,36 +335,25 @@ std::array OptimizedThermalGenerator::calculateAvrUnitDai return avrCostDailyValues; } -void OptimizedThermalGenerator::setClusterDailyValues() -{ - for (const auto& entryWeightMap : maintenanceGroup_) - { - const auto& area = *(entryWeightMap.first); - auto& areaVariables = dailyClusterData.areaMap; - areaVariables[&area] = DailyClusterDataPerArea(); - // loop per thermal clusters inside the area - fill in the structure - for (auto it = area.thermal.list.mapping.begin(); it != area.thermal.list.mapping.end(); - ++it) - { - const auto& cluster = *(it->second); - - // we do not check if cluster.optimizeMaintenance = true here - // we add all the clusters Power inside maintenance group - if (!checkClusterExist(cluster)) - continue; - - auto& clusterVariables = areaVariables[&area].clusterMap; - clusterVariables[&cluster] = DailyClusterDataPerCluster(); - clusterVariables[&cluster].maxPower = calculateMaxUnitOutput(cluster); - clusterVariables[&cluster].unitCost = calculateAvrUnitDailyCost(cluster); - } - } - return; -} - double OptimizedThermalGenerator::getUnitPowerCost(const Data::ThermalCluster& cluster, int optimizationDay) { + /* + ** Unit cost can be directly set, + ** Or calculated using Fuel Cost, Co2 cost, Fuel Eff and V&O Cost. + + ** In second case we also need information which year it is (to choose proper TS number, and + also what hour it is) + ** we need price per day (so averaging the hourly values) + ** this is NOT calculated prior to the simulation - so if we only want to run ts-gen, we cannot + get this info just yet + ** using: + ** getMarginalCost(uint serieIndex, uint hourInTheYear) or + ** getMarketBidCost(uint hourInTheYear, uint year) + ** TODO CR27: maybe for phase-II + ** for now just disable this option but take into account the thermalModulationCost!! + */ + if (cluster.costgeneration == Data::useCostTimeseries) { logs.warning() diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 878e8baf10..2e54f62c9a 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -24,7 +24,7 @@ class OptimizedThermalGenerator : public GeneratorTempData // optimization problem construction methods void buildProblemVariables(const OptProblemSettings& optSett); void countVariables(); - void allocateOptimizationProblemVariablesStruct(const OptProblemSettings& optSett); + void allocateOptimizationProblemVariablesStruct(); void buildEnsAndSpillageVariables(const OptProblemSettings& optSett); void buildUnitPowerOutputVariables(const OptProblemSettings& optSett); void buildStartEndMntVariables(const OptProblemSettings& optSett); @@ -81,15 +81,14 @@ class OptimizedThermalGenerator : public GeneratorTempData std::pair calculateTimeHorizonAndStep(); std::pair calculateMaintenanceGroupENSandSpillageCost(); void calculateResidualLoad(); + void setClusterDailyValues(); // calculate parameters methods - per cluster uint calculateNumberOfMaintenances(const Data::ThermalCluster& cluster, uint timeHorizon); uint calculateAverageMaintenanceDuration(Data::ThermalCluster& cluster); static std::array calculateMaxUnitOutput(const Data::ThermalCluster& cluster); static std::array calculateAvrUnitDailyCost(const Data::ThermalCluster& cluster); - - void setClusterDailyValues(); - + // getters double getUnitPowerCost(const Data::ThermalCluster& cluster, int optimizationDay); double getUnitPowerOutput(const Data::ThermalCluster& cluster, int optimizationDay); diff --git a/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp b/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp index 64e693a408..b4d8ac281a 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp @@ -93,22 +93,6 @@ void OptimizedThermalGenerator::setProblemPowerCostPerCluster(const OptProblemSe const Data::Area& area, const Data::ThermalCluster& cluster) { - /* - ** Unit cost can be directly set, - ** Or calculated using Fuel Cost, Co2 cost, Fuel Eff and V&O Cost. - - ** In second case we also need information which year it is (to choose proper TS number, and - also what hour it is) - ** we need price per day (so averaging the hourly values) - ** this is NOT calculated prior to the simulation - so if we only want to run ts-gen, we cannot - get this info just yet - ** using: - ** getMarginalCost(uint serieIndex, uint hourInTheYear) or - ** getMarketBidCost(uint hourInTheYear, uint year) - ** TODO CR27: maybe for phase-II - ** for now just disable this option but take into account the thermalModulationCost!! - */ - double unitPowerCost = getUnitPowerCost(cluster, day + optSett.firstDay); // loop per unit inside the cluster for (int unit = 0; unit < cluster.unitCount; ++unit) From 29ed5c54ada60a5e5380f4833c892a8b44d14c3c Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 22 Nov 2023 10:49:55 +0100 Subject: [PATCH 130/315] refactor - move parameters calc methods to separate cpp file --- src/solver/ts-generator/CMakeLists.txt | 1 + .../CalculateParameters.cpp | 463 ++++++++++++++++++ .../OptimizedGenerator.cpp | 453 ----------------- 3 files changed, 464 insertions(+), 453 deletions(-) create mode 100644 src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp diff --git a/src/solver/ts-generator/CMakeLists.txt b/src/solver/ts-generator/CMakeLists.txt index 4e7cabf28f..2fe4ab8a1e 100644 --- a/src/solver/ts-generator/CMakeLists.txt +++ b/src/solver/ts-generator/CMakeLists.txt @@ -18,6 +18,7 @@ set(SRC_OPTIMIZEDGENERATORS optimized-thermal-generator/pre-scenario-builder.cpp optimized-thermal-generator/OptimizedGenerator.h optimized-thermal-generator/OptimizedGenerator.cpp + optimized-thermal-generator/CalculateParameters.cpp optimized-thermal-generator/CreateVariables.cpp optimized-thermal-generator/SetVariableBounds.cpp optimized-thermal-generator/SetProblemConstraints.cpp diff --git a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp new file mode 100644 index 0000000000..cae770c73f --- /dev/null +++ b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp @@ -0,0 +1,463 @@ +// +// Created by milos on 14/11/23. +// + +#include "OptimizedGenerator.h" + +namespace Antares::Solver::TSGenerator +{ + +// calculate parameters methods - per maintenance group +void OptimizedThermalGenerator::setMaintenanceGroupParameters() +{ + // timeHorizon, timeStep ENS and Spillage are defined per one MaintenanceGroup + // Residual Load (or reference value) array is defined per one MaintenanceGroup + calculateResidualLoad(); + residualLoadDailyValues_ = calculateDailySums(maintenanceGroup_.getUsedResidualLoadTS()); + std::tie(ensCost_, spillCost_) = calculateMaintenanceGroupENSandSpillageCost(); + std::tie(timeStep_, timeHorizon_) = calculateTimeHorizonAndStep(); + setClusterDailyValues(); +} + +bool OptimizedThermalGenerator::checkMaintenanceGroupParameters() +{ + if (timeStep_ == 0) + { + logs.info() << "Maintenance group: " << maintenanceGroup_.name() + << ": The timeseries generation will be skiped: timeStep = 0. It is possible " + "that the maintenance group has no clusters designated for maintenance " + "planning, or at least one cluster has interPoPeriod = 0"; + return false; + } + if (timeHorizon_ == 0) + { + logs.info() + << "Maintenance group: " << maintenanceGroup_.name() + << ": The timeseries generation will be skiped: timeHorizon = 0. It is possible " + "that the maintenance group has no clusters designated for maintenance " + "planning, or all clusters have interPoPeriod = 0"; + return false; + } + // add some more check here if necessary! + return true; +} + +std::pair OptimizedThermalGenerator::calculateTimeHorizonAndStep() +{ + std::vector averageDurationBetweenMaintenances = {}; + for (const auto& entryWeightMap : maintenanceGroup_) + { + const auto& area = *(entryWeightMap.first); + for (auto it = area.thermal.list.mapping.begin(); it != area.thermal.list.mapping.end(); + ++it) + { + const auto& cluster = *(it->second); + if (cluster.doWeGenerateTS(globalThermalTSgeneration_) && cluster.optimizeMaintenance) + { + averageDurationBetweenMaintenances.push_back(cluster.interPoPeriod); + } + } + } + + // Using std::minmax_element to find min and max + auto [minIter, maxIter] = std::minmax_element(averageDurationBetweenMaintenances.begin(), + averageDurationBetweenMaintenances.end()); + + // Check if the vector is not empty + if (minIter != averageDurationBetweenMaintenances.end() + && maxIter != averageDurationBetweenMaintenances.end()) + { + return std::make_pair(*minIter, 2 * (*maxIter)); + } + + return std::make_pair(0, 0); +} + +std::pair OptimizedThermalGenerator::calculateMaintenanceGroupENSandSpillageCost() +{ + std::vector ensVector = {}; + std::vector spillageVector = {}; + for (const auto& entryWeightMap : maintenanceGroup_) + { + const auto& area = *(entryWeightMap.first); + ensVector.push_back(area.thermal.unsuppliedEnergyCost); + spillageVector.push_back(area.thermal.spilledEnergyCost); + } + + // Using std::minmax_element to find min and max + auto ens = std::min_element(ensVector.begin(), ensVector.end()); + auto spill = std::min_element(spillageVector.begin(), spillageVector.end()); + + // Check if the vector is not empty + if (ens != ensVector.end() && spill != spillageVector.end()) + { + return std::make_pair(*ens, *spill); + } + + return std::make_pair(0, 0); +} + +void OptimizedThermalGenerator::calculateResidualLoad() +{ + // create reference value arrays + std::array refValueLoad = {}; + std::array refValueRor = {}; + std::array refValueRenewable = {}; + std::array refValue = {}; + + // for phase II + if (maintenanceGroup_.type() == Data::MaintenanceGroup::typeTimeserie) + { + // read user defined ts - userProvidedResidualLoadTS_ with getter - phase-II + return; + } + + // loop through the elements of weightMap weights_ + for (const auto& entryWeightMap : maintenanceGroup_) + { + const auto& area = *(entryWeightMap.first); + const auto weights = (entryWeightMap.second); + + auto tmpLoad = calculateAverageLoadTs(area); + auto tmpRor = calculateAverageRorTs(area); + auto tmpRenewable = calculateAverageRenewableTs(area); + + for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) + { + refValueLoad[row] += tmpLoad[row] * weights.load; + refValueRor[row] += tmpRor[row] * weights.ror; + refValueRenewable[row] += tmpRenewable[row] * weights.renewable; + } + } + // calculate reference value + for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) + refValue[row] = refValueLoad[row] - refValueRor[row] - refValueRenewable[row]; + // set ResidualLoadTS + maintenanceGroup_.setUsedResidualLoadTS(refValue); +} + +void OptimizedThermalGenerator::setClusterDailyValues() +{ + for (const auto& entryWeightMap : maintenanceGroup_) + { + const auto& area = *(entryWeightMap.first); + auto& areaVariables = dailyClusterData.areaMap; + areaVariables[&area] = DailyClusterDataPerArea(); + // loop per thermal clusters inside the area - fill in the structure + for (auto it = area.thermal.list.mapping.begin(); it != area.thermal.list.mapping.end(); + ++it) + { + const auto& cluster = *(it->second); + + // we do not check if cluster.optimizeMaintenance = true here + // we add all the clusters Power inside maintenance group + if (!checkClusterExist(cluster)) + continue; + + auto& clusterVariables = areaVariables[&area].clusterMap; + clusterVariables[&cluster] = DailyClusterDataPerCluster(); + clusterVariables[&cluster].maxPower = calculateMaxUnitOutput(cluster); + clusterVariables[&cluster].unitCost = calculateAvrUnitDailyCost(cluster); + } + } + return; +} + +// calculate parameters methods - per cluster +uint OptimizedThermalGenerator::calculateNumberOfMaintenances(const Data::ThermalCluster& cluster, + uint timeHorizon) +{ + // timeHorizon cannot be 0. The whole maintenance group would be skipped if this happened + // on the other hand interPoPeriod can be 0. So we say at least 2 maintenance if this happens + if (cluster.interPoPeriod == 0) + { + logs.warning() << "Cluster: " << cluster.getFullName() + << "has interPoPeriod = 0. Number of maintenances for all units inside this " + "cluster will be set to 2"; + return minNumberOfMaintenances; + } + + return timeHorizon / cluster.interPoPeriod; // floor +} + +uint OptimizedThermalGenerator::calculateAverageMaintenanceDuration(Data::ThermalCluster& cluster) +{ + double sum = 0.0; + for (std::size_t row = 0; row < DAYS_PER_YEAR; ++row) + { + sum += cluster.prepro->data[Data::PreproThermal::poDuration][row]; + } + + return sum / static_cast(DAYS_PER_YEAR); +} + +std::array OptimizedThermalGenerator::calculateMaxUnitOutput( + const Data::ThermalCluster& cluster) +{ + std::array maxOutputDailyValues = {}; + std::array maxOutputHourlyValues = {}; + + // transfer to array + for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) + { + maxOutputHourlyValues[row] + = cluster.modulation[Data::ThermalModulation::thermalModulationCapacity][row]; + } + + maxOutputDailyValues = calculateDailySums(maxOutputHourlyValues); + // multiply by per unit power (nominal capacity) + for (double& num : maxOutputDailyValues) + { + num *= cluster.nominalCapacity; + } + return maxOutputDailyValues; +} + +std::array OptimizedThermalGenerator::calculateAvrUnitDailyCost( + const Data::ThermalCluster& cluster) +{ + std::array avrCostDailyValues = {}; + std::array costHourlyValues = {}; + + // transfer to array + for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) + { + costHourlyValues[row] + = cluster.modulation[Data::ThermalModulation::thermalModulationMarketBid][row]; + } + + avrCostDailyValues = calculateDailySums(costHourlyValues); + // multiply by per unit/cluster market bid cost + average this on 24 hours + for (double& num : avrCostDailyValues) + { + num *= cluster.marketBidCost / 24.0; + } + return avrCostDailyValues; +} + +double OptimizedThermalGenerator::getUnitPowerCost(const Data::ThermalCluster& cluster, + int optimizationDay) +{ + /* + ** Unit cost can be directly set, + ** Or calculated using Fuel Cost, Co2 cost, Fuel Eff and V&O Cost. + + ** In second case we also need information which year it is (to choose proper TS number, and + also what hour it is) + ** we need price per day (so averaging the hourly values) + ** this is NOT calculated prior to the simulation - so if we only want to run ts-gen, we cannot + get this info just yet + ** using: + ** getMarginalCost(uint serieIndex, uint hourInTheYear) or + ** getMarketBidCost(uint hourInTheYear, uint year) + ** TODO CR27: maybe for phase-II + ** for now just disable this option but take into account the thermalModulationCost!! + */ + + if (cluster.costgeneration == Data::useCostTimeseries) + { + logs.warning() + << "Cluster: " << cluster.getFullName() + << " has Cost generation set to: Use cost timeseries. Option not suported yet. " + "Cost set to zero."; + return 0.; + } + + int realDay = dayOfTheYear(optimizationDay); + auto unitCost + = dailyClusterData.areaMap[cluster.parentArea].clusterMap[&cluster].unitCost[realDay]; + return unitCost; +} + +double OptimizedThermalGenerator::getUnitPowerOutput(const Data::ThermalCluster& cluster, + int optimizationDay) +{ + int realDay = dayOfTheYear(optimizationDay); + auto unitOutput + = dailyClusterData.areaMap[cluster.parentArea].clusterMap[&cluster].maxPower[realDay]; + return unitOutput; +} + +// calculate parameters methods - per cluster-Unit +int OptimizedThermalGenerator::calculateUnitEarliestStartOfFirstMaintenance( + Data::ThermalCluster& cluster, + uint unitIndex) +{ + // earliest start of the first maintenance of unit u (beginning of the window, can be negative): + // let it return negative value - if it returns negative value we wont implement constraint: + // s[tauLower-1][u][1] = 0 + // TODO CR27: if the approach above breaks the solver + // we force the start of the first maintenance to be after day=0 + // s[fixed = 0][u][1] = 0 + if (unitIndex < cluster.daysSinceLastMaintenance.size()) + { + return (cluster.interPoPeriod - cluster.daysSinceLastMaintenance[unitIndex] + - cluster.poWindows); + } + else + { + logs.error() << "Cluster: " << cluster.getFullName() + << " does not have unit: " << unitIndex; + return 0; + } +} + +int OptimizedThermalGenerator::calculateUnitLatestStartOfFirstMaintenance( + Data::ThermalCluster& cluster, + uint unitIndex) +{ + // latest start of the first maintenance of unit u (end of the window, must be positive): + if (unitIndex < cluster.daysSinceLastMaintenance.size()) + { + // this cannot be negative: + // cluster.interPoPeriod - cluster.daysSinceLastMaintenance[unitIndex] - is always positive + // or zero + // cluster.poWindows is positive or zero + // so std::max is not necessary but I will keep it for now + return std::max( + cluster.interPoPeriod - cluster.daysSinceLastMaintenance[unitIndex] + cluster.poWindows, + 0); + } + else + { + logs.error() << "Cluster: " << cluster.getFullName() + << " does not have unit: " << unitIndex; + return 0; + } +} + +// auxillary functions - for parameter calculations +std::array OptimizedThermalGenerator::calculateDailySums( + const std::array& hourlyValues) +{ + std::array dailyValues; + auto hours_iter = hourlyValues.begin(); + + for (double& day_sum : dailyValues) + { + day_sum = std::accumulate(hours_iter, hours_iter + 24, 0.0); + hours_iter += 24; + } + + return dailyValues; +} + +std::array OptimizedThermalGenerator::calculateAverageTs( + const Matrix& tsValue, + const Matrix& tsNumbers) +{ + // define array + std::array averageTs = {}; + // calculate sum + for (std::size_t year = 0; year < tsNumbers.height; ++year) + { + for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) + { + averageTs[row] += tsValue[tsNumbers[0][year]][row]; + } + } + // calculate mean + for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) + { + averageTs[row] = averageTs[row] / tsNumbers.height; + } + // return + return averageTs; +} + +bool OptimizedThermalGenerator::checkClusterExist(const Data::ThermalCluster& cluster) +{ + if (!cluster.prepro) + { + logs.error() << "Cluster: " << cluster.getFullName() + << ": The timeseries will not be regenerated. All data " + "related to the ts-generator for " + << "'thermal' have been released."; + return false; + } + + if (0 == cluster.unitCount || 0 == cluster.nominalCapacity) + { + return false; + } + return true; +} + +int OptimizedThermalGenerator::dayOfTheYear(int optimizationDay) +{ + return optimizationDay % DAYS_PER_YEAR; +} + +// calculate Average time-series functions +std::array OptimizedThermalGenerator::calculateAverageLoadTs( + const Data::Area& area) +{ + // we assume ready-make TS - (pre-check exist for this!) + const auto tsValues = area.load.series.timeSeries; + const auto tsNumbers = area.load.series.timeseriesNumbers; + return calculateAverageTs(tsValues, tsNumbers); +} + +std::array OptimizedThermalGenerator::calculateAverageRorTs( + const Data::Area& area) +{ + const auto tsValues = area.hydro.series->ror.timeSeries; + auto tsNumbers = area.hydro.series->ror.timeseriesNumbers; + return calculateAverageTs(tsValues, tsNumbers); +} + +std::array OptimizedThermalGenerator::calculateAverageRenewableTsAggregated( + const Data::Area& area) +{ + std::array averageTsSolar + = calculateAverageTs(area.solar.series.timeSeries, area.solar.series.timeseriesNumbers); + std::array averageTsWind + = calculateAverageTs(area.wind.series.timeSeries, area.wind.series.timeseriesNumbers); + + std::array averageTsRenewable = {}; + for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) + { + averageTsRenewable[row] = (averageTsSolar[row] + averageTsWind[row]); + } + return averageTsRenewable; +} + +std::array OptimizedThermalGenerator::calculateAverageRenewableTsClusters( + const Data::Area& area) +{ + std::array averageTsRenewable = {}; + for (const auto& entryCluster : area.renewable.clusters) + { + auto& cluster = *entryCluster; + // this is not even necessary - because area.renewable.clusters returns list of only + // ENABLED clusters but let's keep it for now + if (!cluster.enabled) + continue; + auto tmpArrayPerCluster + = calculateAverageTs(cluster.series.timeSeries, cluster.series.timeseriesNumbers); + for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) + { + if (cluster.tsMode == Data::RenewableCluster::productionFactor) + averageTsRenewable[row] + += tmpArrayPerCluster[row] * cluster.unitCount * cluster.nominalCapacity; + else + averageTsRenewable[row] += tmpArrayPerCluster[row]; + } + } + return averageTsRenewable; +} + +std::array OptimizedThermalGenerator::calculateAverageRenewableTs( + const Data::Area& area) +{ + if (study.parameters.renewableGeneration.isAggregated()) + { + return calculateAverageRenewableTsAggregated(area); + } + else // clusters it is + { + return calculateAverageRenewableTsClusters(area); + } +} + +} // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp index 256f38a50c..fc47969b56 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp @@ -107,457 +107,4 @@ void OptimizedThermalGenerator::createOptimizationProblemPerCluster(const Data:: } } -// calculate parameters methods - per maintenance group -void OptimizedThermalGenerator::setMaintenanceGroupParameters() -{ - // timeHorizon, timeStep ENS and Spillage are defined per one MaintenanceGroup - // Residual Load (or reference value) array is defined per one MaintenanceGroup - calculateResidualLoad(); - residualLoadDailyValues_ = calculateDailySums(maintenanceGroup_.getUsedResidualLoadTS()); - std::tie(ensCost_, spillCost_) = calculateMaintenanceGroupENSandSpillageCost(); - std::tie(timeStep_, timeHorizon_) = calculateTimeHorizonAndStep(); - setClusterDailyValues(); -} - -bool OptimizedThermalGenerator::checkMaintenanceGroupParameters() -{ - if (timeStep_ == 0) - { - logs.info() << "Maintenance group: " << maintenanceGroup_.name() - << ": The timeseries generation will be skiped: timeStep = 0. It is possible " - "that the maintenance group has no clusters designated for maintenance " - "planning, or at least one cluster has interPoPeriod = 0"; - return false; - } - if (timeHorizon_ == 0) - { - logs.info() - << "Maintenance group: " << maintenanceGroup_.name() - << ": The timeseries generation will be skiped: timeHorizon = 0. It is possible " - "that the maintenance group has no clusters designated for maintenance " - "planning, or all clusters have interPoPeriod = 0"; - return false; - } - // add some more check here if necessary! - return true; -} - -std::pair OptimizedThermalGenerator::calculateTimeHorizonAndStep() -{ - std::vector averageDurationBetweenMaintenances = {}; - for (const auto& entryWeightMap : maintenanceGroup_) - { - const auto& area = *(entryWeightMap.first); - for (auto it = area.thermal.list.mapping.begin(); it != area.thermal.list.mapping.end(); - ++it) - { - const auto& cluster = *(it->second); - if (cluster.doWeGenerateTS(globalThermalTSgeneration_) && cluster.optimizeMaintenance) - { - averageDurationBetweenMaintenances.push_back(cluster.interPoPeriod); - } - } - } - - // Using std::minmax_element to find min and max - auto [minIter, maxIter] = std::minmax_element(averageDurationBetweenMaintenances.begin(), - averageDurationBetweenMaintenances.end()); - - // Check if the vector is not empty - if (minIter != averageDurationBetweenMaintenances.end() - && maxIter != averageDurationBetweenMaintenances.end()) - { - return std::make_pair(*minIter, 2 * (*maxIter)); - } - - return std::make_pair(0, 0); -} - -std::pair OptimizedThermalGenerator::calculateMaintenanceGroupENSandSpillageCost() -{ - std::vector ensVector = {}; - std::vector spillageVector = {}; - for (const auto& entryWeightMap : maintenanceGroup_) - { - const auto& area = *(entryWeightMap.first); - ensVector.push_back(area.thermal.unsuppliedEnergyCost); - spillageVector.push_back(area.thermal.spilledEnergyCost); - } - - // Using std::minmax_element to find min and max - auto ens = std::min_element(ensVector.begin(), ensVector.end()); - auto spill = std::min_element(spillageVector.begin(), spillageVector.end()); - - // Check if the vector is not empty - if (ens != ensVector.end() && spill != spillageVector.end()) - { - return std::make_pair(*ens, *spill); - } - - return std::make_pair(0, 0); -} - -void OptimizedThermalGenerator::calculateResidualLoad() -{ - // create reference value arrays - std::array refValueLoad = {}; - std::array refValueRor = {}; - std::array refValueRenewable = {}; - std::array refValue = {}; - - // for phase II - if (maintenanceGroup_.type() == Data::MaintenanceGroup::typeTimeserie) - { - // read user defined ts - userProvidedResidualLoadTS_ with getter - phase-II - return; - } - - // loop through the elements of weightMap weights_ - for (const auto& entryWeightMap : maintenanceGroup_) - { - const auto& area = *(entryWeightMap.first); - const auto weights = (entryWeightMap.second); - - auto tmpLoad = calculateAverageLoadTs(area); - auto tmpRor = calculateAverageRorTs(area); - auto tmpRenewable = calculateAverageRenewableTs(area); - - for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) - { - refValueLoad[row] += tmpLoad[row] * weights.load; - refValueRor[row] += tmpRor[row] * weights.ror; - refValueRenewable[row] += tmpRenewable[row] * weights.renewable; - } - } - // calculate reference value - for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) - refValue[row] = refValueLoad[row] - refValueRor[row] - refValueRenewable[row]; - // set ResidualLoadTS - maintenanceGroup_.setUsedResidualLoadTS(refValue); -} - -void OptimizedThermalGenerator::setClusterDailyValues() -{ - for (const auto& entryWeightMap : maintenanceGroup_) - { - const auto& area = *(entryWeightMap.first); - auto& areaVariables = dailyClusterData.areaMap; - areaVariables[&area] = DailyClusterDataPerArea(); - // loop per thermal clusters inside the area - fill in the structure - for (auto it = area.thermal.list.mapping.begin(); it != area.thermal.list.mapping.end(); - ++it) - { - const auto& cluster = *(it->second); - - // we do not check if cluster.optimizeMaintenance = true here - // we add all the clusters Power inside maintenance group - if (!checkClusterExist(cluster)) - continue; - - auto& clusterVariables = areaVariables[&area].clusterMap; - clusterVariables[&cluster] = DailyClusterDataPerCluster(); - clusterVariables[&cluster].maxPower = calculateMaxUnitOutput(cluster); - clusterVariables[&cluster].unitCost = calculateAvrUnitDailyCost(cluster); - } - } - return; -} - -// calculate parameters methods - per cluster -uint OptimizedThermalGenerator::calculateNumberOfMaintenances(const Data::ThermalCluster& cluster, - uint timeHorizon) -{ - // timeHorizon cannot be 0. The whole maintenance group would be skipped if this happened - // on the other hand interPoPeriod can be 0. So we say at least 2 maintenance if this happens - if (cluster.interPoPeriod == 0) - { - logs.warning() << "Cluster: " << cluster.getFullName() - << "has interPoPeriod = 0. Number of maintenances for all units inside this " - "cluster will be set to 2"; - return minNumberOfMaintenances; - } - - return timeHorizon / cluster.interPoPeriod; // floor -} - -uint OptimizedThermalGenerator::calculateAverageMaintenanceDuration(Data::ThermalCluster& cluster) -{ - double sum = 0.0; - for (std::size_t row = 0; row < DAYS_PER_YEAR; ++row) - { - sum += cluster.prepro->data[Data::PreproThermal::poDuration][row]; - } - - return sum / static_cast(DAYS_PER_YEAR); -} - -std::array OptimizedThermalGenerator::calculateMaxUnitOutput( - const Data::ThermalCluster& cluster) -{ - std::array maxOutputDailyValues = {}; - std::array maxOutputHourlyValues = {}; - - // transfer to array - for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) - { - maxOutputHourlyValues[row] - = cluster.modulation[Data::ThermalModulation::thermalModulationCapacity][row]; - } - - maxOutputDailyValues = calculateDailySums(maxOutputHourlyValues); - // multiply by per unit power (nominal capacity) - for (double& num : maxOutputDailyValues) - { - num *= cluster.nominalCapacity; - } - return maxOutputDailyValues; -} - -std::array OptimizedThermalGenerator::calculateAvrUnitDailyCost( - const Data::ThermalCluster& cluster) -{ - std::array avrCostDailyValues = {}; - std::array costHourlyValues = {}; - - // transfer to array - for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) - { - costHourlyValues[row] - = cluster.modulation[Data::ThermalModulation::thermalModulationMarketBid][row]; - } - - avrCostDailyValues = calculateDailySums(costHourlyValues); - // multiply by per unit/cluster market bid cost + average this on 24 hours - for (double& num : avrCostDailyValues) - { - num *= cluster.marketBidCost / 24.0; - } - return avrCostDailyValues; -} - -double OptimizedThermalGenerator::getUnitPowerCost(const Data::ThermalCluster& cluster, - int optimizationDay) -{ - /* - ** Unit cost can be directly set, - ** Or calculated using Fuel Cost, Co2 cost, Fuel Eff and V&O Cost. - - ** In second case we also need information which year it is (to choose proper TS number, and - also what hour it is) - ** we need price per day (so averaging the hourly values) - ** this is NOT calculated prior to the simulation - so if we only want to run ts-gen, we cannot - get this info just yet - ** using: - ** getMarginalCost(uint serieIndex, uint hourInTheYear) or - ** getMarketBidCost(uint hourInTheYear, uint year) - ** TODO CR27: maybe for phase-II - ** for now just disable this option but take into account the thermalModulationCost!! - */ - - if (cluster.costgeneration == Data::useCostTimeseries) - { - logs.warning() - << "Cluster: " << cluster.getFullName() - << " has Cost generation set to: Use cost timeseries. Option not suported yet. " - "Cost set to zero."; - return 0.; - } - - int realDay = dayOfTheYear(optimizationDay); - auto unitCost - = dailyClusterData.areaMap[cluster.parentArea].clusterMap[&cluster].unitCost[realDay]; - return unitCost; -} - -double OptimizedThermalGenerator::getUnitPowerOutput(const Data::ThermalCluster& cluster, - int optimizationDay) -{ - int realDay = dayOfTheYear(optimizationDay); - auto unitOutput - = dailyClusterData.areaMap[cluster.parentArea].clusterMap[&cluster].maxPower[realDay]; - return unitOutput; -} - -// calculate parameters methods - per cluster-Unit -int OptimizedThermalGenerator::calculateUnitEarliestStartOfFirstMaintenance( - Data::ThermalCluster& cluster, - uint unitIndex) -{ - // earliest start of the first maintenance of unit u (beginning of the window, can be negative): - // let it return negative value - if it returns negative value we wont implement constraint: - // s[tauLower-1][u][1] = 0 - // TODO CR27: if the approach above breaks the solver - // we force the start of the first maintenance to be after day=0 - // s[fixed = 0][u][1] = 0 - if (unitIndex < cluster.daysSinceLastMaintenance.size()) - { - return (cluster.interPoPeriod - cluster.daysSinceLastMaintenance[unitIndex] - - cluster.poWindows); - } - else - { - logs.error() << "Cluster: " << cluster.getFullName() - << " does not have unit: " << unitIndex; - return 0; - } -} - -int OptimizedThermalGenerator::calculateUnitLatestStartOfFirstMaintenance( - Data::ThermalCluster& cluster, - uint unitIndex) -{ - // latest start of the first maintenance of unit u (end of the window, must be positive): - if (unitIndex < cluster.daysSinceLastMaintenance.size()) - { - // this cannot be negative: - // cluster.interPoPeriod - cluster.daysSinceLastMaintenance[unitIndex] - is always positive - // or zero - // cluster.poWindows is positive or zero - // so std::max is not necessary but I will keep it for now - return std::max( - cluster.interPoPeriod - cluster.daysSinceLastMaintenance[unitIndex] + cluster.poWindows, - 0); - } - else - { - logs.error() << "Cluster: " << cluster.getFullName() - << " does not have unit: " << unitIndex; - return 0; - } -} - -// auxillary functions -std::array OptimizedThermalGenerator::calculateDailySums( - const std::array& hourlyValues) -{ - std::array dailyValues; - auto hours_iter = hourlyValues.begin(); - - for (double& day_sum : dailyValues) - { - day_sum = std::accumulate(hours_iter, hours_iter + 24, 0.0); - hours_iter += 24; - } - - return dailyValues; -} - -std::array OptimizedThermalGenerator::calculateAverageTs( - const Matrix& tsValue, - const Matrix& tsNumbers) -{ - // define array - std::array averageTs = {}; - // calculate sum - for (std::size_t year = 0; year < tsNumbers.height; ++year) - { - for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) - { - averageTs[row] += tsValue[tsNumbers[0][year]][row]; - } - } - // calculate mean - for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) - { - averageTs[row] = averageTs[row] / tsNumbers.height; - } - // return - return averageTs; -} - -bool OptimizedThermalGenerator::checkClusterExist(const Data::ThermalCluster& cluster) -{ - if (!cluster.prepro) - { - logs.error() << "Cluster: " << cluster.getFullName() - << ": The timeseries will not be regenerated. All data " - "related to the ts-generator for " - << "'thermal' have been released."; - return false; - } - - if (0 == cluster.unitCount || 0 == cluster.nominalCapacity) - { - return false; - } - return true; -} - -int OptimizedThermalGenerator::dayOfTheYear(int optimizationDay) -{ - return optimizationDay % DAYS_PER_YEAR; -} - -// calculate Average time-series functions -std::array OptimizedThermalGenerator::calculateAverageLoadTs( - const Data::Area& area) -{ - // we assume ready-make TS - (pre-check exist for this!) - const auto tsValues = area.load.series.timeSeries; - const auto tsNumbers = area.load.series.timeseriesNumbers; - return calculateAverageTs(tsValues, tsNumbers); -} - -std::array OptimizedThermalGenerator::calculateAverageRorTs( - const Data::Area& area) -{ - const auto tsValues = area.hydro.series->ror.timeSeries; - auto tsNumbers = area.hydro.series->ror.timeseriesNumbers; - return calculateAverageTs(tsValues, tsNumbers); -} - -std::array OptimizedThermalGenerator::calculateAverageRenewableTsAggregated( - const Data::Area& area) -{ - std::array averageTsSolar - = calculateAverageTs(area.solar.series.timeSeries, area.solar.series.timeseriesNumbers); - std::array averageTsWind - = calculateAverageTs(area.wind.series.timeSeries, area.wind.series.timeseriesNumbers); - - std::array averageTsRenewable = {}; - for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) - { - averageTsRenewable[row] = (averageTsSolar[row] + averageTsWind[row]); - } - return averageTsRenewable; -} - -std::array OptimizedThermalGenerator::calculateAverageRenewableTsClusters( - const Data::Area& area) -{ - std::array averageTsRenewable = {}; - for (const auto& entryCluster : area.renewable.clusters) - { - auto& cluster = *entryCluster; - // this is not even necessary - because area.renewable.clusters returns list of only - // ENABLED clusters but let's keep it for now - if (!cluster.enabled) - continue; - auto tmpArrayPerCluster - = calculateAverageTs(cluster.series.timeSeries, cluster.series.timeseriesNumbers); - for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) - { - if (cluster.tsMode == Data::RenewableCluster::productionFactor) - averageTsRenewable[row] - += tmpArrayPerCluster[row] * cluster.unitCount * cluster.nominalCapacity; - else - averageTsRenewable[row] += tmpArrayPerCluster[row]; - } - } - return averageTsRenewable; -} - -std::array OptimizedThermalGenerator::calculateAverageRenewableTs( - const Data::Area& area) -{ - if (study.parameters.renewableGeneration.isAggregated()) - { - return calculateAverageRenewableTsAggregated(area); - } - else // clusters it is - { - return calculateAverageRenewableTsClusters(area); - } -} - } // namespace Antares::Solver::TSGenerator From f8a386a7725bbf73dd5eeea66215c74bcecc87a3 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 22 Nov 2023 12:09:38 +0100 Subject: [PATCH 131/315] refactor createVariables --- .../CreateVariables.cpp | 276 +++++++++++------- .../OptimizedGenerator.h | 33 ++- 2 files changed, 196 insertions(+), 113 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp b/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp index 44326010b5..0784a0fd6f 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp @@ -10,8 +10,8 @@ void OptimizedThermalGenerator::buildProblemVariables(const OptProblemSettings& { // this is now just dummy optimization problem countVariables(); - - allocateOptimizationProblemVariablesStruct(); + + allocateVarStruct(); buildEnsAndSpillageVariables(optSett); buildUnitPowerOutputVariables(optSett); buildStartEndMntVariables(optSett); @@ -76,43 +76,55 @@ void OptimizedThermalGenerator::countVariables() } // populate OptimizationProblemVariables struct -void OptimizedThermalGenerator::allocateOptimizationProblemVariablesStruct() +void OptimizedThermalGenerator::allocateVarStruct() { - // loop per day - fill in structure + // loop per day for (int day = 0; day < timeHorizon_; ++day) { // fill the variable structure var.day.push_back(OptimizationProblemVariablesPerDay()); + allocateVarStructPerGroup(day); + } +} - // loop per area inside maintenance group - fill in the structure - for (const auto& entryWeightMap : maintenanceGroup_) - { - const auto& area = *(entryWeightMap.first); - auto& areaVariables = var.day[day].areaMap; - areaVariables[&area] = OptimizationProblemVariablesPerArea(); +void OptimizedThermalGenerator::allocateVarStructPerGroup(int day) +{ + // loop per areas inside maintenance group + for (const auto& entryWeightMap : maintenanceGroup_) + { + const auto& area = *(entryWeightMap.first); + auto& areaVariables = var.day[day].areaMap; + areaVariables[&area] = OptimizationProblemVariablesPerArea(); + allocateVarStructPerArea(day, area); + } +} - // loop per thermal clusters inside the area - fill in the structure - for (auto it = area.thermal.list.mapping.begin(); it != area.thermal.list.mapping.end(); - ++it) - { - const auto& cluster = *(it->second); +void OptimizedThermalGenerator::allocateVarStructPerArea(int day, const Data::Area& area) +{ + // loop per thermal clusters inside the area + for (auto it = area.thermal.list.mapping.begin(); it != area.thermal.list.mapping.end(); ++it) + { + const auto& cluster = *(it->second); - // we do not check if cluster.optimizeMaintenance = true here - // we add all the clusters Power inside maintenance group - if (!checkClusterExist(cluster)) - continue; + // we do not check if cluster.optimizeMaintenance = true here + // we add all the clusters Power inside maintenance group + if (!checkClusterExist(cluster)) + continue; - auto& clusterVariables = areaVariables[&area].clusterMap; - clusterVariables[&cluster] = OptimizationProblemVariablesPerCluster(); + auto& clusterVariables = var.day[day].areaMap[&area].clusterMap; + clusterVariables[&cluster] = OptimizationProblemVariablesPerCluster(); + allocateVarStructPerCluster(day, cluster); + } +} - // loop per unit inside the cluster - fill in the structure - for (int unit = 0; unit < cluster.unitCount; ++unit) - { - clusterVariables[&cluster].unitMap.push_back( - OptimizationProblemVariablesPerUnit()); - } - } - } +void OptimizedThermalGenerator::allocateVarStructPerCluster(int day, + const Data::ThermalCluster& cluster) +{ + // loop per unit inside the cluster + for (int unit = 0; unit < cluster.unitCount; ++unit) + { + var.day[day].areaMap[cluster.parentArea].clusterMap[&cluster].unitMap.push_back( + OptimizationProblemVariablesPerUnit()); } } @@ -142,102 +154,144 @@ void OptimizedThermalGenerator::buildUnitPowerOutputVariables(const OptProblemSe // loop per day for (int day = 0; day < timeHorizon_; ++day) { - // loop per area inside maintenance group - for (const auto& entryWeightMap : maintenanceGroup_) - { - const auto& area = *(entryWeightMap.first); - auto& areaVariables = var.day[day].areaMap; - - // loop per thermal clusters inside the area - for (auto it = area.thermal.list.mapping.begin(); it != area.thermal.list.mapping.end(); - ++it) - { - const auto& cluster = *(it->second); - - // we do not check if cluster.optimizeMaintenance = true here - // we add all the clusters Power inside maintenance group - if (!checkClusterExist(cluster)) - continue; - - auto& clusterVariables = areaVariables[&area].clusterMap; - - // loop per unit inside the cluster - for (int unit = 0; unit < cluster.unitCount; ++unit) - { - // add P[t][u] variables - clusterVariables[&cluster].unitMap[unit].P - = solver.MakeNumVar(0.0, - infinity, - "P_[" + std::to_string(day + optSett.firstDay) + "][" - + cluster.getFullName().to() + "." - + std::to_string(unit) + "]"); - } - } - } + buildUnitPowerOutputVariablesPerGroup(optSett, day); } - return; } +void OptimizedThermalGenerator::buildUnitPowerOutputVariablesPerGroup( + const OptProblemSettings& optSett, + int day) +{ + // loop per areas inside maintenance group + for (const auto& entryWeightMap : maintenanceGroup_) + { + const auto& area = *(entryWeightMap.first); + buildUnitPowerOutputVariablesPerArea(optSett, day, area); + } +} + +void OptimizedThermalGenerator::buildUnitPowerOutputVariablesPerArea( + const OptProblemSettings& optSett, + int day, + const Data::Area& area) +{ + // loop per thermal clusters inside the area + for (auto it = area.thermal.list.mapping.begin(); it != area.thermal.list.mapping.end(); ++it) + { + const auto& cluster = *(it->second); + + // we do not check if cluster.optimizeMaintenance = true here + // we add all the clusters Power inside maintenance group + if (!checkClusterExist(cluster)) + continue; + + buildUnitPowerOutputVariablesPerCluster(optSett, day, cluster); + } +} + +void OptimizedThermalGenerator::buildUnitPowerOutputVariablesPerCluster( + const OptProblemSettings& optSett, + int day, + const Data::ThermalCluster& cluster) +{ + // loop per units inside the cluster + for (int unit = 0; unit < cluster.unitCount; ++unit) + { + // add P[t][u] variables + var.day[day].areaMap[cluster.parentArea].clusterMap[&cluster].unitMap[unit].P + = solver.MakeNumVar(0.0, + infinity, + "P_[" + std::to_string(day + optSett.firstDay) + "][" + + cluster.getFullName().to() + "." + + std::to_string(unit) + "]"); + } +} + // create VARIABLES per day, per cluster-unit and per maintenance - s[t][u][m] & e[t][u][m] void OptimizedThermalGenerator::buildStartEndMntVariables(const OptProblemSettings& optSett) { // loop per day for (int day = 0; day < timeHorizon_; ++day) { - // loop per area inside maintenance group - for (const auto& entryWeightMap : maintenanceGroup_) - { - const auto& area = *(entryWeightMap.first); - auto& areaVariables = var.day[day].areaMap; - - // loop per thermal clusters inside the area - for (auto it = area.thermal.list.mapping.begin(); it != area.thermal.list.mapping.end(); - ++it) - { - const auto& cluster = *(it->second); - - // check if cluster exist, do we generate + optimizeMaintenance - // create start end variables only for these clusters - bool createStartEndVar = checkClusterExist(cluster) - && cluster.doWeGenerateTS(globalThermalTSgeneration_) - && cluster.optimizeMaintenance; - if (!createStartEndVar) - continue; - - auto& clusterVariables = areaVariables[&area].clusterMap; - int totalMntNumber = calculateNumberOfMaintenances(cluster, timeHorizon_); - - // loop per unit inside the cluster - for (int unit = 0; unit < cluster.unitCount; ++unit) - { - auto& unitVariables = clusterVariables[&cluster].unitMap; - // loop per maintenances per unit - for (int mnt = 0; mnt < totalMntNumber; ++mnt) - { - // add start[t][u][m] variables - unitVariables[unit].start.push_back(solver.MakeIntVar( - 0.0, - 1.0, - "S_[" + std::to_string(day + optSett.firstDay) + "][" - + cluster.getFullName().to() + "." + std::to_string(unit) - + "][" + std::to_string(mnt) + "]")); - - // add end[t][u][m] variables - unitVariables[unit].end.push_back(solver.MakeIntVar( - 0.0, - 1.0, - "E_[" + std::to_string(day + optSett.firstDay) + "][" - + cluster.getFullName().to() + "." + std::to_string(unit) - + "][" + std::to_string(mnt) + "]")); - } - } - } - } + buildStartEndMntVariablesPerGroup(optSett, day); } return; } +void OptimizedThermalGenerator::buildStartEndMntVariablesPerGroup(const OptProblemSettings& optSett, + int day) +{ + // loop per areas inside maintenance group + for (const auto& entryWeightMap : maintenanceGroup_) + { + const auto& area = *(entryWeightMap.first); + buildStartEndMntVariablesPerArea(optSett, day, area); + } +} + +void OptimizedThermalGenerator::buildStartEndMntVariablesPerArea(const OptProblemSettings& optSett, + int day, + const Data ::Area& area) +{ + // loop per thermal clusters inside the area + for (auto it = area.thermal.list.mapping.begin(); it != area.thermal.list.mapping.end(); ++it) + { + const auto& cluster = *(it->second); + + // check if cluster exist, do we generate + optimizeMaintenance + // create start end variables only for these clusters + bool createStartEndVar = checkClusterExist(cluster) + && cluster.doWeGenerateTS(globalThermalTSgeneration_) + && cluster.optimizeMaintenance; + if (!createStartEndVar) + continue; + + buildStartEndMntVariablesPerCluster(optSett, day, cluster); + } +} + +void OptimizedThermalGenerator::buildStartEndMntVariablesPerCluster( + const OptProblemSettings& optSett, + int day, + const Data ::ThermalCluster& cluster) +{ + int totalMntNumber = calculateNumberOfMaintenances(cluster, timeHorizon_); + // loop per units inside the cluster + for (int unit = 0; unit < cluster.unitCount; ++unit) + { + buildStartEndMntVariablesPerUnit(optSett, day, cluster, unit, totalMntNumber); + } +} + +void OptimizedThermalGenerator::buildStartEndMntVariablesPerUnit( + const OptProblemSettings& optSett, + int day, + const Data ::ThermalCluster& cluster, + int unit, + int totalMntNumber) +{ + // loop per maintenances per unit + for (int mnt = 0; mnt < totalMntNumber; ++mnt) + { + // add start[t][u][m] variables + var.day[day].areaMap[cluster.parentArea].clusterMap[&cluster].unitMap[unit].start.push_back( + solver.MakeIntVar(0.0, + 1.0, + "S_[" + std::to_string(day + optSett.firstDay) + "][" + + cluster.getFullName().to() + "." + std::to_string(unit) + + "][" + std::to_string(mnt) + "]")); + + // add end[t][u][m] variables + var.day[day].areaMap[cluster.parentArea].clusterMap[&cluster].unitMap[unit].end.push_back( + solver.MakeIntVar(0.0, + 1.0, + "E_[" + std::to_string(day + optSett.firstDay) + "][" + + cluster.getFullName().to() + "." + std::to_string(unit) + + "][" + std::to_string(mnt) + "]")); + } +} + void OptimizedThermalGenerator::printAllVariables() { for (MPVariable* const variable : solver.variables()) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 2e54f62c9a..86e4aa64e4 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -22,12 +22,41 @@ class OptimizedThermalGenerator : public GeneratorTempData { private: // optimization problem construction methods - void buildProblemVariables(const OptProblemSettings& optSett); + void countVariables(); - void allocateOptimizationProblemVariablesStruct(); + + void allocateVarStruct(); + void allocateVarStructPerGroup(int day); + void allocateVarStructPerArea(int day, const Data::Area& area); + void allocateVarStructPerCluster(int day, const Data::ThermalCluster& cluster); + + void buildProblemVariables(const OptProblemSettings& optSett); + void buildEnsAndSpillageVariables(const OptProblemSettings& optSett); + void buildUnitPowerOutputVariables(const OptProblemSettings& optSett); + void buildUnitPowerOutputVariablesPerGroup(const OptProblemSettings& optSett, int day); + void buildUnitPowerOutputVariablesPerArea(const OptProblemSettings& optSett, + int day, + const Data::Area& area); + void buildUnitPowerOutputVariablesPerCluster(const OptProblemSettings& optSett, + int day, + const Data::ThermalCluster& cluster); + void buildStartEndMntVariables(const OptProblemSettings& optSett); + void buildStartEndMntVariablesPerGroup(const OptProblemSettings& optSett, int day); + void buildStartEndMntVariablesPerArea(const OptProblemSettings& optSett, + int day, + const Data ::Area& area); + void buildStartEndMntVariablesPerCluster(const OptProblemSettings& optSett, + int day, + const Data ::ThermalCluster& cluster); + void buildStartEndMntVariablesPerUnit(const OptProblemSettings& optSett, + int day, + const Data ::ThermalCluster& cluster, + int unit, + int totalMntNumber); + void printAllVariables(); // for debug purpose only! void setVariableBounds(); From 13e508a8b7b497cfe8186bd64231c2085246faac Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 22 Nov 2023 12:10:10 +0100 Subject: [PATCH 132/315] improve calculateNumberOfMaintenances --- .../optimized-thermal-generator/CalculateParameters.cpp | 6 +++--- .../optimized-thermal-generator/OptimizedGenerator.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp index cae770c73f..cf8701551b 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp @@ -164,8 +164,8 @@ void OptimizedThermalGenerator::setClusterDailyValues() } // calculate parameters methods - per cluster -uint OptimizedThermalGenerator::calculateNumberOfMaintenances(const Data::ThermalCluster& cluster, - uint timeHorizon) +int OptimizedThermalGenerator::calculateNumberOfMaintenances(const Data::ThermalCluster& cluster, + int timeHorizon) { // timeHorizon cannot be 0. The whole maintenance group would be skipped if this happened // on the other hand interPoPeriod can be 0. So we say at least 2 maintenance if this happens @@ -177,7 +177,7 @@ uint OptimizedThermalGenerator::calculateNumberOfMaintenances(const Data::Therma return minNumberOfMaintenances; } - return timeHorizon / cluster.interPoPeriod; // floor + return std::max(timeHorizon / cluster.interPoPeriod, minNumberOfMaintenances); // floor } uint OptimizedThermalGenerator::calculateAverageMaintenanceDuration(Data::ThermalCluster& cluster) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 86e4aa64e4..20305dd8a2 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -11,7 +11,7 @@ #include // static const std::string mntPlSolverName = "cbc"; -static const uint minNumberOfMaintenances = 2; +static const int minNumberOfMaintenances = 2; using namespace operations_research; @@ -113,7 +113,7 @@ class OptimizedThermalGenerator : public GeneratorTempData void setClusterDailyValues(); // calculate parameters methods - per cluster - uint calculateNumberOfMaintenances(const Data::ThermalCluster& cluster, uint timeHorizon); + int calculateNumberOfMaintenances(const Data::ThermalCluster& cluster, int timeHorizon); uint calculateAverageMaintenanceDuration(Data::ThermalCluster& cluster); static std::array calculateMaxUnitOutput(const Data::ThermalCluster& cluster); static std::array calculateAvrUnitDailyCost(const Data::ThermalCluster& cluster); From 2e482f7e20c39649c785cbc11431e3e20a81f64d Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 22 Nov 2023 13:26:15 +0100 Subject: [PATCH 133/315] refactor - override method names - simpler --- .../CreateVariables.cpp | 74 ++++++++--------- .../OptimizedGenerator.h | 79 +++++++++---------- .../SetProblemCost.cpp | 44 +++++------ 3 files changed, 95 insertions(+), 102 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp b/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp index 0784a0fd6f..bbb499d30f 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp @@ -83,11 +83,11 @@ void OptimizedThermalGenerator::allocateVarStruct() { // fill the variable structure var.day.push_back(OptimizationProblemVariablesPerDay()); - allocateVarStructPerGroup(day); + allocateVarStruct(day); } } -void OptimizedThermalGenerator::allocateVarStructPerGroup(int day) +void OptimizedThermalGenerator::allocateVarStruct(int day) { // loop per areas inside maintenance group for (const auto& entryWeightMap : maintenanceGroup_) @@ -95,11 +95,11 @@ void OptimizedThermalGenerator::allocateVarStructPerGroup(int day) const auto& area = *(entryWeightMap.first); auto& areaVariables = var.day[day].areaMap; areaVariables[&area] = OptimizationProblemVariablesPerArea(); - allocateVarStructPerArea(day, area); + allocateVarStruct(day, area); } } -void OptimizedThermalGenerator::allocateVarStructPerArea(int day, const Data::Area& area) +void OptimizedThermalGenerator::allocateVarStruct(int day, const Data::Area& area) { // loop per thermal clusters inside the area for (auto it = area.thermal.list.mapping.begin(); it != area.thermal.list.mapping.end(); ++it) @@ -113,12 +113,11 @@ void OptimizedThermalGenerator::allocateVarStructPerArea(int day, const Data::Ar auto& clusterVariables = var.day[day].areaMap[&area].clusterMap; clusterVariables[&cluster] = OptimizationProblemVariablesPerCluster(); - allocateVarStructPerCluster(day, cluster); + allocateVarStruct(day, cluster); } } -void OptimizedThermalGenerator::allocateVarStructPerCluster(int day, - const Data::ThermalCluster& cluster) +void OptimizedThermalGenerator::allocateVarStruct(int day, const Data::ThermalCluster& cluster) { // loop per unit inside the cluster for (int unit = 0; unit < cluster.unitCount; ++unit) @@ -154,27 +153,25 @@ void OptimizedThermalGenerator::buildUnitPowerOutputVariables(const OptProblemSe // loop per day for (int day = 0; day < timeHorizon_; ++day) { - buildUnitPowerOutputVariablesPerGroup(optSett, day); + buildUnitPowerOutputVariables(optSett, day); } return; } -void OptimizedThermalGenerator::buildUnitPowerOutputVariablesPerGroup( - const OptProblemSettings& optSett, - int day) +void OptimizedThermalGenerator::buildUnitPowerOutputVariables(const OptProblemSettings& optSett, + int day) { // loop per areas inside maintenance group for (const auto& entryWeightMap : maintenanceGroup_) { const auto& area = *(entryWeightMap.first); - buildUnitPowerOutputVariablesPerArea(optSett, day, area); + buildUnitPowerOutputVariables(optSett, day, area); } } -void OptimizedThermalGenerator::buildUnitPowerOutputVariablesPerArea( - const OptProblemSettings& optSett, - int day, - const Data::Area& area) +void OptimizedThermalGenerator::buildUnitPowerOutputVariables(const OptProblemSettings& optSett, + int day, + const Data::Area& area) { // loop per thermal clusters inside the area for (auto it = area.thermal.list.mapping.begin(); it != area.thermal.list.mapping.end(); ++it) @@ -186,14 +183,13 @@ void OptimizedThermalGenerator::buildUnitPowerOutputVariablesPerArea( if (!checkClusterExist(cluster)) continue; - buildUnitPowerOutputVariablesPerCluster(optSett, day, cluster); + buildUnitPowerOutputVariables(optSett, day, cluster); } } -void OptimizedThermalGenerator::buildUnitPowerOutputVariablesPerCluster( - const OptProblemSettings& optSett, - int day, - const Data::ThermalCluster& cluster) +void OptimizedThermalGenerator::buildUnitPowerOutputVariables(const OptProblemSettings& optSett, + int day, + const Data::ThermalCluster& cluster) { // loop per units inside the cluster for (int unit = 0; unit < cluster.unitCount; ++unit) @@ -214,25 +210,25 @@ void OptimizedThermalGenerator::buildStartEndMntVariables(const OptProblemSettin // loop per day for (int day = 0; day < timeHorizon_; ++day) { - buildStartEndMntVariablesPerGroup(optSett, day); + buildStartEndMntVariables(optSett, day); } return; } -void OptimizedThermalGenerator::buildStartEndMntVariablesPerGroup(const OptProblemSettings& optSett, - int day) +void OptimizedThermalGenerator::buildStartEndMntVariables(const OptProblemSettings& optSett, + int day) { // loop per areas inside maintenance group for (const auto& entryWeightMap : maintenanceGroup_) { const auto& area = *(entryWeightMap.first); - buildStartEndMntVariablesPerArea(optSett, day, area); + buildStartEndMntVariables(optSett, day, area); } } -void OptimizedThermalGenerator::buildStartEndMntVariablesPerArea(const OptProblemSettings& optSett, - int day, - const Data ::Area& area) +void OptimizedThermalGenerator::buildStartEndMntVariables(const OptProblemSettings& optSett, + int day, + const Data ::Area& area) { // loop per thermal clusters inside the area for (auto it = area.thermal.list.mapping.begin(); it != area.thermal.list.mapping.end(); ++it) @@ -247,29 +243,27 @@ void OptimizedThermalGenerator::buildStartEndMntVariablesPerArea(const OptProble if (!createStartEndVar) continue; - buildStartEndMntVariablesPerCluster(optSett, day, cluster); + buildStartEndMntVariables(optSett, day, cluster); } } -void OptimizedThermalGenerator::buildStartEndMntVariablesPerCluster( - const OptProblemSettings& optSett, - int day, - const Data ::ThermalCluster& cluster) +void OptimizedThermalGenerator::buildStartEndMntVariables(const OptProblemSettings& optSett, + int day, + const Data ::ThermalCluster& cluster) { int totalMntNumber = calculateNumberOfMaintenances(cluster, timeHorizon_); // loop per units inside the cluster for (int unit = 0; unit < cluster.unitCount; ++unit) { - buildStartEndMntVariablesPerUnit(optSett, day, cluster, unit, totalMntNumber); + buildStartEndMntVariables(optSett, day, cluster, unit, totalMntNumber); } } -void OptimizedThermalGenerator::buildStartEndMntVariablesPerUnit( - const OptProblemSettings& optSett, - int day, - const Data ::ThermalCluster& cluster, - int unit, - int totalMntNumber) +void OptimizedThermalGenerator::buildStartEndMntVariables(const OptProblemSettings& optSett, + int day, + const Data ::ThermalCluster& cluster, + int unit, + int totalMntNumber) { // loop per maintenances per unit for (int mnt = 0; mnt < totalMntNumber; ++mnt) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 20305dd8a2..c825272428 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -26,36 +26,36 @@ class OptimizedThermalGenerator : public GeneratorTempData void countVariables(); void allocateVarStruct(); - void allocateVarStructPerGroup(int day); - void allocateVarStructPerArea(int day, const Data::Area& area); - void allocateVarStructPerCluster(int day, const Data::ThermalCluster& cluster); + void allocateVarStruct(int day); + void allocateVarStruct(int day, const Data::Area& area); + void allocateVarStruct(int day, const Data::ThermalCluster& cluster); void buildProblemVariables(const OptProblemSettings& optSett); void buildEnsAndSpillageVariables(const OptProblemSettings& optSett); void buildUnitPowerOutputVariables(const OptProblemSettings& optSett); - void buildUnitPowerOutputVariablesPerGroup(const OptProblemSettings& optSett, int day); - void buildUnitPowerOutputVariablesPerArea(const OptProblemSettings& optSett, - int day, - const Data::Area& area); - void buildUnitPowerOutputVariablesPerCluster(const OptProblemSettings& optSett, - int day, - const Data::ThermalCluster& cluster); + void buildUnitPowerOutputVariables(const OptProblemSettings& optSett, int day); + void buildUnitPowerOutputVariables(const OptProblemSettings& optSett, + int day, + const Data::Area& area); + void buildUnitPowerOutputVariables(const OptProblemSettings& optSett, + int day, + const Data::ThermalCluster& cluster); void buildStartEndMntVariables(const OptProblemSettings& optSett); - void buildStartEndMntVariablesPerGroup(const OptProblemSettings& optSett, int day); - void buildStartEndMntVariablesPerArea(const OptProblemSettings& optSett, - int day, - const Data ::Area& area); - void buildStartEndMntVariablesPerCluster(const OptProblemSettings& optSett, - int day, - const Data ::ThermalCluster& cluster); - void buildStartEndMntVariablesPerUnit(const OptProblemSettings& optSett, - int day, - const Data ::ThermalCluster& cluster, - int unit, - int totalMntNumber); + void buildStartEndMntVariables(const OptProblemSettings& optSett, int day); + void buildStartEndMntVariables(const OptProblemSettings& optSett, + int day, + const Data ::Area& area); + void buildStartEndMntVariables(const OptProblemSettings& optSett, + int day, + const Data ::ThermalCluster& cluster); + void buildStartEndMntVariables(const OptProblemSettings& optSett, + int day, + const Data ::ThermalCluster& cluster, + int unit, + int totalMntNumber); void printAllVariables(); // for debug purpose only! @@ -75,24 +75,23 @@ class OptimizedThermalGenerator : public GeneratorTempData void setProblemEnsCost(MPObjective* objective); void setProblemSpillCost(MPObjective* objective); void setProblemPowerCost(const OptProblemSettings& optSett, MPObjective* objective); - void setProblemPowerCostPerGroup(const OptProblemSettings& optSett, - MPObjective* objective, - int day); - void setProblemPowerCostPerArea(const OptProblemSettings& optSett, - MPObjective* objective, - int day, - const Data::Area& area); - void setProblemPowerCostPerCluster(const OptProblemSettings& optSett, - MPObjective* objective, - int day, - const Data::Area& area, - const Data::ThermalCluster& cluster); - void setProblemPowerCostPerUnit(MPObjective* objective, - int day, - const Data::Area& area, - const Data::ThermalCluster& cluster, - int unitIndex, - double powerCost); + void setProblemPowerCost(const OptProblemSettings& optSett, MPObjective* objective, int day); + void setProblemPowerCost(const OptProblemSettings& optSett, + MPObjective* objective, + int day, + const Data::Area& area); + void setProblemPowerCost(const OptProblemSettings& optSett, + MPObjective* objective, + int day, + const Data::Area& area, + const Data::ThermalCluster& cluster); + void setProblemPowerCost(MPObjective* objective, + int day, + const Data::Area& area, + const Data::ThermalCluster& cluster, + int unitIndex, + double powerCost); + void printObjectiveFunction(MPObjective* objective); void solveProblem(); diff --git a/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp b/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp index b4d8ac281a..1479a04d46 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp @@ -49,28 +49,28 @@ void OptimizedThermalGenerator::setProblemPowerCost(const OptProblemSettings& op // loop per day for (int day = 0; day < timeHorizon_; ++day) { - setProblemPowerCostPerGroup(optSett, objective, day); + setProblemPowerCost(optSett, objective, day); } return; } -void OptimizedThermalGenerator::setProblemPowerCostPerGroup(const OptProblemSettings& optSett, - MPObjective* objective, - int day) +void OptimizedThermalGenerator::setProblemPowerCost(const OptProblemSettings& optSett, + MPObjective* objective, + int day) { // loop per area inside maintenance group for (const auto& entryWeightMap : maintenanceGroup_) { const auto& area = *(entryWeightMap.first); - setProblemPowerCostPerArea(optSett, objective, day, area); + setProblemPowerCost(optSett, objective, day, area); } return; } -void OptimizedThermalGenerator::setProblemPowerCostPerArea(const OptProblemSettings& optSett, - MPObjective* objective, - int day, - const Data::Area& area) +void OptimizedThermalGenerator::setProblemPowerCost(const OptProblemSettings& optSett, + MPObjective* objective, + int day, + const Data::Area& area) { // loop per thermal clusters inside the area for (auto it = area.thermal.list.mapping.begin(); it != area.thermal.list.mapping.end(); ++it) @@ -82,32 +82,32 @@ void OptimizedThermalGenerator::setProblemPowerCostPerArea(const OptProblemSetti if (!checkClusterExist(cluster)) continue; - setProblemPowerCostPerCluster(optSett, objective, day, area, cluster); + setProblemPowerCost(optSett, objective, day, area, cluster); } return; } -void OptimizedThermalGenerator::setProblemPowerCostPerCluster(const OptProblemSettings& optSett, - MPObjective* objective, - int day, - const Data::Area& area, - const Data::ThermalCluster& cluster) +void OptimizedThermalGenerator::setProblemPowerCost(const OptProblemSettings& optSett, + MPObjective* objective, + int day, + const Data::Area& area, + const Data::ThermalCluster& cluster) { double unitPowerCost = getUnitPowerCost(cluster, day + optSett.firstDay); // loop per unit inside the cluster for (int unit = 0; unit < cluster.unitCount; ++unit) { - setProblemPowerCostPerUnit(objective, day, area, cluster, unit, unitPowerCost); + setProblemPowerCost(objective, day, area, cluster, unit, unitPowerCost); } return; } -void OptimizedThermalGenerator::setProblemPowerCostPerUnit(MPObjective* objective, - int day, - const Data::Area& area, - const Data::ThermalCluster& cluster, - int unitIndex, - double cost) +void OptimizedThermalGenerator::setProblemPowerCost(MPObjective* objective, + int day, + const Data::Area& area, + const Data::ThermalCluster& cluster, + int unitIndex, + double cost) { objective->SetCoefficient(var.day[day].areaMap[&area].clusterMap[&cluster].unitMap[unitIndex].P, cost); From 93929ddc38a511b93e56b178bb3dfa710d7f3e66 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 22 Nov 2023 14:05:21 +0100 Subject: [PATCH 134/315] improve calculateUnitLatest/EarliestStartOfFirstMaintenance --- .../CalculateParameters.cpp | 21 +++++++++++++------ .../OptimizedGenerator.h | 8 +++++-- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp index cf8701551b..bf1c7fe964 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp @@ -280,15 +280,23 @@ double OptimizedThermalGenerator::getUnitPowerOutput(const Data::ThermalCluster& // calculate parameters methods - per cluster-Unit int OptimizedThermalGenerator::calculateUnitEarliestStartOfFirstMaintenance( - Data::ThermalCluster& cluster, + const Data::ThermalCluster& cluster, uint unitIndex) { // earliest start of the first maintenance of unit u (beginning of the window, can be negative): // let it return negative value - if it returns negative value we wont implement constraint: // s[tauLower-1][u][1] = 0 - // TODO CR27: if the approach above breaks the solver + + // TODO CR27: + // if the approach above breaks the solver // we force the start of the first maintenance to be after day=0 // s[fixed = 0][u][1] = 0 + + // TODO CR27: + // we need to store cluster.daysSinceLastMaintenance[unitIndex] + // somewhere locally - since we need to update the values after each timeStep_ + // and we do not want to change values inside "cluster" that will later be used for UI & txt + if (unitIndex < cluster.daysSinceLastMaintenance.size()) { return (cluster.interPoPeriod - cluster.daysSinceLastMaintenance[unitIndex] @@ -303,7 +311,7 @@ int OptimizedThermalGenerator::calculateUnitEarliestStartOfFirstMaintenance( } int OptimizedThermalGenerator::calculateUnitLatestStartOfFirstMaintenance( - Data::ThermalCluster& cluster, + const Data::ThermalCluster& cluster, uint unitIndex) { // latest start of the first maintenance of unit u (end of the window, must be positive): @@ -313,10 +321,11 @@ int OptimizedThermalGenerator::calculateUnitLatestStartOfFirstMaintenance( // cluster.interPoPeriod - cluster.daysSinceLastMaintenance[unitIndex] - is always positive // or zero // cluster.poWindows is positive or zero - // so std::max is not necessary but I will keep it for now - return std::max( + // however we will make sure it does not surpass timeHorizon_ - 1 value + + return std::min( cluster.interPoPeriod - cluster.daysSinceLastMaintenance[unitIndex] + cluster.poWindows, - 0); + timeHorizon_ - 1); } else { diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index c825272428..9d46a4f644 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -64,6 +64,8 @@ class OptimizedThermalGenerator : public GeneratorTempData void setUnitPowerOutputBounds(); void setStartEndMntBounds(); void setFirstMntStartBounds(); + void setFirstMntStartBounds(const Data::Area& area); + void setFirstMntStartBounds(const Data::ThermalCluster& cluster); void setAllMntMustStartBounds(); void buildProblemConstraints(); @@ -121,8 +123,10 @@ class OptimizedThermalGenerator : public GeneratorTempData double getUnitPowerOutput(const Data::ThermalCluster& cluster, int optimizationDay); // calculate parameters methods - per cluster-Unit - int calculateUnitEarliestStartOfFirstMaintenance(Data::ThermalCluster& cluster, uint unitIndex); - int calculateUnitLatestStartOfFirstMaintenance(Data::ThermalCluster& cluster, uint unitIndex); + int calculateUnitEarliestStartOfFirstMaintenance(const Data::ThermalCluster& cluster, + uint unitIndex); + int calculateUnitLatestStartOfFirstMaintenance(const Data::ThermalCluster& cluster, + uint unitIndex); // auxillary functions static std::array calculateDailySums( From 9ca71b333e579712795cd7490e347935cc5d9d83 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 22 Nov 2023 14:05:31 +0100 Subject: [PATCH 135/315] setFirstMntStartBounds --- .../SetVariableBounds.cpp | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp b/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp index d6e5ff3ce2..c12dbdc5cc 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp @@ -47,9 +47,73 @@ void OptimizedThermalGenerator::setStartEndMntBounds() // start[tauUpper][u][1] = 1 void OptimizedThermalGenerator::setFirstMntStartBounds() { + // loop per areas inside maintenance group + for (const auto& entryWeightMap : maintenanceGroup_) + { + const auto& area = *(entryWeightMap.first); + setFirstMntStartBounds(area); + } return; } +void OptimizedThermalGenerator::setFirstMntStartBounds(const Data::Area& area) +{ + for (auto it = area.thermal.list.mapping.begin(); it != area.thermal.list.mapping.end(); ++it) + { + const auto& cluster = *(it->second); + + // check if cluster exist, do we generate + optimizeMaintenance + // create start end variables only for these clusters + bool createStartEndVar = checkClusterExist(cluster) + && cluster.doWeGenerateTS(globalThermalTSgeneration_) + && cluster.optimizeMaintenance; + if (!createStartEndVar) + continue; + } +} + +void OptimizedThermalGenerator::setFirstMntStartBounds(const Data::ThermalCluster& cluster) +{ + // loop per units inside the cluster + for (int unit = 0; unit < cluster.unitCount; ++unit) + { + int earliestStartOfFirstMaintenance + = calculateUnitEarliestStartOfFirstMaintenance(cluster, unit); + int latestStartOfFirstMaintenance + = calculateUnitLatestStartOfFirstMaintenance(cluster, unit); + + // TODO CR27: + // lets assume for now that when calling two calculate methods above + // that we already did the recalculation of cluster.daysSinceLastMaintenance[unitIndex] + // values if necessary! + + // + // We assume here that vector "start" has member [0] + // meaning: for each unit we assume we have at least one maintenance + // this assumption is ok - since method calculateNumberOfMaintenances() + // will never return number bellow 2 + + if (earliestStartOfFirstMaintenance >= 1) + { + // start[tauLower-1][u][1] = 0 + var.day[earliestStartOfFirstMaintenance - 1] + .areaMap[cluster.parentArea] + .clusterMap[&cluster] + .unitMap[unit] + .start[0] + ->SetBounds(0.0, 0.0); + } + + // start[tauUpper][u][1] = 1 + var.day[latestStartOfFirstMaintenance] + .areaMap[cluster.parentArea] + .clusterMap[&cluster] + .unitMap[unit] + .start[0] + ->SetBounds(1.0, 1.0); + } +} + // BOUNDS/CONSTRAINTS per units and per maintenance - constraint-per-each-unit+mnt[t-fixed=0/T][u][m] // end[0][u][q] = 0 // no maintenance can end in first day // start[T][u][q] = 1 // T - end Day (simulation end) // all maintenance must start till last day From a8699f35f530f41d053d291378e568648515dd31 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 22 Nov 2023 14:25:51 +0100 Subject: [PATCH 136/315] store daysSinceLastMaintenance locally - since we are going to update it after iteration --- .../AuxillaryStructures.h | 1 + .../CalculateParameters.cpp | 18 ++++++++++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h index e08309d03f..5979fb3e08 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h +++ b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h @@ -68,6 +68,7 @@ struct DailyClusterDataPerCluster { std::array maxPower; std::array unitCost; + std::vector daysSinceLastMnt; }; struct DailyClusterDataPerArea diff --git a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp index bf1c7fe964..0574398a59 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp @@ -158,6 +158,10 @@ void OptimizedThermalGenerator::setClusterDailyValues() clusterVariables[&cluster] = DailyClusterDataPerCluster(); clusterVariables[&cluster].maxPower = calculateMaxUnitOutput(cluster); clusterVariables[&cluster].unitCost = calculateAvrUnitDailyCost(cluster); + + // since we will be updating daysSinceLastMaintenance values + // lets create a copy here - this is copy by value! + clusterVariables[&cluster].daysSinceLastMnt = cluster.daysSinceLastMaintenance; } } return; @@ -299,7 +303,10 @@ int OptimizedThermalGenerator::calculateUnitEarliestStartOfFirstMaintenance( if (unitIndex < cluster.daysSinceLastMaintenance.size()) { - return (cluster.interPoPeriod - cluster.daysSinceLastMaintenance[unitIndex] + return (cluster.interPoPeriod + - dailyClusterData.areaMap[cluster.parentArea] + .clusterMap[&cluster] + .daysSinceLastMnt[unitIndex] - cluster.poWindows); } else @@ -323,9 +330,12 @@ int OptimizedThermalGenerator::calculateUnitLatestStartOfFirstMaintenance( // cluster.poWindows is positive or zero // however we will make sure it does not surpass timeHorizon_ - 1 value - return std::min( - cluster.interPoPeriod - cluster.daysSinceLastMaintenance[unitIndex] + cluster.poWindows, - timeHorizon_ - 1); + return std::min(cluster.interPoPeriod + - dailyClusterData.areaMap[cluster.parentArea] + .clusterMap[&cluster] + .daysSinceLastMnt[unitIndex] + + cluster.poWindows, + timeHorizon_ - 1); } else { From 30afaed6f35ab8086f132f8e5dc306a55eea87cd Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 22 Nov 2023 15:18:27 +0100 Subject: [PATCH 137/315] fix setFirstMntStartBounds + print out --- .../optimized-thermal-generator/SetVariableBounds.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp b/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp index c12dbdc5cc..a1e6938aed 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp @@ -13,6 +13,7 @@ void OptimizedThermalGenerator::setVariableBounds() setStartEndMntBounds(); setFirstMntStartBounds(); setAllMntMustStartBounds(); + printAllVariables(); } // BOUNDS per each day - bounds-per-each-day[t] - ENS[t] >= 0, Spill[t] >= 0 @@ -69,6 +70,8 @@ void OptimizedThermalGenerator::setFirstMntStartBounds(const Data::Area& area) && cluster.optimizeMaintenance; if (!createStartEndVar) continue; + + setFirstMntStartBounds(cluster); } } From 96bc28cdef20208cb8e3c07644f4798f7e87c54b Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 22 Nov 2023 15:18:50 +0100 Subject: [PATCH 138/315] improve calculateUnitEarliestStartOfFirstMaintenance --- .../CalculateParameters.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp index 0574398a59..ee5785a95e 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp @@ -303,11 +303,12 @@ int OptimizedThermalGenerator::calculateUnitEarliestStartOfFirstMaintenance( if (unitIndex < cluster.daysSinceLastMaintenance.size()) { - return (cluster.interPoPeriod - - dailyClusterData.areaMap[cluster.parentArea] - .clusterMap[&cluster] - .daysSinceLastMnt[unitIndex] - - cluster.poWindows); + return std::min(cluster.interPoPeriod + - dailyClusterData.areaMap[cluster.parentArea] + .clusterMap[&cluster] + .daysSinceLastMnt[unitIndex] + - cluster.poWindows, + timeHorizon_ - 1); } else { From e12f0abfd6ffb1f43e2196183eab799547c9d16e Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 22 Nov 2023 16:04:46 +0100 Subject: [PATCH 139/315] refactor fixBounds - [WIP] --- .../OptimizedGenerator.h | 9 +- .../SetVariableBounds.cpp | 112 +++++++++++------- 2 files changed, 72 insertions(+), 49 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 9d46a4f644..508605bce4 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -63,10 +63,11 @@ class OptimizedThermalGenerator : public GeneratorTempData void setEnsAndSpillageBounds(); void setUnitPowerOutputBounds(); void setStartEndMntBounds(); - void setFirstMntStartBounds(); - void setFirstMntStartBounds(const Data::Area& area); - void setFirstMntStartBounds(const Data::ThermalCluster& cluster); - void setAllMntMustStartBounds(); + void fixBounds(); + void fixBounds(const Data::Area& area); + void fixBounds(const Data::ThermalCluster& cluster); + void fixBoundsStartFirstMnt(const Data::ThermalCluster& cluster, int unit); + void fixBoundsEndOfMnt(const Data::ThermalCluster& cluster, int unit, int totalMntNum); void buildProblemConstraints(); void buildLoadBalanceConstraints(); diff --git a/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp b/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp index a1e6938aed..080a40e68f 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp @@ -11,8 +11,7 @@ void OptimizedThermalGenerator::setVariableBounds() setEnsAndSpillageBounds(); setUnitPowerOutputBounds(); setStartEndMntBounds(); - setFirstMntStartBounds(); - setAllMntMustStartBounds(); + fixBounds(); printAllVariables(); } @@ -42,23 +41,21 @@ void OptimizedThermalGenerator::setStartEndMntBounds() // it is definitely easier to do set it as a fix bound - // but the solver might go crazy - as for adq.patch -// BOUNDS/CONSTRAINTS per units - constraint-per-each-unit[t-fixed][u][m-fixed] -// first maintenance must start between tauLower and tauUpper -// start[tauLower-1][u][1] = 0 -// start[tauUpper][u][1] = 1 -void OptimizedThermalGenerator::setFirstMntStartBounds() +// this will fix some start & end variable bounds to 0 or 1 +void OptimizedThermalGenerator::fixBounds() { // loop per areas inside maintenance group for (const auto& entryWeightMap : maintenanceGroup_) { const auto& area = *(entryWeightMap.first); - setFirstMntStartBounds(area); + fixBounds(area); } return; } -void OptimizedThermalGenerator::setFirstMntStartBounds(const Data::Area& area) +void OptimizedThermalGenerator::fixBounds(const Data::Area& area) { + // loop per thermal clusters inside the area for (auto it = area.thermal.list.mapping.begin(); it != area.thermal.list.mapping.end(); ++it) { const auto& cluster = *(it->second); @@ -71,57 +68,82 @@ void OptimizedThermalGenerator::setFirstMntStartBounds(const Data::Area& area) if (!createStartEndVar) continue; - setFirstMntStartBounds(cluster); + fixBounds(cluster); } } -void OptimizedThermalGenerator::setFirstMntStartBounds(const Data::ThermalCluster& cluster) +void OptimizedThermalGenerator::fixBounds(const Data::ThermalCluster& cluster) { + int totalMntNumber = calculateNumberOfMaintenances(cluster, timeHorizon_); + // loop per units inside the cluster for (int unit = 0; unit < cluster.unitCount; ++unit) { - int earliestStartOfFirstMaintenance - = calculateUnitEarliestStartOfFirstMaintenance(cluster, unit); - int latestStartOfFirstMaintenance - = calculateUnitLatestStartOfFirstMaintenance(cluster, unit); - - // TODO CR27: - // lets assume for now that when calling two calculate methods above - // that we already did the recalculation of cluster.daysSinceLastMaintenance[unitIndex] - // values if necessary! - - // - // We assume here that vector "start" has member [0] - // meaning: for each unit we assume we have at least one maintenance - // this assumption is ok - since method calculateNumberOfMaintenances() - // will never return number bellow 2 - - if (earliestStartOfFirstMaintenance >= 1) - { - // start[tauLower-1][u][1] = 0 - var.day[earliestStartOfFirstMaintenance - 1] - .areaMap[cluster.parentArea] - .clusterMap[&cluster] - .unitMap[unit] - .start[0] - ->SetBounds(0.0, 0.0); - } - - // start[tauUpper][u][1] = 1 - var.day[latestStartOfFirstMaintenance] + fixBoundsStartFirstMnt(cluster, unit); + fixBoundsEndOfMnt(cluster, unit, totalMntNumber); + } +} + +// Bounds for the start of the first maintenance +// BOUNDS/CONSTRAINTS per units - constraint-per-each-unit[t-fixed][u][m-fixed] +// first maintenance must start between tauLower and tauUpper +// start[tauLower-1][u][1] = 0 +// start[tauUpper][u][1] = 1 +void OptimizedThermalGenerator::fixBoundsStartFirstMnt(const Data::ThermalCluster& cluster, + int unit) +{ + int earliestStartOfFirstMaintenance + = calculateUnitEarliestStartOfFirstMaintenance(cluster, unit); + int latestStartOfFirstMaintenance = calculateUnitLatestStartOfFirstMaintenance(cluster, unit); + + // TODO CR27: + // lets assume for now that when calling two calculate methods above + // that we already did the recalculation of cluster.daysSinceLastMaintenance[unitIndex] + // values if necessary! + + // + // We assume here that vector "start" has member [0] + // meaning: for each unit we assume we have at least one maintenance + // this assumption is ok - since method calculateNumberOfMaintenances() + // will never return number bellow 2 + + if (earliestStartOfFirstMaintenance >= 1) + { + // start[tauLower-1][u][1] = 0 + var.day[earliestStartOfFirstMaintenance - 1] .areaMap[cluster.parentArea] .clusterMap[&cluster] .unitMap[unit] .start[0] - ->SetBounds(1.0, 1.0); + ->SetBounds(0.0, 0.0); } + + // start[tauUpper][u][1] = 1 + var.day[latestStartOfFirstMaintenance] + .areaMap[cluster.parentArea] + .clusterMap[&cluster] + .unitMap[unit] + .start[0] + ->SetBounds(1.0, 1.0); + + return; } -// BOUNDS/CONSTRAINTS per units and per maintenance - constraint-per-each-unit+mnt[t-fixed=0/T][u][m] -// end[0][u][q] = 0 // no maintenance can end in first day -// start[T][u][q] = 1 // T - end Day (simulation end) // all maintenance must start till last day -void OptimizedThermalGenerator::setAllMntMustStartBounds() +// Ensure that units with max average duration between maintenances start their second maintenance +// End of the maintenance on the first day +// BOUNDS/CONSTRAINTS per units and per maintenance - +// constraint-per-each-unit+mnt[t-fixed=0/T][u][m] end[0][u][q] = 0 // no maintenance can end in +// first day start[T][u][q] = 1 // T - end Day (simulation end) // all maintenance must start till +// last day +void OptimizedThermalGenerator::fixBoundsEndOfMnt(const Data::ThermalCluster& cluster, + int unit, + int totalMntNum) { + // loop per maintenances of unit + for (int mnt = 0; mnt < totalMntNum; ++mnt) + { + } + return; } From a01c4341cfcf75b812eec05a9e3d3e42097c8703 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 22 Nov 2023 16:06:46 +0100 Subject: [PATCH 140/315] clean --- .../OptimizedGenerator.h | 4 +-- .../SetVariableBounds.cpp | 25 ------------------- 2 files changed, 1 insertion(+), 28 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 508605bce4..c165e84802 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -60,9 +60,7 @@ class OptimizedThermalGenerator : public GeneratorTempData void printAllVariables(); // for debug purpose only! void setVariableBounds(); - void setEnsAndSpillageBounds(); - void setUnitPowerOutputBounds(); - void setStartEndMntBounds(); + void fixBounds(); void fixBounds(const Data::Area& area); void fixBounds(const Data::ThermalCluster& cluster); diff --git a/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp b/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp index 080a40e68f..28a2d48014 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp @@ -8,35 +8,10 @@ namespace Antares::Solver::TSGenerator { void OptimizedThermalGenerator::setVariableBounds() { - setEnsAndSpillageBounds(); - setUnitPowerOutputBounds(); - setStartEndMntBounds(); fixBounds(); printAllVariables(); } -// BOUNDS per each day - bounds-per-each-day[t] - ENS[t] >= 0, Spill[t] >= 0 -void OptimizedThermalGenerator::setEnsAndSpillageBounds() -{ - // no need for this - defined when creating the Ens & Spill variables - return; -} - -// BOUNDS per day and per each unit - bounds-per-each-day+unit[t][u] - P[t][u] >= 0 -void OptimizedThermalGenerator::setUnitPowerOutputBounds() -{ - // no need for this - defined when creating the P variables - return; -} - -// BOUNDS per day, per each unit and per each mnt - bounds-per-each-day+unit+mnt[t][u][m] -// - s[t][u][m]-> [0, 1] and e[t][u][m]-> [0, 1] -void OptimizedThermalGenerator::setStartEndMntBounds() -{ - // no need for this - defined when creating the Start & End variables - return; -} - // TODO CR27: see if to make this bound or constraint - // it is definitely easier to do set it as a fix bound - // but the solver might go crazy - as for adq.patch From c13ba092cf0b39b3152948ca29e60d210dbec69c Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 22 Nov 2023 16:09:03 +0100 Subject: [PATCH 141/315] clean --- .../optimized-thermal-generator/SetVariableBounds.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp b/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp index 28a2d48014..bccd90a5af 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp @@ -71,11 +71,6 @@ void OptimizedThermalGenerator::fixBoundsStartFirstMnt(const Data::ThermalCluste = calculateUnitEarliestStartOfFirstMaintenance(cluster, unit); int latestStartOfFirstMaintenance = calculateUnitLatestStartOfFirstMaintenance(cluster, unit); - // TODO CR27: - // lets assume for now that when calling two calculate methods above - // that we already did the recalculation of cluster.daysSinceLastMaintenance[unitIndex] - // values if necessary! - // // We assume here that vector "start" has member [0] // meaning: for each unit we assume we have at least one maintenance From 35d0ab432e6ef9c83c7a9733964374469642c15d Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 22 Nov 2023 16:42:28 +0100 Subject: [PATCH 142/315] fixBounds - tested OK --- .../SetVariableBounds.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp b/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp index bccd90a5af..f30da5960f 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp @@ -60,7 +60,6 @@ void OptimizedThermalGenerator::fixBounds(const Data::ThermalCluster& cluster) } // Bounds for the start of the first maintenance -// BOUNDS/CONSTRAINTS per units - constraint-per-each-unit[t-fixed][u][m-fixed] // first maintenance must start between tauLower and tauUpper // start[tauLower-1][u][1] = 0 // start[tauUpper][u][1] = 1 @@ -100,11 +99,7 @@ void OptimizedThermalGenerator::fixBoundsStartFirstMnt(const Data::ThermalCluste } // Ensure that units with max average duration between maintenances start their second maintenance -// End of the maintenance on the first day -// BOUNDS/CONSTRAINTS per units and per maintenance - -// constraint-per-each-unit+mnt[t-fixed=0/T][u][m] end[0][u][q] = 0 // no maintenance can end in -// first day start[T][u][q] = 1 // T - end Day (simulation end) // all maintenance must start till -// last day +// start[T][u][q] = 1 void OptimizedThermalGenerator::fixBoundsEndOfMnt(const Data::ThermalCluster& cluster, int unit, int totalMntNum) @@ -112,6 +107,13 @@ void OptimizedThermalGenerator::fixBoundsEndOfMnt(const Data::ThermalCluster& cl // loop per maintenances of unit for (int mnt = 0; mnt < totalMntNum; ++mnt) { + // start[T][u][q] = 1 + var.day[timeHorizon_ - 1] + .areaMap[cluster.parentArea] + .clusterMap[&cluster] + .unitMap[unit] + .start[mnt] + ->SetBounds(1.0, 1.0); } return; From df8a260d36f0f3f4c429bb56badc18d0e1566183 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 22 Nov 2023 16:48:29 +0100 Subject: [PATCH 143/315] typo --- .../optimized-thermal-generator/AuxillaryStructures.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h index 5979fb3e08..232b338759 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h +++ b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h @@ -23,11 +23,11 @@ class OptProblemSettings final struct OptimizationProblemVariablesPerUnit { - MPVariable* P = nullptr;; // index of P[t][u] variable + MPVariable* P = nullptr;; // pointer to P[t][u] variable // number of elements in the vector is total number of maintenances of unit - std::vector start; // index of s[t][u][m] variable - std::vector end; // index of e[t][u][m] variable + std::vector start; // pointer to s[t][u][m] variable + std::vector end; // pointer to e[t][u][m] variable }; struct OptimizationProblemVariablesPerCluster @@ -44,8 +44,8 @@ struct OptimizationProblemVariablesPerArea struct OptimizationProblemVariablesPerDay { - MPVariable* Ens = nullptr; // index of ENS[t] variable - MPVariable* Spill = nullptr;; // index of Spillage[t] variable + MPVariable* Ens = nullptr; // pointer to ENS[t] variable + MPVariable* Spill = nullptr;; // pointer to Spillage[t] variable // number of elements in the map is total number of areas in optimization problem std::map areaMap; }; From 1250c121a70d8be259b6708c6bd45ddf65c7482a Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 22 Nov 2023 20:46:01 +0100 Subject: [PATCH 144/315] rename --- .../optimized-thermal-generator/SetVariableBounds.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp b/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp index f30da5960f..fe49b11f68 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp @@ -37,10 +37,10 @@ void OptimizedThermalGenerator::fixBounds(const Data::Area& area) // check if cluster exist, do we generate + optimizeMaintenance // create start end variables only for these clusters - bool createStartEndVar = checkClusterExist(cluster) + bool existStartEndVar = checkClusterExist(cluster) && cluster.doWeGenerateTS(globalThermalTSgeneration_) && cluster.optimizeMaintenance; - if (!createStartEndVar) + if (!existStartEndVar) continue; fixBounds(cluster); From 70627e9422861e989f8476d34ab81bb80b7d9691 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 22 Nov 2023 21:08:15 +0100 Subject: [PATCH 145/315] add scenario number and solved trigger to optSett --- .../optimized-thermal-generator/AuxillaryStructures.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h index 232b338759..9ed72806f3 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h +++ b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h @@ -19,6 +19,9 @@ class OptProblemSettings final int firstDay; int lastDay; + int scenario; + + bool solved = true; }; struct OptimizationProblemVariablesPerUnit From b282072673955a3751e5667a972d4a16e9c5548f Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 22 Nov 2023 21:09:40 +0100 Subject: [PATCH 146/315] improve main scenario/step loop add solve problem --- .../CalculateParameters.cpp | 15 +++ .../OptimizedGenerator.cpp | 96 ++++++++----------- .../OptimizedGenerator.h | 10 +- .../SolveProbem.cpp | 36 ++++++- 4 files changed, 94 insertions(+), 63 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp index ee5785a95e..c72d654575 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp @@ -346,6 +346,21 @@ int OptimizedThermalGenerator::calculateUnitLatestStartOfFirstMaintenance( } } +// re-calculate parameters +void OptimizedThermalGenerator::reCalculateDaysSinceLastMnt(const OptProblemSettings& optSett) +{ + if (optSett.scenario == 0 && optSett.firstDay == 0) + return; + if (optSett.scenario != 0 && optSett.firstDay == 0) + { + // we are back in first step, but not first scenario we have messed up our values + // we need to re-do + // clusterVariables[&cluster].daysSinceLastMnt = cluster.daysSinceLastMaintenance; + // for all areas and clusters + } + // TODO CR27: re-calculate days since last maintenance inputs if necessary +} + // auxillary functions - for parameter calculations std::array OptimizedThermalGenerator::calculateDailySums( const std::array& hourlyValues) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp index fc47969b56..240c819cf2 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp @@ -12,6 +12,7 @@ namespace Antares::Solver::TSGenerator // optimization problem - methods void OptimizedThermalGenerator::GenerateOptimizedThermalTimeSeries() { + allocateWhereToWriteTs(); setMaintenanceGroupParameters(); if (!checkMaintenanceGroupParameters()) return; @@ -22,89 +23,74 @@ void OptimizedThermalGenerator::GenerateOptimizedThermalTimeSeries() OptProblemSettings optSett; optSett.firstDay = 0; optSett.lastDay = timeHorizon_; + optSett.scenario = scenarioIndex; + // loop till the end of scenario length while (optSett.firstDay < scenarioLength_ * DAYS_PER_YEAR) { - createOptimizationProblemPerGroup(optSett); + // check if the optimization was successful and exit loop otherwise + if (!runOptimizationProblem(optSett)) + break; // Update the time values for the next iteration optSett.firstDay += timeStep_; optSett.lastDay += timeStep_; } + saveScenarioResults(optSett); } } -void OptimizedThermalGenerator::createOptimizationProblemPerGroup(const OptProblemSettings& optSett) +void OptimizedThermalGenerator::allocateWhereToWriteTs() { - runOptimizationProblem(optSett); - // ... - // do the optimization post-processing here & - // do the writing off the result here - - // just playing here - will ue this loops later for opt problem formulation - // loop through the elements of weightMap weights_ + // loop per areas inside maintenance group for (const auto& entryWeightMap : maintenanceGroup_) { const auto& area = *(entryWeightMap.first); - // loop through the thermal clusters inside the area + // loop per thermal clusters inside the area for (auto it = area.thermal.list.mapping.begin(); it != area.thermal.list.mapping.end(); ++it) { auto& cluster = *(it->second); - createOptimizationProblemPerCluster(area, cluster); - ++pProgression; + + // check if cluster exist, do we generate + optimizeMaintenance + // create start end variables only for these clusters + bool genTS = checkClusterExist(cluster) + && cluster.doWeGenerateTS(globalThermalTSgeneration_) + && cluster.optimizeMaintenance; + if (!genTS) + continue; + + // allocate space + cluster.series.timeSeries.reset(nbThermalTimeseries, 8760); + cluster.series.timeSeries.fill(777.); // dummy for now } } - // end play + return; } -void OptimizedThermalGenerator::createOptimizationProblemPerCluster(const Data::Area& area, - Data::ThermalCluster& cluster) +void OptimizedThermalGenerator::saveScenarioResults(const OptProblemSettings& optSett) { - if (cluster.doWeGenerateTS(globalThermalTSgeneration_) && cluster.optimizeMaintenance) - { - // number of maintenances are defined per cluster-unit - // but are the same for all units inside the same cluster - int numberOfMaintenancesPerUnit; - int averageMaintenanceDuration; - numberOfMaintenancesPerUnit = calculateNumberOfMaintenances( - cluster, timeHorizon_); - averageMaintenanceDuration - = calculateAverageMaintenanceDuration(cluster); // this will floor the double value !! - std::array maxUnitOutput = calculateMaxUnitOutput(cluster); - // uint earliestStartOfFirstMaintenance - // = calculateUnitEarliestStartOfFirstMaintenance(cluster, 8); - // uint latestStartOfFirstMaintenance - // = calculateUnitLatestStartOfFirstMaintenance(cluster, 8); - // just playing here - this needs to go into new method - class - operator - logs.info() << "CR27-INFO: This cluster is active for mnt planning: " - << cluster.getFullName(); - - if (!cluster.prepro) - { - logs.error() << "Cluster: " << area.name << '/' << cluster.name() - << ": The timeseries will not be regenerated. All data " - "related to the ts-generator for " - << "'thermal' have been released."; - } + // do not save if optimization failed at some step + if (!optSett.solved) + return; - assert(cluster.prepro); + // create a method to calculate all the Cluster outputs in MW + // using vectors of std::pairs per each cluster-unit + // that will contain maintenance start and duration - if (0 == cluster.unitCount || 0 == cluster.nominalCapacity || nbThermalTimeseries == 0) - { - cluster.series.timeSeries.reset(1, 8760); - } - else - { - cluster.series.timeSeries.reset(nbThermalTimeseries, 8760); - cluster.series.timeSeries.fill(777.); - } + // save results - if (archive) - writeResultsToDisk(area, cluster); + int colSaveFrom = optSett.scenario * scenarioLength_; + int colSaveTo = colSaveFrom + scenarioLength_ - 1; - // end playing - } + // loop through all areas and clusters and write results + + /* + // do not forget archive!! + if (archive) + writeResultsToDisk(area, cluster); + + */ } } // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index c165e84802..530a7e7fe1 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -95,14 +95,15 @@ class OptimizedThermalGenerator : public GeneratorTempData void printObjectiveFunction(MPObjective* objective); - void solveProblem(); + bool solveProblem(OptProblemSettings& optSett); void resetProblem(); - void runOptimizationProblem(const OptProblemSettings& optSett); + void appendStepResults(); // optimization problem - methods - private - void createOptimizationProblemPerGroup(const OptProblemSettings& optSett); - void createOptimizationProblemPerCluster(const Data::Area& area, Data::ThermalCluster& cluster); + void allocateWhereToWriteTs(); + bool runOptimizationProblem(OptProblemSettings& optSett); + void saveScenarioResults(const OptProblemSettings& optSett); // calculate parameters methods - per maintenance group void setMaintenanceGroupParameters(); @@ -126,6 +127,7 @@ class OptimizedThermalGenerator : public GeneratorTempData uint unitIndex); int calculateUnitLatestStartOfFirstMaintenance(const Data::ThermalCluster& cluster, uint unitIndex); + void reCalculateDaysSinceLastMnt(const OptProblemSettings& optSett); // auxillary functions static std::array calculateDailySums( diff --git a/src/solver/ts-generator/optimized-thermal-generator/SolveProbem.cpp b/src/solver/ts-generator/optimized-thermal-generator/SolveProbem.cpp index 47aa359e8e..ef89090c36 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/SolveProbem.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/SolveProbem.cpp @@ -6,18 +6,46 @@ namespace Antares::Solver::TSGenerator { -// call all methods -void OptimizedThermalGenerator::runOptimizationProblem(const OptProblemSettings& optSett) +// call all methods +bool OptimizedThermalGenerator::runOptimizationProblem(OptProblemSettings& optSett) { + reCalculateDaysSinceLastMnt(optSett); buildProblemVariables(optSett); setVariableBounds(); buildProblemConstraints(); setProblemCost(optSett); - solveProblem(); + if (!solveProblem(optSett)) + { + resetProblem(); + return false; + } + appendStepResults(); resetProblem(); + return true; } + // retrieve and check the results if optimization was successful -void OptimizedThermalGenerator::solveProblem() +bool OptimizedThermalGenerator::solveProblem(OptProblemSettings& optSett) +{ + // Solve the problem + const MPSolver::ResultStatus result_status = solver.Solve(); + + if (result_status != MPSolver::OPTIMAL) + { + // If not optimal, print that optimization failed + optSett.solved = false; + logs.warning() << "Maintenance group: " << maintenanceGroup_.name() + << ". Scenario Num: " << optSett.scenario + << ". Optimization failed in step: " << optSett.firstDay << ".Day - " + << optSett.lastDay << ".Day. This scenario wont have generated timeseries"; + return false; + } + return true; +} + +// TODO CR27: move this method somewhere else +// collect and store results form firstDay-lastDay +void OptimizedThermalGenerator::appendStepResults() { return; } From c86c8bf9f16d8557706d052bd7135294579bed1c Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 22 Nov 2023 21:18:47 +0100 Subject: [PATCH 147/315] add comments --- .../OptimizedGenerator.h | 29 ++++++++++++------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 530a7e7fe1..cec7ffee44 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -23,17 +23,18 @@ class OptimizedThermalGenerator : public GeneratorTempData private: // optimization problem construction methods + // dummy function - to be deleted void countVariables(); + // functions to allocate variable structure void allocateVarStruct(); void allocateVarStruct(int day); void allocateVarStruct(int day, const Data::Area& area); void allocateVarStruct(int day, const Data::ThermalCluster& cluster); + // functions to build problem variables void buildProblemVariables(const OptProblemSettings& optSett); - void buildEnsAndSpillageVariables(const OptProblemSettings& optSett); - void buildUnitPowerOutputVariables(const OptProblemSettings& optSett); void buildUnitPowerOutputVariables(const OptProblemSettings& optSett, int day); void buildUnitPowerOutputVariables(const OptProblemSettings& optSett, @@ -42,7 +43,6 @@ class OptimizedThermalGenerator : public GeneratorTempData void buildUnitPowerOutputVariables(const OptProblemSettings& optSett, int day, const Data::ThermalCluster& cluster); - void buildStartEndMntVariables(const OptProblemSettings& optSett); void buildStartEndMntVariables(const OptProblemSettings& optSett, int day); void buildStartEndMntVariables(const OptProblemSettings& optSett, @@ -57,21 +57,21 @@ class OptimizedThermalGenerator : public GeneratorTempData int unit, int totalMntNumber); - void printAllVariables(); // for debug purpose only! - + // functions to fix bounds of some variables void setVariableBounds(); - void fixBounds(); void fixBounds(const Data::Area& area); void fixBounds(const Data::ThermalCluster& cluster); void fixBoundsStartFirstMnt(const Data::ThermalCluster& cluster, int unit); void fixBoundsEndOfMnt(const Data::ThermalCluster& cluster, int unit, int totalMntNum); + // functions to build problem constraints void buildProblemConstraints(); void buildLoadBalanceConstraints(); void setStartEndMntLogicConstraints(); void setMaxUnitOutputConstraints(); + // functions to set problem objective function void setProblemCost(const OptProblemSettings& optSett); void setProblemEnsCost(MPObjective* objective); void setProblemSpillCost(MPObjective* objective); @@ -93,19 +93,25 @@ class OptimizedThermalGenerator : public GeneratorTempData int unitIndex, double powerCost); - void printObjectiveFunction(MPObjective* objective); - + // solve problem and check if optimal solution found bool solveProblem(OptProblemSettings& optSett); + + // reset problem and variable structure void resetProblem(); + // collect and store results from firstDay-lastDay void appendStepResults(); - // optimization problem - methods - private + // print functions for debugging + void printAllVariables(); // for debug purpose only! + void printObjectiveFunction(MPObjective* objective); + + // Functions called in main method: void allocateWhereToWriteTs(); bool runOptimizationProblem(OptProblemSettings& optSett); void saveScenarioResults(const OptProblemSettings& optSett); - // calculate parameters methods - per maintenance group + // Calculate parameters methods - per maintenance group void setMaintenanceGroupParameters(); bool checkMaintenanceGroupParameters(); std::pair calculateTimeHorizonAndStep(); @@ -195,7 +201,8 @@ class OptimizedThermalGenerator : public GeneratorTempData ~OptimizedThermalGenerator() = default; - // optimization problem - methods - public + // Main functions - loop per scenarios and through the scenario length step by step + // (moving window) void GenerateOptimizedThermalTimeSeries(); }; From 2962d271a853ea1782acf6e4cb8761272d2100cf Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 22 Nov 2023 21:25:06 +0100 Subject: [PATCH 148/315] small refactor --- .../ts-generator/optimized-thermal-generator/SolveProbem.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/SolveProbem.cpp b/src/solver/ts-generator/optimized-thermal-generator/SolveProbem.cpp index ef89090c36..7f70fe8cd1 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/SolveProbem.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/SolveProbem.cpp @@ -9,18 +9,15 @@ namespace Antares::Solver::TSGenerator // call all methods bool OptimizedThermalGenerator::runOptimizationProblem(OptProblemSettings& optSett) { + resetProblem(); reCalculateDaysSinceLastMnt(optSett); buildProblemVariables(optSett); setVariableBounds(); buildProblemConstraints(); setProblemCost(optSett); if (!solveProblem(optSett)) - { - resetProblem(); return false; - } appendStepResults(); - resetProblem(); return true; } From e932e98cfd2a7f195fecab4055f7fa612add0a08 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 22 Nov 2023 22:45:38 +0100 Subject: [PATCH 149/315] fixVariableBounds - refactor + rename + add last one --- .../CalculateParameters.cpp | 2 +- .../OptimizedGenerator.h | 16 +++-- .../SetVariableBounds.cpp | 62 +++++++++++++------ .../SolveProbem.cpp | 2 +- 4 files changed, 58 insertions(+), 24 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp index c72d654575..6698c0102a 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp @@ -184,7 +184,7 @@ int OptimizedThermalGenerator::calculateNumberOfMaintenances(const Data::Thermal return std::max(timeHorizon / cluster.interPoPeriod, minNumberOfMaintenances); // floor } -uint OptimizedThermalGenerator::calculateAverageMaintenanceDuration(Data::ThermalCluster& cluster) +int OptimizedThermalGenerator::calculateAverageMaintenanceDuration(const Data::ThermalCluster& cluster) { double sum = 0.0; for (std::size_t row = 0; row < DAYS_PER_YEAR; ++row) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index cec7ffee44..d0c82ef5b1 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -58,12 +58,20 @@ class OptimizedThermalGenerator : public GeneratorTempData int totalMntNumber); // functions to fix bounds of some variables - void setVariableBounds(); + void fixVariableBounds(); void fixBounds(); void fixBounds(const Data::Area& area); void fixBounds(const Data::ThermalCluster& cluster); - void fixBoundsStartFirstMnt(const Data::ThermalCluster& cluster, int unit); - void fixBoundsEndOfMnt(const Data::ThermalCluster& cluster, int unit, int totalMntNum); + void fixBounds(const Data::ThermalCluster& cluster, + int unit, + int totalMntNum, + int avrMntDuration); + void fixBoundsFirstMnt(const Data::ThermalCluster& cluster, int unit); + void fixBoundsStartSecondMnt(const Data::ThermalCluster& cluster, int unit, int mnt); + void fixBoundsMntEnd(const Data::ThermalCluster& cluster, + int unit, + int mnt, + int avrMntDuration); // functions to build problem constraints void buildProblemConstraints(); @@ -121,7 +129,7 @@ class OptimizedThermalGenerator : public GeneratorTempData // calculate parameters methods - per cluster int calculateNumberOfMaintenances(const Data::ThermalCluster& cluster, int timeHorizon); - uint calculateAverageMaintenanceDuration(Data::ThermalCluster& cluster); + int calculateAverageMaintenanceDuration(const Data::ThermalCluster& cluster); static std::array calculateMaxUnitOutput(const Data::ThermalCluster& cluster); static std::array calculateAvrUnitDailyCost(const Data::ThermalCluster& cluster); // getters diff --git a/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp b/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp index fe49b11f68..5a755550c4 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp @@ -6,7 +6,7 @@ namespace Antares::Solver::TSGenerator { -void OptimizedThermalGenerator::setVariableBounds() +void OptimizedThermalGenerator::fixVariableBounds() { fixBounds(); printAllVariables(); @@ -38,8 +38,8 @@ void OptimizedThermalGenerator::fixBounds(const Data::Area& area) // check if cluster exist, do we generate + optimizeMaintenance // create start end variables only for these clusters bool existStartEndVar = checkClusterExist(cluster) - && cluster.doWeGenerateTS(globalThermalTSgeneration_) - && cluster.optimizeMaintenance; + && cluster.doWeGenerateTS(globalThermalTSgeneration_) + && cluster.optimizeMaintenance; if (!existStartEndVar) continue; @@ -50,12 +50,13 @@ void OptimizedThermalGenerator::fixBounds(const Data::Area& area) void OptimizedThermalGenerator::fixBounds(const Data::ThermalCluster& cluster) { int totalMntNumber = calculateNumberOfMaintenances(cluster, timeHorizon_); + int avrMntDuration = calculateAverageMaintenanceDuration(cluster); // loop per units inside the cluster for (int unit = 0; unit < cluster.unitCount; ++unit) { - fixBoundsStartFirstMnt(cluster, unit); - fixBoundsEndOfMnt(cluster, unit, totalMntNumber); + fixBoundsFirstMnt(cluster, unit); + fixBounds(cluster, unit, totalMntNumber, avrMntDuration); } } @@ -63,8 +64,7 @@ void OptimizedThermalGenerator::fixBounds(const Data::ThermalCluster& cluster) // first maintenance must start between tauLower and tauUpper // start[tauLower-1][u][1] = 0 // start[tauUpper][u][1] = 1 -void OptimizedThermalGenerator::fixBoundsStartFirstMnt(const Data::ThermalCluster& cluster, - int unit) +void OptimizedThermalGenerator::fixBoundsFirstMnt(const Data::ThermalCluster& cluster, int unit) { int earliestStartOfFirstMaintenance = calculateUnitEarliestStartOfFirstMaintenance(cluster, unit); @@ -98,25 +98,51 @@ void OptimizedThermalGenerator::fixBoundsStartFirstMnt(const Data::ThermalCluste return; } -// Ensure that units with max average duration between maintenances start their second maintenance -// start[T][u][q] = 1 -void OptimizedThermalGenerator::fixBoundsEndOfMnt(const Data::ThermalCluster& cluster, - int unit, - int totalMntNum) +void OptimizedThermalGenerator::fixBounds(const Data::ThermalCluster& cluster, + int unit, + int totalMntNum, + int avrMntDuration) { // loop per maintenances of unit for (int mnt = 0; mnt < totalMntNum; ++mnt) { - // start[T][u][q] = 1 - var.day[timeHorizon_ - 1] + fixBoundsStartSecondMnt(cluster, unit, mnt); + fixBoundsMntEnd(cluster, unit, mnt, avrMntDuration); + } + + return; +} + +// Ensure that units with max average duration between maintenances start their second maintenance +// start[T][u][q] = 1 +void OptimizedThermalGenerator::fixBoundsStartSecondMnt(const Data::ThermalCluster& cluster, + int unit, + int mnt) +{ + var.day[timeHorizon_ - 1] + .areaMap[cluster.parentArea] + .clusterMap[&cluster] + .unitMap[unit] + .start[mnt] + ->SetBounds(1.0, 1.0); +} + +// End of the maintenance can't happen before average maintenance duration +// end[T = [0, average_maintenance_duration_per_unit]][u][q] = 0 +void OptimizedThermalGenerator::fixBoundsMntEnd(const Data::ThermalCluster& cluster, + int unit, + int mnt, + int avrMntDuration) +{ + for (int day = 0; day < avrMntDuration; ++day) + { + var.day[day] .areaMap[cluster.parentArea] .clusterMap[&cluster] .unitMap[unit] - .start[mnt] - ->SetBounds(1.0, 1.0); + .end[mnt] + ->SetBounds(0.0, 0.0); } - - return; } } // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/SolveProbem.cpp b/src/solver/ts-generator/optimized-thermal-generator/SolveProbem.cpp index 7f70fe8cd1..447341c9d9 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/SolveProbem.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/SolveProbem.cpp @@ -12,7 +12,7 @@ bool OptimizedThermalGenerator::runOptimizationProblem(OptProblemSettings& optSe resetProblem(); reCalculateDaysSinceLastMnt(optSett); buildProblemVariables(optSett); - setVariableBounds(); + fixVariableBounds(); buildProblemConstraints(); setProblemCost(optSett); if (!solveProblem(optSett)) From c555a1d513210cd3c0901e987e54aaf17b7bf085 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 22 Nov 2023 23:41:30 +0100 Subject: [PATCH 150/315] add numberOfMaintenances & averageMaintenanceDuration to DailyClusterDataPerCluster --- .../AuxillaryStructures.h | 2 ++ .../CalculateParameters.cpp | 17 +++++++++++++++++ .../OptimizedGenerator.h | 2 ++ 3 files changed, 21 insertions(+) diff --git a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h index 9ed72806f3..2a75a775c8 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h +++ b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h @@ -72,6 +72,8 @@ struct DailyClusterDataPerCluster std::array maxPower; std::array unitCost; std::vector daysSinceLastMnt; + int numberOfMaintenances; + int averageMaintenanceDuration; }; struct DailyClusterDataPerArea diff --git a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp index 6698c0102a..6e4cefacec 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp @@ -159,6 +159,11 @@ void OptimizedThermalGenerator::setClusterDailyValues() clusterVariables[&cluster].maxPower = calculateMaxUnitOutput(cluster); clusterVariables[&cluster].unitCost = calculateAvrUnitDailyCost(cluster); + clusterVariables[&cluster].numberOfMaintenances + = calculateNumberOfMaintenances(cluster, timeHorizon_); + clusterVariables[&cluster].averageMaintenanceDuration + = calculateAverageMaintenanceDuration(cluster); + // since we will be updating daysSinceLastMaintenance values // lets create a copy here - this is copy by value! clusterVariables[&cluster].daysSinceLastMnt = cluster.daysSinceLastMaintenance; @@ -282,6 +287,18 @@ double OptimizedThermalGenerator::getUnitPowerOutput(const Data::ThermalCluster& return unitOutput; } +int OptimizedThermalGenerator::getNumberOfMaintenances(const Data::ThermalCluster& cluster) +{ + return dailyClusterData.areaMap[cluster.parentArea].clusterMap[&cluster].numberOfMaintenances; +} + +int OptimizedThermalGenerator::getAverageMaintenanceDuration(const Data::ThermalCluster& cluster) +{ + return dailyClusterData.areaMap[cluster.parentArea] + .clusterMap[&cluster] + .averageMaintenanceDuration; +} + // calculate parameters methods - per cluster-Unit int OptimizedThermalGenerator::calculateUnitEarliestStartOfFirstMaintenance( const Data::ThermalCluster& cluster, diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index d0c82ef5b1..bbf4adfcb8 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -135,6 +135,8 @@ class OptimizedThermalGenerator : public GeneratorTempData // getters double getUnitPowerCost(const Data::ThermalCluster& cluster, int optimizationDay); double getUnitPowerOutput(const Data::ThermalCluster& cluster, int optimizationDay); + int getNumberOfMaintenances(const Data::ThermalCluster& cluster); + int getAverageMaintenanceDuration(const Data::ThermalCluster& cluster); // calculate parameters methods - per cluster-Unit int calculateUnitEarliestStartOfFirstMaintenance(const Data::ThermalCluster& cluster, From bde9e5d16ad23698ca3bb1df20d9c8fd44516ece Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 22 Nov 2023 23:47:34 +0100 Subject: [PATCH 151/315] call getters instead of calculate - avoid numerous recalculation --- .../optimized-thermal-generator/CreateVariables.cpp | 3 ++- .../optimized-thermal-generator/SetVariableBounds.cpp | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp b/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp index bbb499d30f..851a525b00 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp @@ -251,7 +251,8 @@ void OptimizedThermalGenerator::buildStartEndMntVariables(const OptProblemSettin int day, const Data ::ThermalCluster& cluster) { - int totalMntNumber = calculateNumberOfMaintenances(cluster, timeHorizon_); + int totalMntNumber = getNumberOfMaintenances(cluster); + // loop per units inside the cluster for (int unit = 0; unit < cluster.unitCount; ++unit) { diff --git a/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp b/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp index 5a755550c4..15df0d20ba 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp @@ -49,8 +49,8 @@ void OptimizedThermalGenerator::fixBounds(const Data::Area& area) void OptimizedThermalGenerator::fixBounds(const Data::ThermalCluster& cluster) { - int totalMntNumber = calculateNumberOfMaintenances(cluster, timeHorizon_); - int avrMntDuration = calculateAverageMaintenanceDuration(cluster); + int totalMntNumber = getNumberOfMaintenances(cluster); + int avrMntDuration = getAverageMaintenanceDuration(cluster); // loop per units inside the cluster for (int unit = 0; unit < cluster.unitCount; ++unit) From 6b46918b46ca9027ab308524aeb17cf309d4a0f0 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 22 Nov 2023 23:58:54 +0100 Subject: [PATCH 152/315] refactor --- .../optimized-thermal-generator/CalculateParameters.cpp | 7 ++++--- .../optimized-thermal-generator/OptimizedGenerator.h | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp index 6e4cefacec..9509125663 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp @@ -16,7 +16,7 @@ void OptimizedThermalGenerator::setMaintenanceGroupParameters() residualLoadDailyValues_ = calculateDailySums(maintenanceGroup_.getUsedResidualLoadTS()); std::tie(ensCost_, spillCost_) = calculateMaintenanceGroupENSandSpillageCost(); std::tie(timeStep_, timeHorizon_) = calculateTimeHorizonAndStep(); - setClusterDailyValues(); + setClusterData(); } bool OptimizedThermalGenerator::checkMaintenanceGroupParameters() @@ -52,7 +52,8 @@ std::pair OptimizedThermalGenerator::calculateTimeHorizonAndStep() ++it) { const auto& cluster = *(it->second); - if (cluster.doWeGenerateTS(globalThermalTSgeneration_) && cluster.optimizeMaintenance) + if (checkClusterExist(cluster) && cluster.doWeGenerateTS(globalThermalTSgeneration_) + && cluster.optimizeMaintenance) { averageDurationBetweenMaintenances.push_back(cluster.interPoPeriod); } @@ -136,7 +137,7 @@ void OptimizedThermalGenerator::calculateResidualLoad() maintenanceGroup_.setUsedResidualLoadTS(refValue); } -void OptimizedThermalGenerator::setClusterDailyValues() +void OptimizedThermalGenerator::setClusterData() { for (const auto& entryWeightMap : maintenanceGroup_) { diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index bbf4adfcb8..258cc805e5 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -125,7 +125,7 @@ class OptimizedThermalGenerator : public GeneratorTempData std::pair calculateTimeHorizonAndStep(); std::pair calculateMaintenanceGroupENSandSpillageCost(); void calculateResidualLoad(); - void setClusterDailyValues(); + void setClusterData(); // calculate parameters methods - per cluster int calculateNumberOfMaintenances(const Data::ThermalCluster& cluster, int timeHorizon); From 5455baa0b820bd2d457d219e1d3cb9c42599d1f9 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Thu, 23 Nov 2023 09:29:05 +0100 Subject: [PATCH 153/315] renaming + more getters --- .../AuxillaryStructures.h | 2 +- .../CalculateParameters.cpp | 36 ++++++++++++------- .../OptimizedGenerator.h | 7 ++-- .../SetProblemCost.cpp | 4 +-- 4 files changed, 31 insertions(+), 18 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h index 2a75a775c8..0a9abd5198 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h +++ b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h @@ -70,7 +70,7 @@ struct OptimizationProblemVariables struct DailyClusterDataPerCluster { std::array maxPower; - std::array unitCost; + std::array avgCost; std::vector daysSinceLastMnt; int numberOfMaintenances; int averageMaintenanceDuration; diff --git a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp index 9509125663..8ca23b9258 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp @@ -158,7 +158,7 @@ void OptimizedThermalGenerator::setClusterData() auto& clusterVariables = areaVariables[&area].clusterMap; clusterVariables[&cluster] = DailyClusterDataPerCluster(); clusterVariables[&cluster].maxPower = calculateMaxUnitOutput(cluster); - clusterVariables[&cluster].unitCost = calculateAvrUnitDailyCost(cluster); + clusterVariables[&cluster].avgCost = calculateAvrUnitDailyCost(cluster); clusterVariables[&cluster].numberOfMaintenances = calculateNumberOfMaintenances(cluster, timeHorizon_); @@ -245,8 +245,9 @@ std::array OptimizedThermalGenerator::calculateAvrUnitDai return avrCostDailyValues; } -double OptimizedThermalGenerator::getUnitPowerCost(const Data::ThermalCluster& cluster, - int optimizationDay) +// Getters +double OptimizedThermalGenerator::getPowerCost(const Data::ThermalCluster& cluster, + int optimizationDay) { /* ** Unit cost can be directly set, @@ -273,19 +274,22 @@ double OptimizedThermalGenerator::getUnitPowerCost(const Data::ThermalCluster& c return 0.; } - int realDay = dayOfTheYear(optimizationDay); - auto unitCost - = dailyClusterData.areaMap[cluster.parentArea].clusterMap[&cluster].unitCost[realDay]; - return unitCost; + return dailyClusterData.areaMap[cluster.parentArea] + .clusterMap[&cluster] + .avgCost[dayOfTheYear(optimizationDay)]; } -double OptimizedThermalGenerator::getUnitPowerOutput(const Data::ThermalCluster& cluster, - int optimizationDay) +double OptimizedThermalGenerator::getPowerOutput(const Data::ThermalCluster& cluster, + int optimizationDay) { - int realDay = dayOfTheYear(optimizationDay); - auto unitOutput - = dailyClusterData.areaMap[cluster.parentArea].clusterMap[&cluster].maxPower[realDay]; - return unitOutput; + return dailyClusterData.areaMap[cluster.parentArea] + .clusterMap[&cluster] + .maxPower[dayOfTheYear(optimizationDay)]; +} + +double OptimizedThermalGenerator::getResidualLoad(int optimizationDay) +{ + return residualLoadDailyValues_[dayOfTheYear(optimizationDay)]; } int OptimizedThermalGenerator::getNumberOfMaintenances(const Data::ThermalCluster& cluster) @@ -300,6 +304,12 @@ int OptimizedThermalGenerator::getAverageMaintenanceDuration(const Data::Thermal .averageMaintenanceDuration; } +int OptimizedThermalGenerator::getAverageDurationBetweenMaintenances( + const Data::ThermalCluster& cluster) +{ + return cluster.interPoPeriod; +} + // calculate parameters methods - per cluster-Unit int OptimizedThermalGenerator::calculateUnitEarliestStartOfFirstMaintenance( const Data::ThermalCluster& cluster, diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 258cc805e5..056cb7cf78 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -132,11 +132,14 @@ class OptimizedThermalGenerator : public GeneratorTempData int calculateAverageMaintenanceDuration(const Data::ThermalCluster& cluster); static std::array calculateMaxUnitOutput(const Data::ThermalCluster& cluster); static std::array calculateAvrUnitDailyCost(const Data::ThermalCluster& cluster); + // getters - double getUnitPowerCost(const Data::ThermalCluster& cluster, int optimizationDay); - double getUnitPowerOutput(const Data::ThermalCluster& cluster, int optimizationDay); + double getPowerCost(const Data::ThermalCluster& cluster, int optimizationDay); + double getPowerOutput(const Data::ThermalCluster& cluster, int optimizationDay); + double getResidualLoad(int optimizationDay); int getNumberOfMaintenances(const Data::ThermalCluster& cluster); int getAverageMaintenanceDuration(const Data::ThermalCluster& cluster); + int getAverageDurationBetweenMaintenances(const Data::ThermalCluster& cluster); // calculate parameters methods - per cluster-Unit int calculateUnitEarliestStartOfFirstMaintenance(const Data::ThermalCluster& cluster, diff --git a/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp b/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp index 1479a04d46..d3e6b0cd46 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp @@ -7,7 +7,7 @@ namespace Antares::Solver::TSGenerator { // create OBJECTIVE FUNCTION - sum through [t] and sum through [u] -// sum[days]{ EnsCost*Ens[day] + SpillCost[day] + sum[units][ UnitCost*P[t][u] ] } +// sum[days]{ EnsCost*Ens[day] + SpillCost[day] + sum[units][ avgCost*P[t][u] ] } void OptimizedThermalGenerator::setProblemCost(const OptProblemSettings& optSett) { MPObjective* objective = solver.MutableObjective(); @@ -93,7 +93,7 @@ void OptimizedThermalGenerator::setProblemPowerCost(const OptProblemSettings& op const Data::Area& area, const Data::ThermalCluster& cluster) { - double unitPowerCost = getUnitPowerCost(cluster, day + optSett.firstDay); + double unitPowerCost = getPowerCost(cluster, day + optSett.firstDay); // loop per unit inside the cluster for (int unit = 0; unit < cluster.unitCount; ++unit) { From c4ebbdb36e0149b85ae5fb1f1145d04b74c858e5 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Thu, 23 Nov 2023 09:45:50 +0100 Subject: [PATCH 154/315] refactor create P var - create by all days first --- .../CreateVariables.cpp | 30 +++++++++---------- .../OptimizedGenerator.h | 9 +++--- 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp b/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp index 851a525b00..fb118d7519 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp @@ -149,28 +149,16 @@ void OptimizedThermalGenerator::buildEnsAndSpillageVariables(const OptProblemSet // create VARIABLES per day and per cluster-unit - P[t][u] void OptimizedThermalGenerator::buildUnitPowerOutputVariables(const OptProblemSettings& optSett) -{ - // loop per day - for (int day = 0; day < timeHorizon_; ++day) - { - buildUnitPowerOutputVariables(optSett, day); - } - return; -} - -void OptimizedThermalGenerator::buildUnitPowerOutputVariables(const OptProblemSettings& optSett, - int day) { // loop per areas inside maintenance group for (const auto& entryWeightMap : maintenanceGroup_) { const auto& area = *(entryWeightMap.first); - buildUnitPowerOutputVariables(optSett, day, area); + buildUnitPowerOutputVariables(optSett, area); } } void OptimizedThermalGenerator::buildUnitPowerOutputVariables(const OptProblemSettings& optSett, - int day, const Data::Area& area) { // loop per thermal clusters inside the area @@ -183,16 +171,26 @@ void OptimizedThermalGenerator::buildUnitPowerOutputVariables(const OptProblemSe if (!checkClusterExist(cluster)) continue; - buildUnitPowerOutputVariables(optSett, day, cluster); + buildUnitPowerOutputVariables(optSett, cluster); } } void OptimizedThermalGenerator::buildUnitPowerOutputVariables(const OptProblemSettings& optSett, - int day, const Data::ThermalCluster& cluster) { // loop per units inside the cluster for (int unit = 0; unit < cluster.unitCount; ++unit) + { + buildUnitPowerOutputVariables(optSett, cluster, unit); + } +} + +void OptimizedThermalGenerator::buildUnitPowerOutputVariables(const OptProblemSettings& optSett, + const Data::ThermalCluster& cluster, + int unit) +{ + // loop per day + for (int day = 0; day < timeHorizon_; ++day) { // add P[t][u] variables var.day[day].areaMap[cluster.parentArea].clusterMap[&cluster].unitMap[unit].P @@ -202,6 +200,8 @@ void OptimizedThermalGenerator::buildUnitPowerOutputVariables(const OptProblemSe + cluster.getFullName().to() + "." + std::to_string(unit) + "]"); } + + return; } // create VARIABLES per day, per cluster-unit and per maintenance - s[t][u][m] & e[t][u][m] diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 056cb7cf78..524f424d4b 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -36,13 +36,12 @@ class OptimizedThermalGenerator : public GeneratorTempData void buildProblemVariables(const OptProblemSettings& optSett); void buildEnsAndSpillageVariables(const OptProblemSettings& optSett); void buildUnitPowerOutputVariables(const OptProblemSettings& optSett); - void buildUnitPowerOutputVariables(const OptProblemSettings& optSett, int day); + void buildUnitPowerOutputVariables(const OptProblemSettings& optSett, const Data::Area& area); void buildUnitPowerOutputVariables(const OptProblemSettings& optSett, - int day, - const Data::Area& area); - void buildUnitPowerOutputVariables(const OptProblemSettings& optSett, - int day, const Data::ThermalCluster& cluster); + void buildUnitPowerOutputVariables(const OptProblemSettings& optSett, + const Data::ThermalCluster& cluster, + int day); void buildStartEndMntVariables(const OptProblemSettings& optSett); void buildStartEndMntVariables(const OptProblemSettings& optSett, int day); void buildStartEndMntVariables(const OptProblemSettings& optSett, From 603185cf662cb02808e1dec0cdc10f8c6c24e7ff Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Thu, 23 Nov 2023 09:48:29 +0100 Subject: [PATCH 155/315] clean-refactor --- .../optimized-thermal-generator/OptimizedGenerator.h | 1 - .../optimized-thermal-generator/SetVariableBounds.cpp | 5 ----- .../ts-generator/optimized-thermal-generator/SolveProbem.cpp | 2 +- 3 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 524f424d4b..41c23c96e3 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -57,7 +57,6 @@ class OptimizedThermalGenerator : public GeneratorTempData int totalMntNumber); // functions to fix bounds of some variables - void fixVariableBounds(); void fixBounds(); void fixBounds(const Data::Area& area); void fixBounds(const Data::ThermalCluster& cluster); diff --git a/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp b/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp index 15df0d20ba..8273467228 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp @@ -6,11 +6,6 @@ namespace Antares::Solver::TSGenerator { -void OptimizedThermalGenerator::fixVariableBounds() -{ - fixBounds(); - printAllVariables(); -} // TODO CR27: see if to make this bound or constraint - // it is definitely easier to do set it as a fix bound - diff --git a/src/solver/ts-generator/optimized-thermal-generator/SolveProbem.cpp b/src/solver/ts-generator/optimized-thermal-generator/SolveProbem.cpp index 447341c9d9..117c4235d1 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/SolveProbem.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/SolveProbem.cpp @@ -12,7 +12,7 @@ bool OptimizedThermalGenerator::runOptimizationProblem(OptProblemSettings& optSe resetProblem(); reCalculateDaysSinceLastMnt(optSett); buildProblemVariables(optSett); - fixVariableBounds(); + fixBounds(); buildProblemConstraints(); setProblemCost(optSett); if (!solveProblem(optSett)) From 87b773c3515838f59edc04d5494f04c920822725 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Thu, 23 Nov 2023 10:12:09 +0100 Subject: [PATCH 156/315] refactor build start/end vars - all days first --- .../CreateVariables.cpp | 45 ++++++++++++------- .../OptimizedGenerator.h | 15 ++++--- 2 files changed, 37 insertions(+), 23 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp b/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp index fb118d7519..7c7e552616 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp @@ -206,28 +206,16 @@ void OptimizedThermalGenerator::buildUnitPowerOutputVariables(const OptProblemSe // create VARIABLES per day, per cluster-unit and per maintenance - s[t][u][m] & e[t][u][m] void OptimizedThermalGenerator::buildStartEndMntVariables(const OptProblemSettings& optSett) -{ - // loop per day - for (int day = 0; day < timeHorizon_; ++day) - { - buildStartEndMntVariables(optSett, day); - } - return; -} - -void OptimizedThermalGenerator::buildStartEndMntVariables(const OptProblemSettings& optSett, - int day) { // loop per areas inside maintenance group for (const auto& entryWeightMap : maintenanceGroup_) { const auto& area = *(entryWeightMap.first); - buildStartEndMntVariables(optSett, day, area); + buildStartEndMntVariables(optSett, area); } } void OptimizedThermalGenerator::buildStartEndMntVariables(const OptProblemSettings& optSett, - int day, const Data ::Area& area) { // loop per thermal clusters inside the area @@ -243,12 +231,11 @@ void OptimizedThermalGenerator::buildStartEndMntVariables(const OptProblemSettin if (!createStartEndVar) continue; - buildStartEndMntVariables(optSett, day, cluster); + buildStartEndMntVariables(optSett, cluster); } } void OptimizedThermalGenerator::buildStartEndMntVariables(const OptProblemSettings& optSett, - int day, const Data ::ThermalCluster& cluster) { int totalMntNumber = getNumberOfMaintenances(cluster); @@ -256,18 +243,30 @@ void OptimizedThermalGenerator::buildStartEndMntVariables(const OptProblemSettin // loop per units inside the cluster for (int unit = 0; unit < cluster.unitCount; ++unit) { - buildStartEndMntVariables(optSett, day, cluster, unit, totalMntNumber); + buildStartEndMntVariables(optSett, cluster, unit, totalMntNumber); } } void OptimizedThermalGenerator::buildStartEndMntVariables(const OptProblemSettings& optSett, - int day, const Data ::ThermalCluster& cluster, int unit, int totalMntNumber) { // loop per maintenances per unit for (int mnt = 0; mnt < totalMntNumber; ++mnt) + { + buildStartVariables(optSett, cluster, unit, mnt); + buildEndVariables(optSett, cluster, unit, mnt); + } +} + +void OptimizedThermalGenerator::buildStartVariables(const OptProblemSettings& optSett, + const Data ::ThermalCluster& cluster, + int unit, + int mnt) +{ + // loop per day + for (int day = 0; day < timeHorizon_; ++day) { // add start[t][u][m] variables var.day[day].areaMap[cluster.parentArea].clusterMap[&cluster].unitMap[unit].start.push_back( @@ -276,7 +275,18 @@ void OptimizedThermalGenerator::buildStartEndMntVariables(const OptProblemSettin "S_[" + std::to_string(day + optSett.firstDay) + "][" + cluster.getFullName().to() + "." + std::to_string(unit) + "][" + std::to_string(mnt) + "]")); + } + return; +} +void OptimizedThermalGenerator::buildEndVariables(const OptProblemSettings& optSett, + const Data ::ThermalCluster& cluster, + int unit, + int mnt) +{ + // loop per day + for (int day = 0; day < timeHorizon_; ++day) + { // add end[t][u][m] variables var.day[day].areaMap[cluster.parentArea].clusterMap[&cluster].unitMap[unit].end.push_back( solver.MakeIntVar(0.0, @@ -285,6 +295,7 @@ void OptimizedThermalGenerator::buildStartEndMntVariables(const OptProblemSettin + cluster.getFullName().to() + "." + std::to_string(unit) + "][" + std::to_string(mnt) + "]")); } + return; } void OptimizedThermalGenerator::printAllVariables() diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 41c23c96e3..6924e737bb 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -43,18 +43,21 @@ class OptimizedThermalGenerator : public GeneratorTempData const Data::ThermalCluster& cluster, int day); void buildStartEndMntVariables(const OptProblemSettings& optSett); - void buildStartEndMntVariables(const OptProblemSettings& optSett, int day); + void buildStartEndMntVariables(const OptProblemSettings& optSett, const Data ::Area& area); void buildStartEndMntVariables(const OptProblemSettings& optSett, - int day, - const Data ::Area& area); - void buildStartEndMntVariables(const OptProblemSettings& optSett, - int day, const Data ::ThermalCluster& cluster); void buildStartEndMntVariables(const OptProblemSettings& optSett, - int day, const Data ::ThermalCluster& cluster, int unit, int totalMntNumber); + void buildStartVariables(const OptProblemSettings& optSett, + const Data ::ThermalCluster& cluster, + int unit, + int mnt); + void buildEndVariables(const OptProblemSettings& optSett, + const Data ::ThermalCluster& cluster, + int unit, + int mnt); // functions to fix bounds of some variables void fixBounds(); From 2dc9f4c862981432de593eecbb035bd0a574982b Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Thu, 23 Nov 2023 12:01:31 +0100 Subject: [PATCH 157/315] setLoadBalanceConstraints + print --- .../OptimizedGenerator.h | 12 +- .../SetProblemConstraints.cpp | 103 +++++++++++++++++- .../SolveProbem.cpp | 2 +- 3 files changed, 111 insertions(+), 6 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 6924e737bb..6acecf9083 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -75,8 +75,15 @@ class OptimizedThermalGenerator : public GeneratorTempData int avrMntDuration); // functions to build problem constraints - void buildProblemConstraints(); - void buildLoadBalanceConstraints(); + void buildProblemConstraints(const OptProblemSettings& optSett); + void setLoadBalanceConstraints(const OptProblemSettings& optSett); + void setLoadBalanceConstraints(const OptProblemSettings& optSett, int& day); + void insertEnsVars(MPConstraint* ct, int day); + void insertSpillVars(MPConstraint* ct, int day); + void insertPowerVars(MPConstraint* ct, int day); + void insertPowerVars(MPConstraint* ct, int day, const Data::Area& area); + void insertPowerVars(MPConstraint* ct, int day, const Data::ThermalCluster& cluster); + void insertPowerVars(MPConstraint* ct, int day, const Data::ThermalCluster& cluster, int unit); void setStartEndMntLogicConstraints(); void setMaxUnitOutputConstraints(); @@ -114,6 +121,7 @@ class OptimizedThermalGenerator : public GeneratorTempData // print functions for debugging void printAllVariables(); // for debug purpose only! void printObjectiveFunction(MPObjective* objective); + void printConstraints(); // Functions called in main method: void allocateWhereToWriteTs(); diff --git a/src/solver/ts-generator/optimized-thermal-generator/SetProblemConstraints.cpp b/src/solver/ts-generator/optimized-thermal-generator/SetProblemConstraints.cpp index 7c09f6c45b..1199579c0c 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/SetProblemConstraints.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/SetProblemConstraints.cpp @@ -6,19 +6,95 @@ namespace Antares::Solver::TSGenerator { -void OptimizedThermalGenerator::buildProblemConstraints() +void OptimizedThermalGenerator::buildProblemConstraints(const OptProblemSettings& optSett) { - buildLoadBalanceConstraints(); + setLoadBalanceConstraints(optSett); setStartEndMntLogicConstraints(); setMaxUnitOutputConstraints(); + printConstraints(); } // load balance CONSTRAINTS - constraint-per-each-day[t] - we have sum through [u] inside of it -void OptimizedThermalGenerator::buildLoadBalanceConstraints() +void OptimizedThermalGenerator::setLoadBalanceConstraints(const OptProblemSettings& optSett) { + // Define constraints + for (int day = 0; day < timeHorizon_; ++day) + { + setLoadBalanceConstraints(optSett, day); + } return; } +void OptimizedThermalGenerator::setLoadBalanceConstraints(const OptProblemSettings& optSett, + int& day) +{ + int optimizationDay = day + optSett.firstDay; + std::string ctName = "LoadBalanceConstraintDay_" + std::to_string(optimizationDay); + double equalTo = getResidualLoad(optimizationDay); + MPConstraint* ct = solver.MakeRowConstraint(equalTo, equalTo, ctName); + + insertPowerVars(ct, day); + insertEnsVars(ct, day); + insertSpillVars(ct, day); + return; +} + +void OptimizedThermalGenerator::insertEnsVars(MPConstraint* ct, int day) +{ + ct->SetCoefficient(var.day[day].Ens, 1.0); +} + +void OptimizedThermalGenerator::insertSpillVars(MPConstraint* ct, int day) +{ + ct->SetCoefficient(var.day[day].Spill, -1.0); +} + +void OptimizedThermalGenerator::insertPowerVars(MPConstraint* ct, int day) +{ + // loop per areas inside maintenance group + for (const auto& entryWeightMap : maintenanceGroup_) + { + const auto& area = *(entryWeightMap.first); + insertPowerVars(ct, day, area); + } +} + +void OptimizedThermalGenerator::insertPowerVars(MPConstraint* ct, int day, const Data::Area& area) +{ + // loop per thermal clusters inside the area + for (auto it = area.thermal.list.mapping.begin(); it != area.thermal.list.mapping.end(); ++it) + { + const auto& cluster = *(it->second); + + // we do not check if cluster.optimizeMaintenance = true here + // we add all the clusters Power inside maintenance group + if (!checkClusterExist(cluster)) + continue; + + insertPowerVars(ct, day, cluster); + } +} + +void OptimizedThermalGenerator::insertPowerVars(MPConstraint* ct, + int day, + const Data::ThermalCluster& cluster) +{ + // loop per units inside the cluster + for (int unit = 0; unit < cluster.unitCount; ++unit) + { + insertPowerVars(ct, day, cluster, unit); + } +} + +void OptimizedThermalGenerator::insertPowerVars(MPConstraint* ct, + int day, + const Data::ThermalCluster& cluster, + int unit) +{ + ct->SetCoefficient( + var.day[day].areaMap[cluster.parentArea].clusterMap[&cluster].unitMap[unit].P, 1.0); +} + // CONSTRAINTS per days, per units and per maintenance - constraint-per-each-day+unit+mnt[t][u][m] void OptimizedThermalGenerator::setStartEndMntLogicConstraints() { @@ -30,4 +106,25 @@ void OptimizedThermalGenerator::setMaxUnitOutputConstraints() return; } +void OptimizedThermalGenerator::printConstraints() +{ + const int num_constraints = solver.NumConstraints(); + + for (int i = 0; i < num_constraints; ++i) + { + const MPConstraint* const constraint = solver.constraint(i); + std::cout << "**** Constraint " << i + 1 << " ****" << std::endl; + std::cout << "Lower Bound: " << constraint->lb() << std::endl; + std::cout << "Upper Bound: " << constraint->ub() << std::endl; + + for (const auto& term : constraint->terms()) + { + const MPVariable* const var = term.first; + const double coefficient = term.second; + std::cout << var->name() << ": " << coefficient << std::endl; + } + std::cout << "------------------------" << std::endl; + } +} + } // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/SolveProbem.cpp b/src/solver/ts-generator/optimized-thermal-generator/SolveProbem.cpp index 117c4235d1..da5164ecdb 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/SolveProbem.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/SolveProbem.cpp @@ -13,7 +13,7 @@ bool OptimizedThermalGenerator::runOptimizationProblem(OptProblemSettings& optSe reCalculateDaysSinceLastMnt(optSett); buildProblemVariables(optSett); fixBounds(); - buildProblemConstraints(); + buildProblemConstraints(optSett); setProblemCost(optSett); if (!solveProblem(optSett)) return false; From 35be8fdb50aa1d90ef907621229f52e9f4ae0d18 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Thu, 23 Nov 2023 12:03:47 +0100 Subject: [PATCH 158/315] improve debug printing constraints --- .../optimized-thermal-generator/SetProblemConstraints.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/solver/ts-generator/optimized-thermal-generator/SetProblemConstraints.cpp b/src/solver/ts-generator/optimized-thermal-generator/SetProblemConstraints.cpp index 1199579c0c..caefb34356 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/SetProblemConstraints.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/SetProblemConstraints.cpp @@ -114,6 +114,7 @@ void OptimizedThermalGenerator::printConstraints() { const MPConstraint* const constraint = solver.constraint(i); std::cout << "**** Constraint " << i + 1 << " ****" << std::endl; + std::cout << "Name: " << constraint->name() << std::endl; std::cout << "Lower Bound: " << constraint->lb() << std::endl; std::cout << "Upper Bound: " << constraint->ub() << std::endl; From b62d1437e37796c2a18742d6eb3d2bf63d47c478 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Thu, 23 Nov 2023 12:45:50 +0100 Subject: [PATCH 159/315] deltaSolver for <= & >= constraints --- .../optimized-thermal-generator/OptimizedGenerator.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 6acecf9083..700c17e88e 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -12,6 +12,7 @@ // static const std::string mntPlSolverName = "cbc"; static const int minNumberOfMaintenances = 2; +static const double deltaSolver = 10e-3; using namespace operations_research; From ac54c53e0dec99aa12b4dcd01d6283d0bd2df190 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Thu, 23 Nov 2023 13:37:27 +0100 Subject: [PATCH 160/315] setMaxUnitOutputConstraints - tested --- .../OptimizedGenerator.h | 24 +++- .../SetProblemConstraints.cpp | 108 +++++++++++++++++- 2 files changed, 125 insertions(+), 7 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 700c17e88e..9d9f30ccb5 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -86,7 +86,29 @@ class OptimizedThermalGenerator : public GeneratorTempData void insertPowerVars(MPConstraint* ct, int day, const Data::ThermalCluster& cluster); void insertPowerVars(MPConstraint* ct, int day, const Data::ThermalCluster& cluster, int unit); void setStartEndMntLogicConstraints(); - void setMaxUnitOutputConstraints(); + void setMaxUnitOutputConstraints(const OptProblemSettings& optSett); + void setMaxUnitOutputConstraints(const OptProblemSettings& optSett, int& day); + void setMaxUnitOutputConstraints(const OptProblemSettings& optSett, + int day, + const Data::Area& area); + void setMaxUnitOutputConstraints(const OptProblemSettings& optSett, + int day, + const Data::ThermalCluster& cluster); + void setMaxUnitOutputConstraints(const OptProblemSettings& optSett, + int day, + const Data::ThermalCluster& cluster, + int unit, + double maxOutput); + void insertStartSum(MPConstraint* ct, + int day, + const Data::ThermalCluster& cluster, + int unit, + double maxPower); + void insertEndSum(MPConstraint* ct, + int day, + const Data::ThermalCluster& cluster, + int unit, + double maxPower); // functions to set problem objective function void setProblemCost(const OptProblemSettings& optSett); diff --git a/src/solver/ts-generator/optimized-thermal-generator/SetProblemConstraints.cpp b/src/solver/ts-generator/optimized-thermal-generator/SetProblemConstraints.cpp index caefb34356..f52eae4c5c 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/SetProblemConstraints.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/SetProblemConstraints.cpp @@ -10,14 +10,13 @@ void OptimizedThermalGenerator::buildProblemConstraints(const OptProblemSettings { setLoadBalanceConstraints(optSett); setStartEndMntLogicConstraints(); - setMaxUnitOutputConstraints(); + setMaxUnitOutputConstraints(optSett); printConstraints(); } // load balance CONSTRAINTS - constraint-per-each-day[t] - we have sum through [u] inside of it void OptimizedThermalGenerator::setLoadBalanceConstraints(const OptProblemSettings& optSett) { - // Define constraints for (int day = 0; day < timeHorizon_; ++day) { setLoadBalanceConstraints(optSett, day); @@ -29,7 +28,7 @@ void OptimizedThermalGenerator::setLoadBalanceConstraints(const OptProblemSettin int& day) { int optimizationDay = day + optSett.firstDay; - std::string ctName = "LoadBalanceConstraintDay_" + std::to_string(optimizationDay); + std::string ctName = "LoadBalanceConstraint[" + std::to_string(optimizationDay) + "]"; double equalTo = getResidualLoad(optimizationDay); MPConstraint* ct = solver.MakeRowConstraint(equalTo, equalTo, ctName); @@ -62,9 +61,9 @@ void OptimizedThermalGenerator::insertPowerVars(MPConstraint* ct, int day) void OptimizedThermalGenerator::insertPowerVars(MPConstraint* ct, int day, const Data::Area& area) { // loop per thermal clusters inside the area - for (auto it = area.thermal.list.mapping.begin(); it != area.thermal.list.mapping.end(); ++it) + for (const auto& clusterEntry : area.thermal.list.mapping) { - const auto& cluster = *(it->second); + const auto& cluster = *(clusterEntry.second); // we do not check if cluster.optimizeMaintenance = true here // we add all the clusters Power inside maintenance group @@ -100,12 +99,109 @@ void OptimizedThermalGenerator::setStartEndMntLogicConstraints() { return; } + +// Maximum outputs of the units // CONSTRAINTS per days and per units - constraint-per-each-day+unit[t][u][m-sum per m] -void OptimizedThermalGenerator::setMaxUnitOutputConstraints() +void OptimizedThermalGenerator::setMaxUnitOutputConstraints(const OptProblemSettings& optSett) { + for (int day = 0; day < timeHorizon_; ++day) + { + setMaxUnitOutputConstraints(optSett, day); + } return; } +void OptimizedThermalGenerator::setMaxUnitOutputConstraints(const OptProblemSettings& optSett, + int& day) +{ + // loop per areas inside maintenance group + for (const auto& entryWeightMap : maintenanceGroup_) + { + const auto& area = *(entryWeightMap.first); + setMaxUnitOutputConstraints(optSett, day, area); + } +} + +void OptimizedThermalGenerator::setMaxUnitOutputConstraints(const OptProblemSettings& optSett, + int day, + const Data::Area& area) +{ + // loop per thermal clusters inside the area + for (const auto& clusterEntry : area.thermal.list.mapping) + { + const auto& cluster = *(clusterEntry.second); + + // we do not check if cluster.optimizeMaintenance = true here + // we add all the clusters Power inside maintenance group + if (!checkClusterExist(cluster)) + continue; + + setMaxUnitOutputConstraints(optSett, day, cluster); + } +} + +void OptimizedThermalGenerator::setMaxUnitOutputConstraints(const OptProblemSettings& optSett, + int day, + const Data::ThermalCluster& cluster) +{ + int optimizationDay = day + optSett.firstDay; + double maxPower = getPowerOutput(cluster, optimizationDay); + // loop per units inside the cluster + for (int unit = 0; unit < cluster.unitCount; ++unit) + { + setMaxUnitOutputConstraints(optSett, day, cluster, unit, maxPower); + } +} + +void OptimizedThermalGenerator::setMaxUnitOutputConstraints(const OptProblemSettings& optSett, + int day, + const Data::ThermalCluster& cluster, + int unit, + double maxPower) +{ + int optimizationDay = day + optSett.firstDay; + std::string ctName = "MaxPowerOutputConstraint[" + std::to_string(optimizationDay) + "][" + + cluster.getFullName().to() + "." + std::to_string(unit) + + "]"; + MPConstraint* ct = solver.MakeRowConstraint(0.0 - deltaSolver, maxPower + deltaSolver, ctName); + + insertPowerVars(ct, day, cluster, unit); // re-using this method on purpose! + insertStartSum(ct, day, cluster, unit, maxPower); + insertEndSum(ct, day, cluster, unit, maxPower); +} + +void OptimizedThermalGenerator::insertStartSum(MPConstraint* ct, + int day, + const Data::ThermalCluster& cluster, + int unit, + double maxPower) +{ + int totalMntNumber = getNumberOfMaintenances(cluster); + // loop per maintenances per unit + for (int mnt = 0; mnt < totalMntNumber; ++mnt) + { + ct->SetCoefficient( + var.day[day].areaMap[cluster.parentArea].clusterMap[&cluster].unitMap[unit].start[mnt], + maxPower); + } +} + +void OptimizedThermalGenerator::insertEndSum(MPConstraint* ct, + int day, + const Data::ThermalCluster& cluster, + int unit, + double maxPower) +{ + int totalMntNumber = getNumberOfMaintenances(cluster); + // loop per maintenances per unit + for (int mnt = 0; mnt < totalMntNumber; ++mnt) + { + ct->SetCoefficient( + var.day[day].areaMap[cluster.parentArea].clusterMap[&cluster].unitMap[unit].end[mnt], + -maxPower); + } +} + void OptimizedThermalGenerator::printConstraints() { const int num_constraints = solver.NumConstraints(); From 7f9497c96a1888ff9497aefb10455a222a20f2dc Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Thu, 23 Nov 2023 14:22:24 +0100 Subject: [PATCH 161/315] adjust max output constraint if cluster/unit is not in maintenance just do 0 Date: Thu, 23 Nov 2023 14:29:22 +0100 Subject: [PATCH 162/315] fix comments --- .../optimized-thermal-generator/SetProblemConstraints.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/solver/ts-generator/optimized-thermal-generator/SetProblemConstraints.cpp b/src/solver/ts-generator/optimized-thermal-generator/SetProblemConstraints.cpp index affd04e304..5975db4752 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/SetProblemConstraints.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/SetProblemConstraints.cpp @@ -171,6 +171,7 @@ void OptimizedThermalGenerator::setMaxUnitOutputConstraints(const OptProblemSett // we add sum[per-q](s[t][u][q]-e[t][u][q]) // only if we have defined variables start and end for the units + // if not we ebd up with: 0 <= P <= Pmax // note we already passed check: !checkClusterExist(cluster) // so here we just check if the cluster is involved in maintenance planing if (!(cluster.doWeGenerateTS(globalThermalTSgeneration_) && cluster.optimizeMaintenance)) From 76c18c3c3c75c39fa2c49e5e301c9357b2bc507d Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Thu, 23 Nov 2023 15:02:36 +0100 Subject: [PATCH 163/315] maybe idea for refactoring phase-II --- .../optimized-thermal-generator/AuxillaryStructures.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h index 0a9abd5198..d54ba8d869 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h +++ b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h @@ -24,6 +24,14 @@ class OptProblemSettings final bool solved = true; }; +// TODO CR27: +// maybe for refactoring create a vector of structs called units +// each unit struct will contain pointer to area/cluster/int unitIndex/ bool createStartEnd +// pointer to var P*, vector of pointers to var start<*> & end<*> +// then loop just through that vector + loop per time step +// not loop nesting into day-area-cluster-unit +// maybe better ?@! + struct OptimizationProblemVariablesPerUnit { MPVariable* P = nullptr;; // pointer to P[t][u] variable From 42725811d3070033cc10b302eab6872b52a5a3b6 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Thu, 23 Nov 2023 17:05:51 +0100 Subject: [PATCH 164/315] setStartEndMntLogicConstraints - tested one by one - works - solver wont find results! --- .../CreateVariables.cpp | 8 +- .../OptimizedGenerator.h | 33 +++- .../SetProblemConstraints.cpp | 175 +++++++++++++++++- 3 files changed, 205 insertions(+), 11 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp b/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp index 7c7e552616..48fea2148c 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp @@ -40,7 +40,7 @@ void OptimizedThermalGenerator::countVariables() x->SetLB(1.5); // Define constraints - MPConstraint* const ct = solver.MakeRowConstraint(12.0, infinity, "ct"); + MPConstraint* const ct = solver.MakeRowConstraint(12.0, solverInfinity, "ct"); ct->SetCoefficient(x, 1.5); ct->SetCoefficient(y, 2.0); @@ -134,14 +134,14 @@ void OptimizedThermalGenerator::buildEnsAndSpillageVariables(const OptProblemSet { // add ENS variables var.day[day].Ens = solver.MakeNumVar( - 0.0, infinity, "ENS_[" + std::to_string(day + optSett.firstDay) + "]"); + 0.0, solverInfinity, "ENS_[" + std::to_string(day + optSett.firstDay) + "]"); } for (int day = 0; day < timeHorizon_; ++day) { // add Spillage variables var.day[day].Spill = solver.MakeNumVar( - 0.0, infinity, "Spill_[" + std::to_string(day + optSett.firstDay) + "]"); + 0.0, solverInfinity, "Spill_[" + std::to_string(day + optSett.firstDay) + "]"); } return; @@ -195,7 +195,7 @@ void OptimizedThermalGenerator::buildUnitPowerOutputVariables(const OptProblemSe // add P[t][u] variables var.day[day].areaMap[cluster.parentArea].clusterMap[&cluster].unitMap[unit].P = solver.MakeNumVar(0.0, - infinity, + solverInfinity, "P_[" + std::to_string(day + optSett.firstDay) + "][" + cluster.getFullName().to() + "." + std::to_string(unit) + "]"); diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 9d9f30ccb5..497610aab8 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -12,7 +12,7 @@ // static const std::string mntPlSolverName = "cbc"; static const int minNumberOfMaintenances = 2; -static const double deltaSolver = 10e-3; +static const double solverDelta = 10e-4; using namespace operations_research; @@ -85,7 +85,32 @@ class OptimizedThermalGenerator : public GeneratorTempData void insertPowerVars(MPConstraint* ct, int day, const Data::Area& area); void insertPowerVars(MPConstraint* ct, int day, const Data::ThermalCluster& cluster); void insertPowerVars(MPConstraint* ct, int day, const Data::ThermalCluster& cluster, int unit); - void setStartEndMntLogicConstraints(); + void setStartEndMntLogicConstraints(const OptProblemSettings& optSett); + void setStartEndMntLogicConstraints(const OptProblemSettings& optSett, const Data::Area& area); + void setStartEndMntLogicConstraints(const OptProblemSettings& optSett, + const Data::ThermalCluster& cluster); + void setStartEndMntLogicConstraints(const OptProblemSettings& optSett, + const Data::ThermalCluster& cluster, + int unit); + void setEndOfMaintenanceEventBasedOnAverageDurationOfMaintenanceEvent( + const OptProblemSettings& optSett, + const Data::ThermalCluster& cluster, + int unit, + int mnt); + void setUpFollowingMaintenanceBasedOnAverageDurationBetweenMaintenanceEvents( + const OptProblemSettings& optSett, + const Data::ThermalCluster& cluster, + int unit, + int mnt); + void setOnceStartIsSetToOneItWillBeOneUntilEndOfOptimizationTimeHorizon( + const OptProblemSettings& optSett, + const Data::ThermalCluster& cluster, + int unit, + int mnt); + void setNextMaintenanceCanNotStartBeforePreviousMaintenance(const OptProblemSettings& optSett, + const Data::ThermalCluster& cluster, + int unit, + int mnt); void setMaxUnitOutputConstraints(const OptProblemSettings& optSett); void setMaxUnitOutputConstraints(const OptProblemSettings& optSett, int& day); void setMaxUnitOutputConstraints(const OptProblemSettings& optSett, @@ -211,7 +236,7 @@ class OptimizedThermalGenerator : public GeneratorTempData // MPSolver instance MPSolver solver; - double infinity; + double solverInfinity; public: explicit OptimizedThermalGenerator(Data::Study& study, @@ -241,7 +266,7 @@ class OptimizedThermalGenerator : public GeneratorTempData // params.SetIntegerParam(MPSolverParameters::PRESOLVE, 0); // set solver infinity - infinity = solver.infinity(); + solverInfinity = solver.infinity(); } ~OptimizedThermalGenerator() = default; diff --git a/src/solver/ts-generator/optimized-thermal-generator/SetProblemConstraints.cpp b/src/solver/ts-generator/optimized-thermal-generator/SetProblemConstraints.cpp index 5975db4752..0425377957 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/SetProblemConstraints.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/SetProblemConstraints.cpp @@ -9,7 +9,7 @@ namespace Antares::Solver::TSGenerator void OptimizedThermalGenerator::buildProblemConstraints(const OptProblemSettings& optSett) { setLoadBalanceConstraints(optSett); - setStartEndMntLogicConstraints(); + setStartEndMntLogicConstraints(optSett); setMaxUnitOutputConstraints(optSett); printConstraints(); } @@ -97,11 +97,180 @@ void OptimizedThermalGenerator::insertPowerVars(MPConstraint* ct, ////////////////////////////// // CONSTRAINTS per days, per units and per maintenance - constraint-per-each-day+unit+mnt[t][u][m] -void OptimizedThermalGenerator::setStartEndMntLogicConstraints() +void OptimizedThermalGenerator::setStartEndMntLogicConstraints(const OptProblemSettings& optSett) { + // loop per areas inside maintenance group + for (const auto& entryWeightMap : maintenanceGroup_) + { + const auto& area = *(entryWeightMap.first); + setStartEndMntLogicConstraints(optSett, area); + } +} + +void OptimizedThermalGenerator::setStartEndMntLogicConstraints(const OptProblemSettings& optSett, + const Data::Area& area) +{ + // loop per thermal clusters inside the area + for (const auto& clusterEntry : area.thermal.list.mapping) + { + const auto& cluster = *(clusterEntry.second); + + // check if cluster exist, do we generate + optimizeMaintenance + // create constraints only if start/end actually exist + bool createStartEndVar = checkClusterExist(cluster) + && cluster.doWeGenerateTS(globalThermalTSgeneration_) + && cluster.optimizeMaintenance; + if (!createStartEndVar) + continue; + + setStartEndMntLogicConstraints(optSett, cluster); + } +} + +void OptimizedThermalGenerator::setStartEndMntLogicConstraints(const OptProblemSettings& optSett, + const Data::ThermalCluster& cluster) +{ + // loop per units inside the cluster + for (int unit = 0; unit < cluster.unitCount; ++unit) + { + setStartEndMntLogicConstraints(optSett, cluster, unit); + } +} + +void OptimizedThermalGenerator::setStartEndMntLogicConstraints(const OptProblemSettings& optSett, + const Data::ThermalCluster& cluster, + int unit) +{ + int totalMntNumber = getNumberOfMaintenances(cluster); + // loop per maintenances per unit + for (int mnt = 0; mnt < totalMntNumber; ++mnt) + { + setEndOfMaintenanceEventBasedOnAverageDurationOfMaintenanceEvent( + optSett, cluster, unit, mnt); + setOnceStartIsSetToOneItWillBeOneUntilEndOfOptimizationTimeHorizon( + optSett, cluster, unit, mnt); + } + + // loop per maintenances per unit - except last one + for (int mnt = 0; mnt < totalMntNumber - 1; ++mnt) + { + setUpFollowingMaintenanceBasedOnAverageDurationBetweenMaintenanceEvents( + optSett, cluster, unit, mnt); + setNextMaintenanceCanNotStartBeforePreviousMaintenance(optSett, cluster, unit, mnt); + } +} + +void OptimizedThermalGenerator::setEndOfMaintenanceEventBasedOnAverageDurationOfMaintenanceEvent( + const OptProblemSettings& optSett, + const Data::ThermalCluster& cluster, + int unit, + int mnt) +{ + int averageMaintenanceDuration = getAverageMaintenanceDuration(cluster); + for (int day = 0; day < timeHorizon_ - averageMaintenanceDuration; ++day) + { + std::string ctName = "E[t+Mu][u][q] = S[t][u][q] -> [" + + std::to_string(day + optSett.firstDay) + "][" + + cluster.getFullName().to() + "." + std::to_string(unit) + + "][" + std::to_string(mnt) + "]"; + MPConstraint* ct = solver.MakeRowConstraint(0.0, 0.0, ctName); + + ct->SetCoefficient(var.day[day + averageMaintenanceDuration] + .areaMap[cluster.parentArea] + .clusterMap[&cluster] + .unitMap[unit] + .end[mnt], + 1.0); + ct->SetCoefficient( + var.day[day].areaMap[cluster.parentArea].clusterMap[&cluster].unitMap[unit].start[mnt], + -1.0); + } + return; +} + +void OptimizedThermalGenerator:: + setUpFollowingMaintenanceBasedOnAverageDurationBetweenMaintenanceEvents( + const OptProblemSettings& optSett, + const Data::ThermalCluster& cluster, + int unit, + int mnt) +{ + int averageDurationBetweenMaintenances = getAverageDurationBetweenMaintenances(cluster); + for (int day = 0; day < timeHorizon_ - averageDurationBetweenMaintenances; ++day) + { + std::string ctName = "S[t+Tu][u][q+1] = E[t][u][q] -> [" + + std::to_string(day + optSett.firstDay) + "][" + + cluster.getFullName().to() + "." + std::to_string(unit) + + "][" + std::to_string(mnt) + "]"; + MPConstraint* ct = solver.MakeRowConstraint(0.0, 0.0, ctName); + + ct->SetCoefficient(var.day[day + averageDurationBetweenMaintenances] + .areaMap[cluster.parentArea] + .clusterMap[&cluster] + .unitMap[unit] + .start[mnt + 1], + 1.0); + ct->SetCoefficient( + var.day[day].areaMap[cluster.parentArea].clusterMap[&cluster].unitMap[unit].end[mnt], + -1.0); + } + return; +} + +void OptimizedThermalGenerator::setOnceStartIsSetToOneItWillBeOneUntilEndOfOptimizationTimeHorizon( + const OptProblemSettings& optSett, + const Data::ThermalCluster& cluster, + int unit, + int mnt) +{ + for (int day = 0; day < timeHorizon_ - 1; ++day) + { + std::string ctName = "S[t+1][u][q] >= S[t][u][q] -> [" + + std::to_string(day + optSett.firstDay) + "][" + + cluster.getFullName().to() + "." + std::to_string(unit) + + "][" + std::to_string(mnt) + "]"; + MPConstraint* ct = solver.MakeRowConstraint(0.0 - solverDelta, solverInfinity, ctName); + + ct->SetCoefficient(var.day[day + 1] + .areaMap[cluster.parentArea] + .clusterMap[&cluster] + .unitMap[unit] + .start[mnt], + 1.0); + ct->SetCoefficient( + var.day[day].areaMap[cluster.parentArea].clusterMap[&cluster].unitMap[unit].start[mnt], + -1.0); + } + return; +} + +void OptimizedThermalGenerator::setNextMaintenanceCanNotStartBeforePreviousMaintenance( + const OptProblemSettings& optSett, + const Data::ThermalCluster& cluster, + int unit, + int mnt) +{ + for (int day = 0; day < timeHorizon_; ++day) + { + std::string ctName = "S[t][u][q] >= S[t][u][q+1] -> [" + + std::to_string(day + optSett.firstDay) + "][" + + cluster.getFullName().to() + "." + std::to_string(unit) + + "][" + std::to_string(mnt) + "]"; + MPConstraint* ct = solver.MakeRowConstraint(0.0 - solverDelta, solverInfinity, ctName); + + ct->SetCoefficient( + var.day[day].areaMap[cluster.parentArea].clusterMap[&cluster].unitMap[unit].start[mnt], + 1.0); + ct->SetCoefficient( + var.day[day].areaMap[cluster.parentArea].clusterMap[&cluster].unitMap[unit].start[mnt + + 1], + -1.0); + } return; } +////////////////////////////// + // Maximum outputs of the units // CONSTRAINTS per days and per units - constraint-per-each-day+unit[t][u][m-sum per m] void OptimizedThermalGenerator::setMaxUnitOutputConstraints(const OptProblemSettings& optSett) @@ -165,7 +334,7 @@ void OptimizedThermalGenerator::setMaxUnitOutputConstraints(const OptProblemSett std::string ctName = "MaxPowerOutputConstraint[" + std::to_string(optimizationDay) + "][" + cluster.getFullName().to() + "." + std::to_string(unit) + "]"; - MPConstraint* ct = solver.MakeRowConstraint(0.0 - deltaSolver, maxPower + deltaSolver, ctName); + MPConstraint* ct = solver.MakeRowConstraint(0.0 - solverDelta, maxPower + solverDelta, ctName); insertPowerVars(ct, day, cluster, unit); // re-using this method on purpose! From 464632d38f46115cbcae50979085e2b71c5d48c0 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Fri, 24 Nov 2023 08:16:11 +0100 Subject: [PATCH 165/315] clean + comments --- .../optimized-thermal-generator/CreateVariables.cpp | 1 - .../optimized-thermal-generator/SetProblemConstraints.cpp | 1 - .../optimized-thermal-generator/SetVariableBounds.cpp | 4 ++-- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp b/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp index 48fea2148c..877c0dd9bf 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp @@ -15,7 +15,6 @@ void OptimizedThermalGenerator::buildProblemVariables(const OptProblemSettings& buildEnsAndSpillageVariables(optSett); buildUnitPowerOutputVariables(optSett); buildStartEndMntVariables(optSett); - printAllVariables(); } void OptimizedThermalGenerator::countVariables() diff --git a/src/solver/ts-generator/optimized-thermal-generator/SetProblemConstraints.cpp b/src/solver/ts-generator/optimized-thermal-generator/SetProblemConstraints.cpp index 0425377957..3040f59892 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/SetProblemConstraints.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/SetProblemConstraints.cpp @@ -11,7 +11,6 @@ void OptimizedThermalGenerator::buildProblemConstraints(const OptProblemSettings setLoadBalanceConstraints(optSett); setStartEndMntLogicConstraints(optSett); setMaxUnitOutputConstraints(optSett); - printConstraints(); } // load balance CONSTRAINTS - constraint-per-each-day[t] - we have sum through [u] inside of it diff --git a/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp b/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp index 8273467228..32eac14253 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp @@ -79,7 +79,7 @@ void OptimizedThermalGenerator::fixBoundsFirstMnt(const Data::ThermalCluster& cl .clusterMap[&cluster] .unitMap[unit] .start[0] - ->SetBounds(0.0, 0.0); + ->SetBounds(0.0, 0.0); //inclusive range } // start[tauUpper][u][1] = 1 @@ -88,7 +88,7 @@ void OptimizedThermalGenerator::fixBoundsFirstMnt(const Data::ThermalCluster& cl .clusterMap[&cluster] .unitMap[unit] .start[0] - ->SetBounds(1.0, 1.0); + ->SetBounds(1.0, 1.0); //inclusive range return; } From 3bff790c46422dd91514c9755949b8e0d1e87950 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Fri, 24 Nov 2023 08:46:11 +0100 Subject: [PATCH 166/315] clean/refactor - move all print to separate file --- src/solver/ts-generator/CMakeLists.txt | 1 + .../CreateVariables.cpp | 14 ----- .../OptimizedGenerator.h | 3 +- .../PrintProblemVarRes.cpp | 62 +++++++++++++++++++ .../SetProblemConstraints.cpp | 22 ------- .../SetProblemCost.cpp | 12 ---- .../SolveProbem.cpp | 1 + 7 files changed, 66 insertions(+), 49 deletions(-) create mode 100644 src/solver/ts-generator/optimized-thermal-generator/PrintProblemVarRes.cpp diff --git a/src/solver/ts-generator/CMakeLists.txt b/src/solver/ts-generator/CMakeLists.txt index 2fe4ab8a1e..4c0fa390fd 100644 --- a/src/solver/ts-generator/CMakeLists.txt +++ b/src/solver/ts-generator/CMakeLists.txt @@ -25,6 +25,7 @@ set(SRC_OPTIMIZEDGENERATORS optimized-thermal-generator/SetProblemCost.cpp optimized-thermal-generator/ResetProblem.cpp optimized-thermal-generator/SolveProbem.cpp + optimized-thermal-generator/PrintProblemVarRes.cpp ) source_group("ts-generator\\optimized-thermal-generator" FILES ${SRC_OPTIMIZEDGENERATORS}) diff --git a/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp b/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp index 877c0dd9bf..1bdab78275 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp @@ -297,18 +297,4 @@ void OptimizedThermalGenerator::buildEndVariables(const OptProblemSettings& optS return; } -void OptimizedThermalGenerator::printAllVariables() -{ - for (MPVariable* const variable : solver.variables()) - { - std::cout << "Variable: " << variable->name() << ", " - << "Lower bound: " << variable->lb() << ", " - << "Upper bound: " << variable->ub() << std::endl; - } - - std::cout << "total number of variables is: " << solver.NumVariables() << std::endl; - - return; -} - } // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 497610aab8..5265fdfbcc 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -167,9 +167,10 @@ class OptimizedThermalGenerator : public GeneratorTempData void appendStepResults(); // print functions for debugging - void printAllVariables(); // for debug purpose only! + void printAllVariables(); void printObjectiveFunction(MPObjective* objective); void printConstraints(); + void printProblemVarAndResults(); // Functions called in main method: void allocateWhereToWriteTs(); diff --git a/src/solver/ts-generator/optimized-thermal-generator/PrintProblemVarRes.cpp b/src/solver/ts-generator/optimized-thermal-generator/PrintProblemVarRes.cpp new file mode 100644 index 0000000000..5330c2a612 --- /dev/null +++ b/src/solver/ts-generator/optimized-thermal-generator/PrintProblemVarRes.cpp @@ -0,0 +1,62 @@ +// +// Created by milos on 14/11/23. +// + +#include "OptimizedGenerator.h" + +namespace Antares::Solver::TSGenerator +{ +void OptimizedThermalGenerator::printProblemVarAndResults() +{ + printAllVariables(); + printConstraints(); + printObjectiveFunction(solver.MutableObjective()); +} + +void OptimizedThermalGenerator::printAllVariables() +{ + for (MPVariable* const variable : solver.variables()) + { + std::cout << "Variable: " << variable->name() << ", " + << "Lower bound: " << variable->lb() << ", " + << "Upper bound: " << variable->ub() << std::endl; + } + + std::cout << "total number of variables is: " << solver.NumVariables() << std::endl; + + return; +} + +void OptimizedThermalGenerator::printConstraints() +{ + const int num_constraints = solver.NumConstraints(); + + for (int i = 0; i < num_constraints; ++i) + { + const MPConstraint* const constraint = solver.constraint(i); + std::cout << "**** Constraint " << i + 1 << " ****" << std::endl; + std::cout << "Name: " << constraint->name() << std::endl; + std::cout << "Lower Bound: " << constraint->lb() << std::endl; + std::cout << "Upper Bound: " << constraint->ub() << std::endl; + + for (const auto& term : constraint->terms()) + { + const MPVariable* const var = term.first; + const double coefficient = term.second; + std::cout << var->name() << ": " << coefficient << std::endl; + } + std::cout << "------------------------" << std::endl; + } +} + +void OptimizedThermalGenerator::printObjectiveFunction(MPObjective* objective) +{ + for (MPVariable* variable : solver.variables()) + { + std::cout << variable->name() << ": " << objective->GetCoefficient(variable) << std::endl; + } + std::cout << std::endl; + return; +} + +} // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/SetProblemConstraints.cpp b/src/solver/ts-generator/optimized-thermal-generator/SetProblemConstraints.cpp index 3040f59892..4fa1a6247a 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/SetProblemConstraints.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/SetProblemConstraints.cpp @@ -381,26 +381,4 @@ void OptimizedThermalGenerator::insertEndSum(MPConstraint* ct, } } -void OptimizedThermalGenerator::printConstraints() -{ - const int num_constraints = solver.NumConstraints(); - - for (int i = 0; i < num_constraints; ++i) - { - const MPConstraint* const constraint = solver.constraint(i); - std::cout << "**** Constraint " << i + 1 << " ****" << std::endl; - std::cout << "Name: " << constraint->name() << std::endl; - std::cout << "Lower Bound: " << constraint->lb() << std::endl; - std::cout << "Upper Bound: " << constraint->ub() << std::endl; - - for (const auto& term : constraint->terms()) - { - const MPVariable* const var = term.first; - const double coefficient = term.second; - std::cout << var->name() << ": " << coefficient << std::endl; - } - std::cout << "------------------------" << std::endl; - } -} - } // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp b/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp index d3e6b0cd46..6b33fc802c 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp @@ -18,8 +18,6 @@ void OptimizedThermalGenerator::setProblemCost(const OptProblemSettings& optSett objective->SetMinimization(); - printObjectiveFunction(objective); - return; } @@ -114,14 +112,4 @@ void OptimizedThermalGenerator::setProblemPowerCost(MPObjective* objective, return; } -void OptimizedThermalGenerator::printObjectiveFunction(MPObjective* objective) -{ - for (MPVariable* variable : solver.variables()) - { - std::cout << variable->name() << ": " << objective->GetCoefficient(variable) << std::endl; - } - std::cout << std::endl; - return; -} - } // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/SolveProbem.cpp b/src/solver/ts-generator/optimized-thermal-generator/SolveProbem.cpp index da5164ecdb..0d9bcad97b 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/SolveProbem.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/SolveProbem.cpp @@ -17,6 +17,7 @@ bool OptimizedThermalGenerator::runOptimizationProblem(OptProblemSettings& optSe setProblemCost(optSett); if (!solveProblem(optSett)) return false; + printProblemVarAndResults(); appendStepResults(); return true; } From 7e4253b67d04c945903f9d5cd14eb04c19709474 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Fri, 24 Nov 2023 08:59:55 +0100 Subject: [PATCH 167/315] clean --- .../CreateVariables.cpp | 60 ------------------- .../OptimizedGenerator.h | 4 +- 2 files changed, 1 insertion(+), 63 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp b/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp index 1bdab78275..8c5045d553 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp @@ -8,72 +8,12 @@ namespace Antares::Solver::TSGenerator { void OptimizedThermalGenerator::buildProblemVariables(const OptProblemSettings& optSett) { - // this is now just dummy optimization problem - countVariables(); - allocateVarStruct(); buildEnsAndSpillageVariables(optSett); buildUnitPowerOutputVariables(optSett); buildStartEndMntVariables(optSett); } -void OptimizedThermalGenerator::countVariables() -{ - /* - TEST optimization - minimize: - * 3x - y - subject to: - * 1.5 x + 2 y >= 12 - * 0 <= x <= 3 - * 0 <= y <= 5 - * x - linear variable - * y - integer variable - */ - - // Define variables and at the same time Boundaries - MPVariable* x = solver.MakeNumVar(0.0, 3.0, "x"); - MPVariable* y = solver.MakeIntVar(0.0, 5.0, "y"); - - // redefine lower bound - just do not make x - constant - x->SetLB(1.5); - - // Define constraints - MPConstraint* const ct = solver.MakeRowConstraint(12.0, solverInfinity, "ct"); - ct->SetCoefficient(x, 1.5); - ct->SetCoefficient(y, 2.0); - - // Define objective function - MPObjective* const objective = solver.MutableObjective(); - objective->SetCoefficient(x, 3); - objective->SetCoefficient(y, -1); - objective->SetMinimization(); - - // Count the number of variables in the solver - int numVariables = solver.NumVariables(); - // Count the number of constraints in the solver - int numConstraints = solver.NumConstraints(); - - // Solve the problem - const MPSolver::ResultStatus result_status = solver.Solve(); - - if (result_status != MPSolver::OPTIMAL) - { - // If not optimal, print that optimization failed - logs.info() << "The problem does not have an optimal solution.\n"; - return; - } - // Access and print the results - printf("Optimal objective value = %.2f\n", objective->Value()); - printf("x = %.2f\n", x->solution_value()); - printf("y = %.2f\n", y->solution_value()); - - // Clear the solver to reset it for the new problem - solver.Clear(); - - return; -} - // populate OptimizationProblemVariables struct void OptimizedThermalGenerator::allocateVarStruct() { diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 5265fdfbcc..9686893a99 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -24,9 +24,6 @@ class OptimizedThermalGenerator : public GeneratorTempData private: // optimization problem construction methods - // dummy function - to be deleted - void countVariables(); - // functions to allocate variable structure void allocateVarStruct(); void allocateVarStruct(int day); @@ -170,6 +167,7 @@ class OptimizedThermalGenerator : public GeneratorTempData void printAllVariables(); void printObjectiveFunction(MPObjective* objective); void printConstraints(); + void printResults(); void printProblemVarAndResults(); // Functions called in main method: From 9ebc70e98c3ae51c624dc4fa8116e20154f49799 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Fri, 24 Nov 2023 12:21:46 +0100 Subject: [PATCH 168/315] printResults method - for debugging purpose - result tested - seems logical - OK --- .../OptimizedGenerator.h | 5 ++ .../PrintProblemVarRes.cpp | 74 +++++++++++++++++++ 2 files changed, 79 insertions(+) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 9686893a99..d4b34dd8c1 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -275,4 +275,9 @@ class OptimizedThermalGenerator : public GeneratorTempData void GenerateOptimizedThermalTimeSeries(); }; +// Declare the auxiliary function outside the class +// Debug & Test purpose - to be removed +template +void printColumnToFile(const std::vector>& data); + } // namespace Antares::Solver::TSGenerator \ No newline at end of file diff --git a/src/solver/ts-generator/optimized-thermal-generator/PrintProblemVarRes.cpp b/src/solver/ts-generator/optimized-thermal-generator/PrintProblemVarRes.cpp index 5330c2a612..b7374eb6c9 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PrintProblemVarRes.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PrintProblemVarRes.cpp @@ -2,6 +2,10 @@ // Created by milos on 14/11/23. // +#include +#include +#include + #include "OptimizedGenerator.h" namespace Antares::Solver::TSGenerator @@ -11,6 +15,7 @@ void OptimizedThermalGenerator::printProblemVarAndResults() printAllVariables(); printConstraints(); printObjectiveFunction(solver.MutableObjective()); + printResults(); } void OptimizedThermalGenerator::printAllVariables() @@ -59,4 +64,73 @@ void OptimizedThermalGenerator::printObjectiveFunction(MPObjective* objective) return; } +void OptimizedThermalGenerator::printResults() +{ + std::vector> dataToPrint; + + // loop per day + for (auto it = var.day.begin(); it != var.day.end(); ++it) + { + // row vector + std::vector RED; + + // ens and spill + RED.push_back(it->Ens->solution_value()); + RED.push_back(it->Spill->solution_value()); + + // powers + start/end + for (const auto& cluster : it->areaMap) + { + for (const auto& unit : cluster.second.clusterMap) + { + for (const auto& perUnit : unit.second.unitMap) + { + // powers + if (perUnit.P != nullptr) + { + RED.push_back(perUnit.P->solution_value()); + } + // start and end + for (uint mnt = 0; mnt < perUnit.start.size(); ++mnt) + { + RED.push_back(perUnit.start[mnt]->solution_value()); + RED.push_back(perUnit.end[mnt]->solution_value()); + } + } + } + } + + dataToPrint.push_back(RED); + } + + printColumnToFile(dataToPrint); + + return; +} + +// Define the auxiliary function outside the class +template +void printColumnToFile(const std::vector>& data) +{ + const std::string& filename = "/home/milos/Documents/RTEi/01-Antares/04-TestModels/CR27.csv"; + std::ofstream outFile(filename); + if (outFile.is_open()) + { + for (size_t row = 0; row < data.size(); ++row) + { + for (size_t col = 0; col < data[row].size(); ++col) + { + outFile << data[row][col]; + outFile << ","; + } + outFile << std::endl; + } + outFile.close(); + } + else + { + std::cerr << "Unable to open file: " << filename << std::endl; + } +} + } // namespace Antares::Solver::TSGenerator From b5a4a4afe0b7438028b83386303b2c4aca3a7e33 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Fri, 24 Nov 2023 17:06:37 +0100 Subject: [PATCH 169/315] re-naming --- .../AuxillaryStructures.h | 10 ++++---- .../CalculateParameters.cpp | 23 ++++++++++--------- .../OptimizedGenerator.h | 2 +- 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h index d54ba8d869..af41986947 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h +++ b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h @@ -75,7 +75,7 @@ struct OptimizationProblemVariables // so inside optimization problem we just retrieve these data // not re-calculate them over and over again -struct DailyClusterDataPerCluster +struct ClusterData { std::array maxPower; std::array avgCost; @@ -84,16 +84,16 @@ struct DailyClusterDataPerCluster int averageMaintenanceDuration; }; -struct DailyClusterDataPerArea +struct AreaData { // number of elements in the map is total number of cluster in area - std::map clusterMap; + std::map clusterMap; }; -struct DailyClusterData +struct MaintenanceData { // number of elements in the map is total number of areas in maintenance group - std::map areaMap; + std::map areaMap; }; } // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp index 8ca23b9258..e05c9f14cf 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp @@ -142,8 +142,8 @@ void OptimizedThermalGenerator::setClusterData() for (const auto& entryWeightMap : maintenanceGroup_) { const auto& area = *(entryWeightMap.first); - auto& areaVariables = dailyClusterData.areaMap; - areaVariables[&area] = DailyClusterDataPerArea(); + auto& areaVariables = maintenanceData.areaMap; + areaVariables[&area] = AreaData(); // loop per thermal clusters inside the area - fill in the structure for (auto it = area.thermal.list.mapping.begin(); it != area.thermal.list.mapping.end(); ++it) @@ -156,7 +156,7 @@ void OptimizedThermalGenerator::setClusterData() continue; auto& clusterVariables = areaVariables[&area].clusterMap; - clusterVariables[&cluster] = DailyClusterDataPerCluster(); + clusterVariables[&cluster] = ClusterData(); clusterVariables[&cluster].maxPower = calculateMaxUnitOutput(cluster); clusterVariables[&cluster].avgCost = calculateAvrUnitDailyCost(cluster); @@ -175,7 +175,7 @@ void OptimizedThermalGenerator::setClusterData() // calculate parameters methods - per cluster int OptimizedThermalGenerator::calculateNumberOfMaintenances(const Data::ThermalCluster& cluster, - int timeHorizon) + int timeHorizon) { // timeHorizon cannot be 0. The whole maintenance group would be skipped if this happened // on the other hand interPoPeriod can be 0. So we say at least 2 maintenance if this happens @@ -190,7 +190,8 @@ int OptimizedThermalGenerator::calculateNumberOfMaintenances(const Data::Thermal return std::max(timeHorizon / cluster.interPoPeriod, minNumberOfMaintenances); // floor } -int OptimizedThermalGenerator::calculateAverageMaintenanceDuration(const Data::ThermalCluster& cluster) +int OptimizedThermalGenerator::calculateAverageMaintenanceDuration( + const Data::ThermalCluster& cluster) { double sum = 0.0; for (std::size_t row = 0; row < DAYS_PER_YEAR; ++row) @@ -274,7 +275,7 @@ double OptimizedThermalGenerator::getPowerCost(const Data::ThermalCluster& clust return 0.; } - return dailyClusterData.areaMap[cluster.parentArea] + return maintenanceData.areaMap[cluster.parentArea] .clusterMap[&cluster] .avgCost[dayOfTheYear(optimizationDay)]; } @@ -282,7 +283,7 @@ double OptimizedThermalGenerator::getPowerCost(const Data::ThermalCluster& clust double OptimizedThermalGenerator::getPowerOutput(const Data::ThermalCluster& cluster, int optimizationDay) { - return dailyClusterData.areaMap[cluster.parentArea] + return maintenanceData.areaMap[cluster.parentArea] .clusterMap[&cluster] .maxPower[dayOfTheYear(optimizationDay)]; } @@ -294,12 +295,12 @@ double OptimizedThermalGenerator::getResidualLoad(int optimizationDay) int OptimizedThermalGenerator::getNumberOfMaintenances(const Data::ThermalCluster& cluster) { - return dailyClusterData.areaMap[cluster.parentArea].clusterMap[&cluster].numberOfMaintenances; + return maintenanceData.areaMap[cluster.parentArea].clusterMap[&cluster].numberOfMaintenances; } int OptimizedThermalGenerator::getAverageMaintenanceDuration(const Data::ThermalCluster& cluster) { - return dailyClusterData.areaMap[cluster.parentArea] + return maintenanceData.areaMap[cluster.parentArea] .clusterMap[&cluster] .averageMaintenanceDuration; } @@ -332,7 +333,7 @@ int OptimizedThermalGenerator::calculateUnitEarliestStartOfFirstMaintenance( if (unitIndex < cluster.daysSinceLastMaintenance.size()) { return std::min(cluster.interPoPeriod - - dailyClusterData.areaMap[cluster.parentArea] + - maintenanceData.areaMap[cluster.parentArea] .clusterMap[&cluster] .daysSinceLastMnt[unitIndex] - cluster.poWindows, @@ -360,7 +361,7 @@ int OptimizedThermalGenerator::calculateUnitLatestStartOfFirstMaintenance( // however we will make sure it does not surpass timeHorizon_ - 1 value return std::min(cluster.interPoPeriod - - dailyClusterData.areaMap[cluster.parentArea] + - maintenanceData.areaMap[cluster.parentArea] .clusterMap[&cluster] .daysSinceLastMnt[unitIndex] + cluster.poWindows, diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index d4b34dd8c1..20ec5bccba 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -230,7 +230,7 @@ class OptimizedThermalGenerator : public GeneratorTempData double ensCost_; double spillCost_; std::array residualLoadDailyValues_; - DailyClusterData dailyClusterData; + MaintenanceData maintenanceData; OptimizationProblemVariables var; // MPSolver instance From 6ffe65ea1de9e44a35ecec28bc6684eccd5e730a Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Fri, 24 Nov 2023 19:33:27 +0100 Subject: [PATCH 170/315] refactor+comments --- .../CalculateParameters.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp index e05c9f14cf..f8a53193b8 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp @@ -145,10 +145,9 @@ void OptimizedThermalGenerator::setClusterData() auto& areaVariables = maintenanceData.areaMap; areaVariables[&area] = AreaData(); // loop per thermal clusters inside the area - fill in the structure - for (auto it = area.thermal.list.mapping.begin(); it != area.thermal.list.mapping.end(); - ++it) + for (const auto& clusterEntry : area.thermal.list.mapping) { - const auto& cluster = *(it->second); + const auto& cluster = *(clusterEntry.second); // we do not check if cluster.optimizeMaintenance = true here // we add all the clusters Power inside maintenance group @@ -179,6 +178,7 @@ int OptimizedThermalGenerator::calculateNumberOfMaintenances(const Data::Thermal { // timeHorizon cannot be 0. The whole maintenance group would be skipped if this happened // on the other hand interPoPeriod can be 0. So we say at least 2 maintenance if this happens + // actually this cannot happen because checkMaintenanceGroupParameters() will kill it by now if (cluster.interPoPeriod == 0) { logs.warning() << "Cluster: " << cluster.getFullName() @@ -198,7 +198,9 @@ int OptimizedThermalGenerator::calculateAverageMaintenanceDuration( { sum += cluster.prepro->data[Data::PreproThermal::poDuration][row]; } - + // poDuration in Antares cannot be below 1.0 + // so it is redundant to check here if return value is above 1.0 + // that is why I did not use std::max() return sum / static_cast(DAYS_PER_YEAR); } From 8ccc3c20dbc3138a33f578d1002021bdf1316c74 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Fri, 24 Nov 2023 23:15:18 +0100 Subject: [PATCH 171/315] refactor --- .../optimized-thermal-generator/CreateVariables.cpp | 12 ++++++------ .../optimized-thermal-generator/SetProblemCost.cpp | 12 ++++++------ .../SetVariableBounds.cpp | 4 ++-- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp b/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp index 8c5045d553..0d562168da 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp @@ -41,9 +41,9 @@ void OptimizedThermalGenerator::allocateVarStruct(int day) void OptimizedThermalGenerator::allocateVarStruct(int day, const Data::Area& area) { // loop per thermal clusters inside the area - for (auto it = area.thermal.list.mapping.begin(); it != area.thermal.list.mapping.end(); ++it) + for (const auto& clusterEntry : area.thermal.list.mapping) { - const auto& cluster = *(it->second); + const auto& cluster = *(clusterEntry.second); // we do not check if cluster.optimizeMaintenance = true here // we add all the clusters Power inside maintenance group @@ -101,9 +101,9 @@ void OptimizedThermalGenerator::buildUnitPowerOutputVariables(const OptProblemSe const Data::Area& area) { // loop per thermal clusters inside the area - for (auto it = area.thermal.list.mapping.begin(); it != area.thermal.list.mapping.end(); ++it) + for (const auto& clusterEntry : area.thermal.list.mapping) { - const auto& cluster = *(it->second); + const auto& cluster = *(clusterEntry.second); // we do not check if cluster.optimizeMaintenance = true here // we add all the clusters Power inside maintenance group @@ -158,9 +158,9 @@ void OptimizedThermalGenerator::buildStartEndMntVariables(const OptProblemSettin const Data ::Area& area) { // loop per thermal clusters inside the area - for (auto it = area.thermal.list.mapping.begin(); it != area.thermal.list.mapping.end(); ++it) + for (const auto& clusterEntry : area.thermal.list.mapping) { - const auto& cluster = *(it->second); + const auto& cluster = *(clusterEntry.second); // check if cluster exist, do we generate + optimizeMaintenance // create start end variables only for these clusters diff --git a/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp b/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp index 6b33fc802c..5d317c35aa 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp @@ -24,9 +24,9 @@ void OptimizedThermalGenerator::setProblemCost(const OptProblemSettings& optSett void OptimizedThermalGenerator::setProblemEnsCost(MPObjective* objective) { // loop per day - for (int day = 0; day < timeHorizon_; ++day) + for (const auto day : var.day) { - objective->SetCoefficient(var.day[day].Ens, ensCost_); + objective->SetCoefficient(day.Ens, ensCost_); } return; } @@ -34,9 +34,9 @@ void OptimizedThermalGenerator::setProblemEnsCost(MPObjective* objective) void OptimizedThermalGenerator::setProblemSpillCost(MPObjective* objective) { // loop per day - for (int day = 0; day < timeHorizon_; ++day) + for (const auto day : var.day) { - objective->SetCoefficient(var.day[day].Spill, spillCost_); + objective->SetCoefficient(day.Spill, spillCost_); } return; } @@ -71,9 +71,9 @@ void OptimizedThermalGenerator::setProblemPowerCost(const OptProblemSettings& op const Data::Area& area) { // loop per thermal clusters inside the area - for (auto it = area.thermal.list.mapping.begin(); it != area.thermal.list.mapping.end(); ++it) + for (const auto& clusterEntry : area.thermal.list.mapping) { - const auto& cluster = *(it->second); + const auto& cluster = *(clusterEntry.second); // we do not check if cluster.optimizeMaintenance = true here // we add all the clusters Power inside maintenance group diff --git a/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp b/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp index 32eac14253..bfcc598245 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp @@ -26,9 +26,9 @@ void OptimizedThermalGenerator::fixBounds() void OptimizedThermalGenerator::fixBounds(const Data::Area& area) { // loop per thermal clusters inside the area - for (auto it = area.thermal.list.mapping.begin(); it != area.thermal.list.mapping.end(); ++it) + for (const auto& clusterEntry : area.thermal.list.mapping) { - const auto& cluster = *(it->second); + const auto& cluster = *(clusterEntry.second); // check if cluster exist, do we generate + optimizeMaintenance // create start end variables only for these clusters From ad5edd35385e661a145646a4610b39357f2b3a49 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Sun, 26 Nov 2023 02:37:56 +0100 Subject: [PATCH 172/315] HUGE refactor - re-define var structure and all the loops --- .../AuxillaryStructures.h | 63 ++-- .../CalculateParameters.cpp | 18 +- .../CreateVariables.cpp | 178 ++++------- .../OptimizedGenerator.h | 117 ++------ .../PrintProblemVarRes.cpp | 82 ++++-- .../ResetProblem.cpp | 4 +- .../SetProblemConstraints.cpp | 276 +++++------------- .../SetProblemCost.cpp | 70 +---- .../SetVariableBounds.cpp | 111 ++----- 9 files changed, 293 insertions(+), 626 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h index af41986947..5bd9291357 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h +++ b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h @@ -12,6 +12,7 @@ using namespace operations_research; namespace Antares::Solver::TSGenerator { +// this class stores data about optimization problem settings class OptProblemSettings final { public: @@ -24,57 +25,47 @@ class OptProblemSettings final bool solved = true; }; -// TODO CR27: -// maybe for refactoring create a vector of structs called units -// each unit struct will contain pointer to area/cluster/int unitIndex/ bool createStartEnd -// pointer to var P*, vector of pointers to var start<*> & end<*> -// then loop just through that vector + loop per time step -// not loop nesting into day-area-cluster-unit -// maybe better ?@! - -struct OptimizationProblemVariablesPerUnit +// this structure stores the data about optimization problem variables +struct Maintenances { - MPVariable* P = nullptr;; // pointer to P[t][u] variable - - // number of elements in the vector is total number of maintenances of unit - std::vector start; // pointer to s[t][u][m] variable - std::vector end; // pointer to e[t][u][m] variable + // number of elements in the vector is number of days in optimization problem + std::vector start; // pointer to s[u][m][t] variables + std::vector end; // pointer to e[u][m][t] variables }; -struct OptimizationProblemVariablesPerCluster +struct Unit { - // number of elements in the vector is total number of units in cluster - std::vector unitMap; -}; + // inputs + const Data::ThermalCluster* parentCluster; + int index; + bool createStartEndVariables; -struct OptimizationProblemVariablesPerArea -{ - // number of elements in the map is total number of clusters in area - std::map clusterMap; -}; + // solver variables -struct OptimizationProblemVariablesPerDay -{ - MPVariable* Ens = nullptr; // pointer to ENS[t] variable - MPVariable* Spill = nullptr;; // pointer to Spillage[t] variable - // number of elements in the map is total number of areas in optimization problem - std::map areaMap; + // number of elements in the vector is number of days in optimization problem + std::vector P; // pointers to P[u][t] variables + + // number of elements in the vector is total maintenances of unit + std::vector maintenances; }; + struct OptimizationProblemVariables { - // number of elements in the vector is total number of days in optimization problem - std::vector day; + // number of elements in the vector is number units (areas*cluster*units) + std::vector clusterUnits; + + // number of elements in the vector is number of days in optimization problem + std::vector ens; // pointers to Ens[t] variables + std::vector spill; // pointers to Spill[t] variables }; // it is better to immediately calculate and populate structures -// that will store information about: -// for each area and each cluster: -// daily arrays with info about: -// daily MaxUnitOutput and -// daily UnitPowerCost +// that will store information about clusters // so inside optimization problem we just retrieve these data // not re-calculate them over and over again +// this structure stores cluster input data (optimization parameters) +// that stays the same during optimizationS struct ClusterData { std::array maxPower; diff --git a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp index f8a53193b8..8d60c7df7c 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp @@ -142,8 +142,8 @@ void OptimizedThermalGenerator::setClusterData() for (const auto& entryWeightMap : maintenanceGroup_) { const auto& area = *(entryWeightMap.first); - auto& areaVariables = maintenanceData.areaMap; - areaVariables[&area] = AreaData(); + auto& areaData = maintenanceData.areaMap; + areaData[&area] = AreaData(); // loop per thermal clusters inside the area - fill in the structure for (const auto& clusterEntry : area.thermal.list.mapping) { @@ -154,19 +154,19 @@ void OptimizedThermalGenerator::setClusterData() if (!checkClusterExist(cluster)) continue; - auto& clusterVariables = areaVariables[&area].clusterMap; - clusterVariables[&cluster] = ClusterData(); - clusterVariables[&cluster].maxPower = calculateMaxUnitOutput(cluster); - clusterVariables[&cluster].avgCost = calculateAvrUnitDailyCost(cluster); + auto& clusterData = areaData[&area].clusterMap; + clusterData[&cluster] = ClusterData(); + clusterData[&cluster].maxPower = calculateMaxUnitOutput(cluster); + clusterData[&cluster].avgCost = calculateAvrUnitDailyCost(cluster); - clusterVariables[&cluster].numberOfMaintenances + clusterData[&cluster].numberOfMaintenances = calculateNumberOfMaintenances(cluster, timeHorizon_); - clusterVariables[&cluster].averageMaintenanceDuration + clusterData[&cluster].averageMaintenanceDuration = calculateAverageMaintenanceDuration(cluster); // since we will be updating daysSinceLastMaintenance values // lets create a copy here - this is copy by value! - clusterVariables[&cluster].daysSinceLastMnt = cluster.daysSinceLastMaintenance; + clusterData[&cluster].daysSinceLastMnt = cluster.daysSinceLastMaintenance; } } return; diff --git a/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp b/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp index 0d562168da..ec48f68020 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp @@ -8,62 +8,8 @@ namespace Antares::Solver::TSGenerator { void OptimizedThermalGenerator::buildProblemVariables(const OptProblemSettings& optSett) { - allocateVarStruct(); buildEnsAndSpillageVariables(optSett); buildUnitPowerOutputVariables(optSett); - buildStartEndMntVariables(optSett); -} - -// populate OptimizationProblemVariables struct -void OptimizedThermalGenerator::allocateVarStruct() -{ - // loop per day - for (int day = 0; day < timeHorizon_; ++day) - { - // fill the variable structure - var.day.push_back(OptimizationProblemVariablesPerDay()); - allocateVarStruct(day); - } -} - -void OptimizedThermalGenerator::allocateVarStruct(int day) -{ - // loop per areas inside maintenance group - for (const auto& entryWeightMap : maintenanceGroup_) - { - const auto& area = *(entryWeightMap.first); - auto& areaVariables = var.day[day].areaMap; - areaVariables[&area] = OptimizationProblemVariablesPerArea(); - allocateVarStruct(day, area); - } -} - -void OptimizedThermalGenerator::allocateVarStruct(int day, const Data::Area& area) -{ - // loop per thermal clusters inside the area - for (const auto& clusterEntry : area.thermal.list.mapping) - { - const auto& cluster = *(clusterEntry.second); - - // we do not check if cluster.optimizeMaintenance = true here - // we add all the clusters Power inside maintenance group - if (!checkClusterExist(cluster)) - continue; - - auto& clusterVariables = var.day[day].areaMap[&area].clusterMap; - clusterVariables[&cluster] = OptimizationProblemVariablesPerCluster(); - allocateVarStruct(day, cluster); - } -} - -void OptimizedThermalGenerator::allocateVarStruct(int day, const Data::ThermalCluster& cluster) -{ - // loop per unit inside the cluster - for (int unit = 0; unit < cluster.unitCount; ++unit) - { - var.day[day].areaMap[cluster.parentArea].clusterMap[&cluster].unitMap.push_back( - OptimizationProblemVariablesPerUnit()); - } } // create VARIABLES per day - ENS[t], Spill[t] @@ -71,22 +17,22 @@ void OptimizedThermalGenerator::buildEnsAndSpillageVariables(const OptProblemSet { for (int day = 0; day < timeHorizon_; ++day) { - // add ENS variables - var.day[day].Ens = solver.MakeNumVar( - 0.0, solverInfinity, "ENS_[" + std::to_string(day + optSett.firstDay) + "]"); + // add ENS[t] variables + vars.ens.push_back(solver.MakeNumVar( + 0.0, solverInfinity, "ENS_[" + std::to_string(day + optSett.firstDay) + "]")); } for (int day = 0; day < timeHorizon_; ++day) { - // add Spillage variables - var.day[day].Spill = solver.MakeNumVar( - 0.0, solverInfinity, "Spill_[" + std::to_string(day + optSett.firstDay) + "]"); + // add Spillage[t] variables + vars.spill.push_back(solver.MakeNumVar( + 0.0, solverInfinity, "Spill_[" + std::to_string(day + optSett.firstDay) + "]")); } return; } -// create VARIABLES per day and per cluster-unit - P[t][u] +// create VARIABLES per day and per cluster-unit - P[u][t] void OptimizedThermalGenerator::buildUnitPowerOutputVariables(const OptProblemSettings& optSett) { // loop per areas inside maintenance group @@ -107,6 +53,8 @@ void OptimizedThermalGenerator::buildUnitPowerOutputVariables(const OptProblemSe // we do not check if cluster.optimizeMaintenance = true here // we add all the clusters Power inside maintenance group + // into optimization problem + // we will exclude only start & end variables if optimizeMaintenance = false if (!checkClusterExist(cluster)) continue; @@ -128,92 +76,72 @@ void OptimizedThermalGenerator::buildUnitPowerOutputVariables(const OptProblemSe const Data::ThermalCluster& cluster, int unit) { + // add new Unit + vars.clusterUnits.push_back(Unit()); + + // but we do not know the total count + // so always retrieve the last one + auto& unitRef = vars.clusterUnits.back(); + + // fill in data for the Unit + unitRef.parentCluster = &cluster; + unitRef.index = unit; // local count inside the cluster + unitRef.createStartEndVariables = true; + // loop per day for (int day = 0; day < timeHorizon_; ++day) { - // add P[t][u] variables - var.day[day].areaMap[cluster.parentArea].clusterMap[&cluster].unitMap[unit].P - = solver.MakeNumVar(0.0, - solverInfinity, - "P_[" + std::to_string(day + optSett.firstDay) + "][" - + cluster.getFullName().to() + "." - + std::to_string(unit) + "]"); + // add P[u][t] variables + unitRef.P.push_back(solver.MakeNumVar(0.0, + solverInfinity, + "P_[" + cluster.getFullName().to() + "." + + std::to_string(unit) + "][" + + std::to_string(day + optSett.firstDay) + "]")); } - return; -} - -// create VARIABLES per day, per cluster-unit and per maintenance - s[t][u][m] & e[t][u][m] -void OptimizedThermalGenerator::buildStartEndMntVariables(const OptProblemSettings& optSett) -{ - // loop per areas inside maintenance group - for (const auto& entryWeightMap : maintenanceGroup_) + // check if: do we generate + optimizeMaintenance + // create start end variables only for these clusters + if (!(cluster.doWeGenerateTS(globalThermalTSgeneration_) && cluster.optimizeMaintenance)) { - const auto& area = *(entryWeightMap.first); - buildStartEndMntVariables(optSett, area); + unitRef.createStartEndVariables = false; + return; } -} -void OptimizedThermalGenerator::buildStartEndMntVariables(const OptProblemSettings& optSett, - const Data ::Area& area) -{ - // loop per thermal clusters inside the area - for (const auto& clusterEntry : area.thermal.list.mapping) - { - const auto& cluster = *(clusterEntry.second); - - // check if cluster exist, do we generate + optimizeMaintenance - // create start end variables only for these clusters - bool createStartEndVar = checkClusterExist(cluster) - && cluster.doWeGenerateTS(globalThermalTSgeneration_) - && cluster.optimizeMaintenance; - if (!createStartEndVar) - continue; - - buildStartEndMntVariables(optSett, cluster); - } -} - -void OptimizedThermalGenerator::buildStartEndMntVariables(const OptProblemSettings& optSett, - const Data ::ThermalCluster& cluster) -{ - int totalMntNumber = getNumberOfMaintenances(cluster); + buildStartEndMntVariables(optSett, cluster, unit, unitRef); - // loop per units inside the cluster - for (int unit = 0; unit < cluster.unitCount; ++unit) - { - buildStartEndMntVariables(optSett, cluster, unit, totalMntNumber); - } + return; } void OptimizedThermalGenerator::buildStartEndMntVariables(const OptProblemSettings& optSett, const Data ::ThermalCluster& cluster, int unit, - int totalMntNumber) + Unit& unitRef) { + int totalMntNumber = getNumberOfMaintenances(cluster); // loop per maintenances per unit for (int mnt = 0; mnt < totalMntNumber; ++mnt) { - buildStartVariables(optSett, cluster, unit, mnt); - buildEndVariables(optSett, cluster, unit, mnt); + unitRef.maintenances.push_back(Maintenances()); + buildStartVariables(optSett, cluster, unit, unitRef, mnt); + buildEndVariables(optSett, cluster, unit, unitRef, mnt); } } void OptimizedThermalGenerator::buildStartVariables(const OptProblemSettings& optSett, const Data ::ThermalCluster& cluster, int unit, + Unit& unitRef, int mnt) { // loop per day for (int day = 0; day < timeHorizon_; ++day) { - // add start[t][u][m] variables - var.day[day].areaMap[cluster.parentArea].clusterMap[&cluster].unitMap[unit].start.push_back( - solver.MakeIntVar(0.0, - 1.0, - "S_[" + std::to_string(day + optSett.firstDay) + "][" - + cluster.getFullName().to() + "." + std::to_string(unit) - + "][" + std::to_string(mnt) + "]")); + // add start[u][m][t] variables + unitRef.maintenances.back().start.push_back(solver.MakeIntVar( + 0.0, + 1.0, + "S_[" + cluster.getFullName().to() + "." + std::to_string(unit) + "][" + + std::to_string(mnt) + "][" + std::to_string(day + optSett.firstDay) + "]")); } return; } @@ -221,18 +149,18 @@ void OptimizedThermalGenerator::buildStartVariables(const OptProblemSettings& op void OptimizedThermalGenerator::buildEndVariables(const OptProblemSettings& optSett, const Data ::ThermalCluster& cluster, int unit, + Unit& unitRef, int mnt) { // loop per day for (int day = 0; day < timeHorizon_; ++day) { - // add end[t][u][m] variables - var.day[day].areaMap[cluster.parentArea].clusterMap[&cluster].unitMap[unit].end.push_back( - solver.MakeIntVar(0.0, - 1.0, - "E_[" + std::to_string(day + optSett.firstDay) + "][" - + cluster.getFullName().to() + "." + std::to_string(unit) - + "][" + std::to_string(mnt) + "]")); + // add end[u][m][t] variables + unitRef.maintenances.back().end.push_back(solver.MakeIntVar( + 0.0, + 1.0, + "E_[" + cluster.getFullName().to() + "." + std::to_string(unit) + "][" + + std::to_string(mnt) + "][" + std::to_string(day + optSett.firstDay) + "]")); } return; } diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 20ec5bccba..4b6de82fb7 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -24,12 +24,6 @@ class OptimizedThermalGenerator : public GeneratorTempData private: // optimization problem construction methods - // functions to allocate variable structure - void allocateVarStruct(); - void allocateVarStruct(int day); - void allocateVarStruct(int day, const Data::Area& area); - void allocateVarStruct(int day, const Data::ThermalCluster& cluster); - // functions to build problem variables void buildProblemVariables(const OptProblemSettings& optSett); void buildEnsAndSpillageVariables(const OptProblemSettings& optSett); @@ -39,38 +33,29 @@ class OptimizedThermalGenerator : public GeneratorTempData const Data::ThermalCluster& cluster); void buildUnitPowerOutputVariables(const OptProblemSettings& optSett, const Data::ThermalCluster& cluster, - int day); - void buildStartEndMntVariables(const OptProblemSettings& optSett); - void buildStartEndMntVariables(const OptProblemSettings& optSett, const Data ::Area& area); - void buildStartEndMntVariables(const OptProblemSettings& optSett, - const Data ::ThermalCluster& cluster); + int unit); void buildStartEndMntVariables(const OptProblemSettings& optSett, - const Data ::ThermalCluster& cluster, + const Data::ThermalCluster& cluster, int unit, - int totalMntNumber); + Unit& unitRef); void buildStartVariables(const OptProblemSettings& optSett, const Data ::ThermalCluster& cluster, int unit, + Unit& unitRef, int mnt); void buildEndVariables(const OptProblemSettings& optSett, const Data ::ThermalCluster& cluster, int unit, + Unit& unitRef, int mnt); // functions to fix bounds of some variables void fixBounds(); - void fixBounds(const Data::Area& area); - void fixBounds(const Data::ThermalCluster& cluster); - void fixBounds(const Data::ThermalCluster& cluster, - int unit, - int totalMntNum, - int avrMntDuration); - void fixBoundsFirstMnt(const Data::ThermalCluster& cluster, int unit); - void fixBoundsStartSecondMnt(const Data::ThermalCluster& cluster, int unit, int mnt); - void fixBoundsMntEnd(const Data::ThermalCluster& cluster, - int unit, - int mnt, - int avrMntDuration); + void fixBounds(const Unit& unit); + void fixBounds(const Unit& unit, int averageMaintenanceDuration); + void fixBoundsFirstMnt(const Unit& unit); + void fixBoundsStartSecondMnt(const Unit& unit, int mnt); + void fixBoundsMntEnd(const Unit& unit, int mnt, int averageMaintenanceDuration); // functions to build problem constraints void buildProblemConstraints(const OptProblemSettings& optSett); @@ -79,84 +64,42 @@ class OptimizedThermalGenerator : public GeneratorTempData void insertEnsVars(MPConstraint* ct, int day); void insertSpillVars(MPConstraint* ct, int day); void insertPowerVars(MPConstraint* ct, int day); - void insertPowerVars(MPConstraint* ct, int day, const Data::Area& area); - void insertPowerVars(MPConstraint* ct, int day, const Data::ThermalCluster& cluster); - void insertPowerVars(MPConstraint* ct, int day, const Data::ThermalCluster& cluster, int unit); + void insertPowerVars(MPConstraint* ct, int day, const Unit& unit); void setStartEndMntLogicConstraints(const OptProblemSettings& optSett); - void setStartEndMntLogicConstraints(const OptProblemSettings& optSett, const Data::Area& area); - void setStartEndMntLogicConstraints(const OptProblemSettings& optSett, - const Data::ThermalCluster& cluster); - void setStartEndMntLogicConstraints(const OptProblemSettings& optSett, - const Data::ThermalCluster& cluster, - int unit); + void setStartEndMntLogicConstraints(const OptProblemSettings& optSett, const Unit& unit); void setEndOfMaintenanceEventBasedOnAverageDurationOfMaintenanceEvent( const OptProblemSettings& optSett, - const Data::ThermalCluster& cluster, - int unit, + const Unit& unit, int mnt); void setUpFollowingMaintenanceBasedOnAverageDurationBetweenMaintenanceEvents( const OptProblemSettings& optSett, - const Data::ThermalCluster& cluster, - int unit, + const Unit& unit, int mnt); void setOnceStartIsSetToOneItWillBeOneUntilEndOfOptimizationTimeHorizon( const OptProblemSettings& optSett, - const Data::ThermalCluster& cluster, - int unit, + const Unit& unit, int mnt); void setNextMaintenanceCanNotStartBeforePreviousMaintenance(const OptProblemSettings& optSett, - const Data::ThermalCluster& cluster, - int unit, + const Unit& cluster, int mnt); void setMaxUnitOutputConstraints(const OptProblemSettings& optSett); void setMaxUnitOutputConstraints(const OptProblemSettings& optSett, int& day); - void setMaxUnitOutputConstraints(const OptProblemSettings& optSett, - int day, - const Data::Area& area); - void setMaxUnitOutputConstraints(const OptProblemSettings& optSett, - int day, - const Data::ThermalCluster& cluster); - void setMaxUnitOutputConstraints(const OptProblemSettings& optSett, - int day, - const Data::ThermalCluster& cluster, - int unit, - double maxOutput); - void insertStartSum(MPConstraint* ct, - int day, - const Data::ThermalCluster& cluster, - int unit, - double maxPower); - void insertEndSum(MPConstraint* ct, - int day, - const Data::ThermalCluster& cluster, - int unit, - double maxPower); + void setMaxUnitOutputConstraints(const OptProblemSettings& optSett, int day, const Unit& unit); + void insertStartSum(MPConstraint* ct, int day, const Unit& unit, double maxPower); + void insertEndSum(MPConstraint* ct, int day, const Unit& cluster, double maxPower); // functions to set problem objective function void setProblemCost(const OptProblemSettings& optSett); void setProblemEnsCost(MPObjective* objective); void setProblemSpillCost(MPObjective* objective); void setProblemPowerCost(const OptProblemSettings& optSett, MPObjective* objective); - void setProblemPowerCost(const OptProblemSettings& optSett, MPObjective* objective, int day); - void setProblemPowerCost(const OptProblemSettings& optSett, - MPObjective* objective, - int day, - const Data::Area& area); void setProblemPowerCost(const OptProblemSettings& optSett, MPObjective* objective, - int day, - const Data::Area& area, - const Data::ThermalCluster& cluster); - void setProblemPowerCost(MPObjective* objective, - int day, - const Data::Area& area, - const Data::ThermalCluster& cluster, - int unitIndex, - double powerCost); + const Unit& unit); // solve problem and check if optimal solution found bool solveProblem(OptProblemSettings& optSett); - + // reset problem and variable structure void resetProblem(); @@ -186,8 +129,10 @@ class OptimizedThermalGenerator : public GeneratorTempData // calculate parameters methods - per cluster int calculateNumberOfMaintenances(const Data::ThermalCluster& cluster, int timeHorizon); int calculateAverageMaintenanceDuration(const Data::ThermalCluster& cluster); - static std::array calculateMaxUnitOutput(const Data::ThermalCluster& cluster); - static std::array calculateAvrUnitDailyCost(const Data::ThermalCluster& cluster); + static std::array calculateMaxUnitOutput( + const Data::ThermalCluster& cluster); + static std::array calculateAvrUnitDailyCost( + const Data::ThermalCluster& cluster); // getters double getPowerCost(const Data::ThermalCluster& cluster, int optimizationDay); @@ -231,7 +176,7 @@ class OptimizedThermalGenerator : public GeneratorTempData double spillCost_; std::array residualLoadDailyValues_; MaintenanceData maintenanceData; - OptimizationProblemVariables var; + OptimizationProblemVariables vars; // MPSolver instance MPSolver solver; @@ -257,27 +202,27 @@ class OptimizedThermalGenerator : public GeneratorTempData // Solver Settings // MP solver parameters / TODD CR27: do we change this - // I would keep it on default values for the time being - + // Access solver parameters MPSolverParameters params; // Set parameter values // params.SetIntegerParam(MPSolverParameters::SCALING, 0); // params.SetIntegerParam(MPSolverParameters::PRESOLVE, 0); - + // set solver infinity solverInfinity = solver.infinity(); } ~OptimizedThermalGenerator() = default; - // Main functions - loop per scenarios and through the scenario length step by step + // Main functions - loop per scenarios and through the scenario length step by step // (moving window) void GenerateOptimizedThermalTimeSeries(); }; -// Declare the auxiliary function outside the class +// Declare the auxiliary function outside the class // Debug & Test purpose - to be removed template -void printColumnToFile(const std::vector>& data); +void printColumnToFile(const std::vector>& data, const std::string& filename); } // namespace Antares::Solver::TSGenerator \ No newline at end of file diff --git a/src/solver/ts-generator/optimized-thermal-generator/PrintProblemVarRes.cpp b/src/solver/ts-generator/optimized-thermal-generator/PrintProblemVarRes.cpp index b7374eb6c9..684920abbb 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PrintProblemVarRes.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PrintProblemVarRes.cpp @@ -5,6 +5,8 @@ #include #include #include +#include +#include #include "OptimizedGenerator.h" @@ -20,47 +22,81 @@ void OptimizedThermalGenerator::printProblemVarAndResults() void OptimizedThermalGenerator::printAllVariables() { + std::vector> dataToPrint; + for (MPVariable* const variable : solver.variables()) { + std::vector RED; std::cout << "Variable: " << variable->name() << ", " << "Lower bound: " << variable->lb() << ", " << "Upper bound: " << variable->ub() << std::endl; + RED.push_back(variable->name()); + RED.push_back(std::to_string(variable->lb())); + RED.push_back(std::to_string(variable->ub())); + dataToPrint.push_back(RED); } std::cout << "total number of variables is: " << solver.NumVariables() << std::endl; - + printColumnToFile( + dataToPrint, "/home/milos/Documents/RTEi/01-Antares/04-TestModels/REFACTOR-CR27-Vars.csv"); return; } void OptimizedThermalGenerator::printConstraints() { const int num_constraints = solver.NumConstraints(); - + std::vector> dataToPrint; for (int i = 0; i < num_constraints; ++i) { + std::vector RED; const MPConstraint* const constraint = solver.constraint(i); std::cout << "**** Constraint " << i + 1 << " ****" << std::endl; std::cout << "Name: " << constraint->name() << std::endl; std::cout << "Lower Bound: " << constraint->lb() << std::endl; std::cout << "Upper Bound: " << constraint->ub() << std::endl; + RED.push_back(constraint->name()); + RED.push_back(std::to_string(constraint->lb())); + RED.push_back(std::to_string(constraint->ub())); + + std::vector RED_SORT; for (const auto& term : constraint->terms()) { const MPVariable* const var = term.first; const double coefficient = term.second; std::cout << var->name() << ": " << coefficient << std::endl; + RED_SORT.push_back(var->name() + "->" + std::to_string(coefficient)); } + + // sort sub vector + std::sort(RED_SORT.begin(), RED_SORT.end()); + // insert it in main vector + RED.insert(RED.end(), RED_SORT.begin(), RED_SORT.end()); + // end of row + dataToPrint.push_back(RED); std::cout << "------------------------" << std::endl; } + + printColumnToFile( + dataToPrint, + "/home/milos/Documents/RTEi/01-Antares/04-TestModels/REFACTOR-CR27-Constraints.csv"); } void OptimizedThermalGenerator::printObjectiveFunction(MPObjective* objective) { + std::vector> dataToPrint; for (MPVariable* variable : solver.variables()) { std::cout << variable->name() << ": " << objective->GetCoefficient(variable) << std::endl; + std::vector RED; + RED.push_back(variable->name()); + RED.push_back(std::to_string(objective->GetCoefficient(variable))); + dataToPrint.push_back(RED); } std::cout << std::endl; + printColumnToFile( + dataToPrint, + "/home/milos/Documents/RTEi/01-Antares/04-TestModels/REFACTOR-CR27-Objective.csv"); return; } @@ -69,50 +105,46 @@ void OptimizedThermalGenerator::printResults() std::vector> dataToPrint; // loop per day - for (auto it = var.day.begin(); it != var.day.end(); ++it) + for (auto day = 0; day != vars.ens.size(); ++day) { // row vector std::vector RED; // ens and spill - RED.push_back(it->Ens->solution_value()); - RED.push_back(it->Spill->solution_value()); + RED.push_back(vars.ens[day]->solution_value()); + RED.push_back(vars.spill[day]->solution_value()); // powers + start/end - for (const auto& cluster : it->areaMap) + for (const auto& unit : vars.clusterUnits) { - for (const auto& unit : cluster.second.clusterMap) + // powers + if (unit.P[day] != nullptr) { - for (const auto& perUnit : unit.second.unitMap) - { - // powers - if (perUnit.P != nullptr) - { - RED.push_back(perUnit.P->solution_value()); - } - // start and end - for (uint mnt = 0; mnt < perUnit.start.size(); ++mnt) - { - RED.push_back(perUnit.start[mnt]->solution_value()); - RED.push_back(perUnit.end[mnt]->solution_value()); - } - } + RED.push_back(unit.P[day]->solution_value()); + } + // start and end + for (uint mnt = 0; mnt < unit.maintenances.size(); ++mnt) + { + RED.push_back(unit.maintenances[mnt].start[day]->solution_value()); + RED.push_back(unit.maintenances[mnt].end[day]->solution_value()); } } dataToPrint.push_back(RED); } - printColumnToFile(dataToPrint); + printf("Optimal objective value = %.2f\n", solver.MutableObjective()->Value()); + + printColumnToFile( + dataToPrint, "/home/milos/Documents/RTEi/01-Antares/04-TestModels/REFACTOR-CR27-Results.csv"); return; } // Define the auxiliary function outside the class template -void printColumnToFile(const std::vector>& data) +void printColumnToFile(const std::vector>& data, const std::string& filename) { - const std::string& filename = "/home/milos/Documents/RTEi/01-Antares/04-TestModels/CR27.csv"; std::ofstream outFile(filename); if (outFile.is_open()) { @@ -133,4 +165,4 @@ void printColumnToFile(const std::vector>& data) } } -} // namespace Antares::Solver::TSGenerator +} // namespace Antares::Solver::TSGenerator \ No newline at end of file diff --git a/src/solver/ts-generator/optimized-thermal-generator/ResetProblem.cpp b/src/solver/ts-generator/optimized-thermal-generator/ResetProblem.cpp index f22758c230..9815acb01e 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/ResetProblem.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/ResetProblem.cpp @@ -10,7 +10,9 @@ void OptimizedThermalGenerator::resetProblem() { // Clear the solver to reset it for the new problem solver.Clear(); - var.day.clear(); + vars.ens.clear(); + vars.spill.clear(); + vars.clusterUnits.clear(); return; } diff --git a/src/solver/ts-generator/optimized-thermal-generator/SetProblemConstraints.cpp b/src/solver/ts-generator/optimized-thermal-generator/SetProblemConstraints.cpp index 4fa1a6247a..9900c0a3f7 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/SetProblemConstraints.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/SetProblemConstraints.cpp @@ -28,8 +28,8 @@ void OptimizedThermalGenerator::setLoadBalanceConstraints(const OptProblemSettin { int optimizationDay = day + optSett.firstDay; std::string ctName = "LoadBalanceConstraint[" + std::to_string(optimizationDay) + "]"; - double equalTo = getResidualLoad(optimizationDay); - MPConstraint* ct = solver.MakeRowConstraint(equalTo, equalTo, ctName); + double residualLoad = getResidualLoad(optimizationDay); + MPConstraint* ct = solver.MakeRowConstraint(residualLoad, residualLoad, ctName); insertPowerVars(ct, day); insertEnsVars(ct, day); @@ -39,150 +39,74 @@ void OptimizedThermalGenerator::setLoadBalanceConstraints(const OptProblemSettin void OptimizedThermalGenerator::insertEnsVars(MPConstraint* ct, int day) { - ct->SetCoefficient(var.day[day].Ens, 1.0); + ct->SetCoefficient(vars.ens[day], 1.0); } void OptimizedThermalGenerator::insertSpillVars(MPConstraint* ct, int day) { - ct->SetCoefficient(var.day[day].Spill, -1.0); + ct->SetCoefficient(vars.spill[day], -1.0); } void OptimizedThermalGenerator::insertPowerVars(MPConstraint* ct, int day) { - // loop per areas inside maintenance group - for (const auto& entryWeightMap : maintenanceGroup_) + for (const auto& unit : vars.clusterUnits) { - const auto& area = *(entryWeightMap.first); - insertPowerVars(ct, day, area); + insertPowerVars(ct, day, unit); } } -void OptimizedThermalGenerator::insertPowerVars(MPConstraint* ct, int day, const Data::Area& area) +void OptimizedThermalGenerator::insertPowerVars(MPConstraint* ct, int day, const Unit& unit) { - // loop per thermal clusters inside the area - for (const auto& clusterEntry : area.thermal.list.mapping) - { - const auto& cluster = *(clusterEntry.second); - - // we do not check if cluster.optimizeMaintenance = true here - // we add all the clusters Power inside maintenance group - if (!checkClusterExist(cluster)) - continue; - - insertPowerVars(ct, day, cluster); - } + ct->SetCoefficient(unit.P[day], 1.0); } -void OptimizedThermalGenerator::insertPowerVars(MPConstraint* ct, - int day, - const Data::ThermalCluster& cluster) -{ - // loop per units inside the cluster - for (int unit = 0; unit < cluster.unitCount; ++unit) - { - insertPowerVars(ct, day, cluster, unit); - } -} - -void OptimizedThermalGenerator::insertPowerVars(MPConstraint* ct, - int day, - const Data::ThermalCluster& cluster, - int unit) -{ - ct->SetCoefficient( - var.day[day].areaMap[cluster.parentArea].clusterMap[&cluster].unitMap[unit].P, 1.0); -} - -////////////////////////////// - -// CONSTRAINTS per days, per units and per maintenance - constraint-per-each-day+unit+mnt[t][u][m] +// CONSTRAINTS per days, per units and per maintenance - constraint-per-each-day+unit+mnt[u][m][t] void OptimizedThermalGenerator::setStartEndMntLogicConstraints(const OptProblemSettings& optSett) { - // loop per areas inside maintenance group - for (const auto& entryWeightMap : maintenanceGroup_) + for (const auto& unit : vars.clusterUnits) { - const auto& area = *(entryWeightMap.first); - setStartEndMntLogicConstraints(optSett, area); + setStartEndMntLogicConstraints(optSett, unit); } } void OptimizedThermalGenerator::setStartEndMntLogicConstraints(const OptProblemSettings& optSett, - const Data::Area& area) + const Unit& unit) { - // loop per thermal clusters inside the area - for (const auto& clusterEntry : area.thermal.list.mapping) - { - const auto& cluster = *(clusterEntry.second); - - // check if cluster exist, do we generate + optimizeMaintenance - // create constraints only if start/end actually exist - bool createStartEndVar = checkClusterExist(cluster) - && cluster.doWeGenerateTS(globalThermalTSgeneration_) - && cluster.optimizeMaintenance; - if (!createStartEndVar) - continue; - - setStartEndMntLogicConstraints(optSett, cluster); - } -} - -void OptimizedThermalGenerator::setStartEndMntLogicConstraints(const OptProblemSettings& optSett, - const Data::ThermalCluster& cluster) -{ - // loop per units inside the cluster - for (int unit = 0; unit < cluster.unitCount; ++unit) - { - setStartEndMntLogicConstraints(optSett, cluster, unit); - } -} + if (!unit.createStartEndVariables) + return; -void OptimizedThermalGenerator::setStartEndMntLogicConstraints(const OptProblemSettings& optSett, - const Data::ThermalCluster& cluster, - int unit) -{ - int totalMntNumber = getNumberOfMaintenances(cluster); // loop per maintenances per unit - for (int mnt = 0; mnt < totalMntNumber; ++mnt) + for (int mnt = 0; mnt < unit.maintenances.size(); ++mnt) { - setEndOfMaintenanceEventBasedOnAverageDurationOfMaintenanceEvent( - optSett, cluster, unit, mnt); - setOnceStartIsSetToOneItWillBeOneUntilEndOfOptimizationTimeHorizon( - optSett, cluster, unit, mnt); + setEndOfMaintenanceEventBasedOnAverageDurationOfMaintenanceEvent(optSett, unit, mnt); + setOnceStartIsSetToOneItWillBeOneUntilEndOfOptimizationTimeHorizon(optSett, unit, mnt); } // loop per maintenances per unit - except last one - for (int mnt = 0; mnt < totalMntNumber - 1; ++mnt) + for (int mnt = 0; mnt < unit.maintenances.size() - 1; ++mnt) { - setUpFollowingMaintenanceBasedOnAverageDurationBetweenMaintenanceEvents( - optSett, cluster, unit, mnt); - setNextMaintenanceCanNotStartBeforePreviousMaintenance(optSett, cluster, unit, mnt); + setUpFollowingMaintenanceBasedOnAverageDurationBetweenMaintenanceEvents(optSett, unit, mnt); + setNextMaintenanceCanNotStartBeforePreviousMaintenance(optSett, unit, mnt); } } void OptimizedThermalGenerator::setEndOfMaintenanceEventBasedOnAverageDurationOfMaintenanceEvent( const OptProblemSettings& optSett, - const Data::ThermalCluster& cluster, - int unit, + const Unit& unit, int mnt) { + const auto& cluster = *(unit.parentCluster); int averageMaintenanceDuration = getAverageMaintenanceDuration(cluster); for (int day = 0; day < timeHorizon_ - averageMaintenanceDuration; ++day) { - std::string ctName = "E[t+Mu][u][q] = S[t][u][q] -> [" - + std::to_string(day + optSett.firstDay) + "][" - + cluster.getFullName().to() + "." + std::to_string(unit) - + "][" + std::to_string(mnt) + "]"; + std::string ctName = "E[u][q][t+Mu] = S[u][q][t] -> [" + + cluster.getFullName().to() + "." + + std::to_string(unit.index) + "][" + std::to_string(mnt) + "][" + + std::to_string(day + optSett.firstDay) + "]"; MPConstraint* ct = solver.MakeRowConstraint(0.0, 0.0, ctName); - ct->SetCoefficient(var.day[day + averageMaintenanceDuration] - .areaMap[cluster.parentArea] - .clusterMap[&cluster] - .unitMap[unit] - .end[mnt], - 1.0); - ct->SetCoefficient( - var.day[day].areaMap[cluster.parentArea].clusterMap[&cluster].unitMap[unit].start[mnt], - -1.0); + ct->SetCoefficient(unit.maintenances[mnt].end[day + averageMaintenanceDuration], 1.0); + ct->SetCoefficient(unit.maintenances[mnt].start[day], -1.0); } return; } @@ -190,86 +114,66 @@ void OptimizedThermalGenerator::setEndOfMaintenanceEventBasedOnAverageDurationOf void OptimizedThermalGenerator:: setUpFollowingMaintenanceBasedOnAverageDurationBetweenMaintenanceEvents( const OptProblemSettings& optSett, - const Data::ThermalCluster& cluster, - int unit, + const Unit& unit, int mnt) { + const auto& cluster = *(unit.parentCluster); int averageDurationBetweenMaintenances = getAverageDurationBetweenMaintenances(cluster); for (int day = 0; day < timeHorizon_ - averageDurationBetweenMaintenances; ++day) { - std::string ctName = "S[t+Tu][u][q+1] = E[t][u][q] -> [" - + std::to_string(day + optSett.firstDay) + "][" - + cluster.getFullName().to() + "." + std::to_string(unit) - + "][" + std::to_string(mnt) + "]"; + std::string ctName = "S[u][q+1][t+Tu] = E[u][q][t] -> [" + + cluster.getFullName().to() + "." + + std::to_string(unit.index) + "][" + std::to_string(mnt) + "][" + + std::to_string(day + optSett.firstDay) + "]"; MPConstraint* ct = solver.MakeRowConstraint(0.0, 0.0, ctName); - ct->SetCoefficient(var.day[day + averageDurationBetweenMaintenances] - .areaMap[cluster.parentArea] - .clusterMap[&cluster] - .unitMap[unit] - .start[mnt + 1], - 1.0); ct->SetCoefficient( - var.day[day].areaMap[cluster.parentArea].clusterMap[&cluster].unitMap[unit].end[mnt], - -1.0); + unit.maintenances[mnt + 1].start[day + averageDurationBetweenMaintenances], 1.0); + ct->SetCoefficient(unit.maintenances[mnt].end[day], -1.0); } return; } void OptimizedThermalGenerator::setOnceStartIsSetToOneItWillBeOneUntilEndOfOptimizationTimeHorizon( const OptProblemSettings& optSett, - const Data::ThermalCluster& cluster, - int unit, + const Unit& unit, int mnt) { + const auto& cluster = *(unit.parentCluster); for (int day = 0; day < timeHorizon_ - 1; ++day) { - std::string ctName = "S[t+1][u][q] >= S[t][u][q] -> [" - + std::to_string(day + optSett.firstDay) + "][" - + cluster.getFullName().to() + "." + std::to_string(unit) - + "][" + std::to_string(mnt) + "]"; + std::string ctName = "S[u][q][t+1] >= S[u][q][t] -> [" + + cluster.getFullName().to() + "." + + std::to_string(unit.index) + "][" + std::to_string(mnt) + "][" + + std::to_string(day + optSett.firstDay) + "]"; MPConstraint* ct = solver.MakeRowConstraint(0.0 - solverDelta, solverInfinity, ctName); - ct->SetCoefficient(var.day[day + 1] - .areaMap[cluster.parentArea] - .clusterMap[&cluster] - .unitMap[unit] - .start[mnt], - 1.0); - ct->SetCoefficient( - var.day[day].areaMap[cluster.parentArea].clusterMap[&cluster].unitMap[unit].start[mnt], - -1.0); + ct->SetCoefficient(unit.maintenances[mnt].start[day + 1], 1.0); + ct->SetCoefficient(unit.maintenances[mnt].start[day], -1.0); } return; } void OptimizedThermalGenerator::setNextMaintenanceCanNotStartBeforePreviousMaintenance( const OptProblemSettings& optSett, - const Data::ThermalCluster& cluster, - int unit, + const Unit& unit, int mnt) { + const auto& cluster = *(unit.parentCluster); for (int day = 0; day < timeHorizon_; ++day) { - std::string ctName = "S[t][u][q] >= S[t][u][q+1] -> [" - + std::to_string(day + optSett.firstDay) + "][" - + cluster.getFullName().to() + "." + std::to_string(unit) - + "][" + std::to_string(mnt) + "]"; + std::string ctName = "S[u][q][t] >= S[u][q+1][t] -> [" + + cluster.getFullName().to() + "." + + std::to_string(unit.index) + "][" + std::to_string(mnt) + "][" + + std::to_string(day + optSett.firstDay) + "]"; MPConstraint* ct = solver.MakeRowConstraint(0.0 - solverDelta, solverInfinity, ctName); - ct->SetCoefficient( - var.day[day].areaMap[cluster.parentArea].clusterMap[&cluster].unitMap[unit].start[mnt], - 1.0); - ct->SetCoefficient( - var.day[day].areaMap[cluster.parentArea].clusterMap[&cluster].unitMap[unit].start[mnt - + 1], - -1.0); + ct->SetCoefficient(unit.maintenances[mnt].start[day], 1.0); + ct->SetCoefficient(unit.maintenances[mnt + 1].start[day], -1.0); } return; } -////////////////////////////// - // Maximum outputs of the units // CONSTRAINTS per days and per units - constraint-per-each-day+unit[t][u][m-sum per m] void OptimizedThermalGenerator::setMaxUnitOutputConstraints(const OptProblemSettings& optSett) @@ -284,100 +188,58 @@ void OptimizedThermalGenerator::setMaxUnitOutputConstraints(const OptProblemSett void OptimizedThermalGenerator::setMaxUnitOutputConstraints(const OptProblemSettings& optSett, int& day) { - // loop per areas inside maintenance group - for (const auto& entryWeightMap : maintenanceGroup_) + for (const auto& unit : vars.clusterUnits) { - const auto& area = *(entryWeightMap.first); - setMaxUnitOutputConstraints(optSett, day, area); + setMaxUnitOutputConstraints(optSett, day, unit); } } void OptimizedThermalGenerator::setMaxUnitOutputConstraints(const OptProblemSettings& optSett, int day, - const Data::Area& area) -{ - // loop per thermal clusters inside the area - for (const auto& clusterEntry : area.thermal.list.mapping) - { - const auto& cluster = *(clusterEntry.second); - - // we do not check if cluster.optimizeMaintenance = true here - // we add all the clusters Power inside maintenance group - if (!checkClusterExist(cluster)) - continue; - - setMaxUnitOutputConstraints(optSett, day, cluster); - } -} - -void OptimizedThermalGenerator::setMaxUnitOutputConstraints(const OptProblemSettings& optSett, - int day, - const Data::ThermalCluster& cluster) + const Unit& unit) { + const auto& cluster = *(unit.parentCluster); int optimizationDay = day + optSett.firstDay; double maxPower = getPowerOutput(cluster, optimizationDay); - // loop per units inside the cluster - for (int unit = 0; unit < cluster.unitCount; ++unit) - { - setMaxUnitOutputConstraints(optSett, day, cluster, unit, maxPower); - } -} -void OptimizedThermalGenerator::setMaxUnitOutputConstraints(const OptProblemSettings& optSett, - int day, - const Data::ThermalCluster& cluster, - int unit, - double maxPower) -{ - int optimizationDay = day + optSett.firstDay; - std::string ctName = "MaxPowerOutputConstraint[" + std::to_string(optimizationDay) + "][" - + cluster.getFullName().to() + "." + std::to_string(unit) + std::string ctName = "MaxPowerOutputConstraint[" + cluster.getFullName().to() + "." + + std::to_string(unit.index) + "][" + std::to_string(optimizationDay) + "]"; MPConstraint* ct = solver.MakeRowConstraint(0.0 - solverDelta, maxPower + solverDelta, ctName); - insertPowerVars(ct, day, cluster, unit); // re-using this method on purpose! + insertPowerVars(ct, day, unit); // re-using this method on purpose! - // we add sum[per-q](s[t][u][q]-e[t][u][q]) + // we add sum[per-q](s[u][q][t]-e[u][q][t]) // only if we have defined variables start and end for the units // if not we ebd up with: 0 <= P <= Pmax - // note we already passed check: !checkClusterExist(cluster) // so here we just check if the cluster is involved in maintenance planing - if (!(cluster.doWeGenerateTS(globalThermalTSgeneration_) && cluster.optimizeMaintenance)) + if (!unit.createStartEndVariables) return; - insertStartSum(ct, day, cluster, unit, maxPower); - insertEndSum(ct, day, cluster, unit, maxPower); + insertStartSum(ct, day, unit, maxPower); + insertEndSum(ct, day, unit, maxPower); } void OptimizedThermalGenerator::insertStartSum(MPConstraint* ct, int day, - const Data::ThermalCluster& cluster, - int unit, + const Unit& unit, double maxPower) { - int totalMntNumber = getNumberOfMaintenances(cluster); - // loop per maintenances per unit - for (int mnt = 0; mnt < totalMntNumber; ++mnt) + for (int mnt = 0; mnt < unit.maintenances.size(); ++mnt) { - ct->SetCoefficient( - var.day[day].areaMap[cluster.parentArea].clusterMap[&cluster].unitMap[unit].start[mnt], - maxPower); + ct->SetCoefficient(unit.maintenances[mnt].start[day], maxPower); } } void OptimizedThermalGenerator::insertEndSum(MPConstraint* ct, int day, - const Data::ThermalCluster& cluster, - int unit, + const Unit& unit, double maxPower) { - int totalMntNumber = getNumberOfMaintenances(cluster); // loop per maintenances per unit - for (int mnt = 0; mnt < totalMntNumber; ++mnt) + for (int mnt = 0; mnt < unit.maintenances.size(); ++mnt) { - ct->SetCoefficient( - var.day[day].areaMap[cluster.parentArea].clusterMap[&cluster].unitMap[unit].end[mnt], - -maxPower); + ct->SetCoefficient(unit.maintenances[mnt].end[day], -maxPower); } } diff --git a/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp b/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp index 5d317c35aa..942adbd698 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp @@ -24,9 +24,9 @@ void OptimizedThermalGenerator::setProblemCost(const OptProblemSettings& optSett void OptimizedThermalGenerator::setProblemEnsCost(MPObjective* objective) { // loop per day - for (const auto day : var.day) + for (const auto& ens : vars.ens) { - objective->SetCoefficient(day.Ens, ensCost_); + objective->SetCoefficient(ens, ensCost_); } return; } @@ -34,9 +34,9 @@ void OptimizedThermalGenerator::setProblemEnsCost(MPObjective* objective) void OptimizedThermalGenerator::setProblemSpillCost(MPObjective* objective) { // loop per day - for (const auto day : var.day) + for (const auto& spill : vars.spill) { - objective->SetCoefficient(day.Spill, spillCost_); + objective->SetCoefficient(spill, spillCost_); } return; } @@ -44,71 +44,25 @@ void OptimizedThermalGenerator::setProblemSpillCost(MPObjective* objective) void OptimizedThermalGenerator::setProblemPowerCost(const OptProblemSettings& optSett, MPObjective* objective) { - // loop per day - for (int day = 0; day < timeHorizon_; ++day) - { - setProblemPowerCost(optSett, objective, day); - } - return; -} - -void OptimizedThermalGenerator::setProblemPowerCost(const OptProblemSettings& optSett, - MPObjective* objective, - int day) -{ - // loop per area inside maintenance group - for (const auto& entryWeightMap : maintenanceGroup_) + // loop per units + for (const auto& unit : vars.clusterUnits) { - const auto& area = *(entryWeightMap.first); - setProblemPowerCost(optSett, objective, day, area); + setProblemPowerCost(optSett, objective, unit); } return; } void OptimizedThermalGenerator::setProblemPowerCost(const OptProblemSettings& optSett, MPObjective* objective, - int day, - const Data::Area& area) + const Unit& unit) { - // loop per thermal clusters inside the area - for (const auto& clusterEntry : area.thermal.list.mapping) - { - const auto& cluster = *(clusterEntry.second); - - // we do not check if cluster.optimizeMaintenance = true here - // we add all the clusters Power inside maintenance group - if (!checkClusterExist(cluster)) - continue; - - setProblemPowerCost(optSett, objective, day, area, cluster); - } - return; -} - -void OptimizedThermalGenerator::setProblemPowerCost(const OptProblemSettings& optSett, - MPObjective* objective, - int day, - const Data::Area& area, - const Data::ThermalCluster& cluster) -{ - double unitPowerCost = getPowerCost(cluster, day + optSett.firstDay); - // loop per unit inside the cluster - for (int unit = 0; unit < cluster.unitCount; ++unit) + // loop per day + for (int day = 0; day < unit.P.size(); ++day) { - setProblemPowerCost(objective, day, area, cluster, unit, unitPowerCost); + double unitPowerCost = getPowerCost(*(unit.parentCluster), day + optSett.firstDay); + objective->SetCoefficient(unit.P[day], unitPowerCost); } - return; -} -void OptimizedThermalGenerator::setProblemPowerCost(MPObjective* objective, - int day, - const Data::Area& area, - const Data::ThermalCluster& cluster, - int unitIndex, - double cost) -{ - objective->SetCoefficient(var.day[day].areaMap[&area].clusterMap[&cluster].unitMap[unitIndex].P, - cost); return; } diff --git a/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp b/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp index bfcc598245..1f2faac1de 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp @@ -14,129 +14,82 @@ namespace Antares::Solver::TSGenerator // this will fix some start & end variable bounds to 0 or 1 void OptimizedThermalGenerator::fixBounds() { - // loop per areas inside maintenance group - for (const auto& entryWeightMap : maintenanceGroup_) + // loop per units + for (const auto& unit : vars.clusterUnits) { - const auto& area = *(entryWeightMap.first); - fixBounds(area); + fixBounds(unit); } return; } -void OptimizedThermalGenerator::fixBounds(const Data::Area& area) +void OptimizedThermalGenerator::fixBounds(const Unit& unit) { - // loop per thermal clusters inside the area - for (const auto& clusterEntry : area.thermal.list.mapping) - { - const auto& cluster = *(clusterEntry.second); - - // check if cluster exist, do we generate + optimizeMaintenance - // create start end variables only for these clusters - bool existStartEndVar = checkClusterExist(cluster) - && cluster.doWeGenerateTS(globalThermalTSgeneration_) - && cluster.optimizeMaintenance; - if (!existStartEndVar) - continue; - - fixBounds(cluster); - } -} + if (!unit.createStartEndVariables) + return; -void OptimizedThermalGenerator::fixBounds(const Data::ThermalCluster& cluster) -{ - int totalMntNumber = getNumberOfMaintenances(cluster); - int avrMntDuration = getAverageMaintenanceDuration(cluster); + int averageMaintenanceDuration = getAverageMaintenanceDuration(*(unit.parentCluster)); - // loop per units inside the cluster - for (int unit = 0; unit < cluster.unitCount; ++unit) - { - fixBoundsFirstMnt(cluster, unit); - fixBounds(cluster, unit, totalMntNumber, avrMntDuration); - } + fixBoundsFirstMnt(unit); + fixBounds(unit, averageMaintenanceDuration); } // Bounds for the start of the first maintenance // first maintenance must start between tauLower and tauUpper -// start[tauLower-1][u][1] = 0 -// start[tauUpper][u][1] = 1 -void OptimizedThermalGenerator::fixBoundsFirstMnt(const Data::ThermalCluster& cluster, int unit) +// start[u][0][tauLower-1] = 0 +// start[u][0][tauUpper] = 1 +void OptimizedThermalGenerator::fixBoundsFirstMnt(const Unit& unit) { int earliestStartOfFirstMaintenance - = calculateUnitEarliestStartOfFirstMaintenance(cluster, unit); - int latestStartOfFirstMaintenance = calculateUnitLatestStartOfFirstMaintenance(cluster, unit); + = calculateUnitEarliestStartOfFirstMaintenance(*(unit.parentCluster), unit.index); + int latestStartOfFirstMaintenance + = calculateUnitLatestStartOfFirstMaintenance(*(unit.parentCluster), unit.index); // - // We assume here that vector "start" has member [0] + // We assume here that vector "maintenance" has member [0] // meaning: for each unit we assume we have at least one maintenance // this assumption is ok - since method calculateNumberOfMaintenances() // will never return number bellow 2 if (earliestStartOfFirstMaintenance >= 1) { - // start[tauLower-1][u][1] = 0 - var.day[earliestStartOfFirstMaintenance - 1] - .areaMap[cluster.parentArea] - .clusterMap[&cluster] - .unitMap[unit] - .start[0] - ->SetBounds(0.0, 0.0); //inclusive range + // start[u][0][tauLower-1] = 0 + unit.maintenances[0].start[earliestStartOfFirstMaintenance - 1]->SetBounds(0.0, 0.0); } - // start[tauUpper][u][1] = 1 - var.day[latestStartOfFirstMaintenance] - .areaMap[cluster.parentArea] - .clusterMap[&cluster] - .unitMap[unit] - .start[0] - ->SetBounds(1.0, 1.0); //inclusive range + // start[u][0][tauUpper] = 1 + unit.maintenances[0].start[latestStartOfFirstMaintenance]->SetBounds(1.0, 1.0); return; } -void OptimizedThermalGenerator::fixBounds(const Data::ThermalCluster& cluster, - int unit, - int totalMntNum, - int avrMntDuration) +void OptimizedThermalGenerator::fixBounds(const Unit& unit, int averageMaintenanceDuration) { // loop per maintenances of unit - for (int mnt = 0; mnt < totalMntNum; ++mnt) + for (int mnt = 0; mnt < unit.maintenances.size(); ++mnt) { - fixBoundsStartSecondMnt(cluster, unit, mnt); - fixBoundsMntEnd(cluster, unit, mnt, avrMntDuration); + fixBoundsStartSecondMnt(unit, mnt); + fixBoundsMntEnd(unit, mnt, averageMaintenanceDuration); } return; } // Ensure that units with max average duration between maintenances start their second maintenance -// start[T][u][q] = 1 -void OptimizedThermalGenerator::fixBoundsStartSecondMnt(const Data::ThermalCluster& cluster, - int unit, - int mnt) +// start[u][q][T] = 1 +void OptimizedThermalGenerator::fixBoundsStartSecondMnt(const Unit& unit, int mnt) { - var.day[timeHorizon_ - 1] - .areaMap[cluster.parentArea] - .clusterMap[&cluster] - .unitMap[unit] - .start[mnt] - ->SetBounds(1.0, 1.0); + unit.maintenances[mnt].start[timeHorizon_ - 1]->SetBounds(1.0, 1.0); } // End of the maintenance can't happen before average maintenance duration -// end[T = [0, average_maintenance_duration_per_unit]][u][q] = 0 -void OptimizedThermalGenerator::fixBoundsMntEnd(const Data::ThermalCluster& cluster, - int unit, +// end[u][q][T = [0, average_maintenance_duration_per_unit]] = 0 +void OptimizedThermalGenerator::fixBoundsMntEnd(const Unit& unit, int mnt, - int avrMntDuration) + int averageMaintenanceDuration) { - for (int day = 0; day < avrMntDuration; ++day) + for (int day = 0; day < averageMaintenanceDuration; ++day) { - var.day[day] - .areaMap[cluster.parentArea] - .clusterMap[&cluster] - .unitMap[unit] - .end[mnt] - ->SetBounds(0.0, 0.0); + unit.maintenances[mnt].end[day]->SetBounds(0.0, 0.0); } } From 80ad7dad399342cbcb6c39170cf8c0a4e37c5d6f Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Sun, 26 Nov 2023 13:17:16 +0100 Subject: [PATCH 173/315] update auxiliary structures due to future use --- .../AuxillaryStructures.h | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h index 5bd9291357..3bfc41b6c7 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h +++ b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h @@ -23,6 +23,7 @@ class OptProblemSettings final int scenario; bool solved = true; + bool isFirstStep = true; }; // this structure stores the data about optimization problem variables @@ -47,6 +48,17 @@ struct Unit // number of elements in the vector is total maintenances of unit std::vector maintenances; + + // results + // we will store results in the same structure + // however we need separate instance of this struct + // since the object that stores optimization variables is cleared after each timeStep + // and the results need to be saved/appended for each timeStep + + // number of elements in the vector is number of maintenances + // first element of the pair is start of the maintenance + // second element of the pair is randomly drawn maintenance duration + std::vector>> maintenanceResults; }; struct OptimizationProblemVariables @@ -59,12 +71,12 @@ struct OptimizationProblemVariables std::vector spill; // pointers to Spill[t] variables }; -// it is better to immediately calculate and populate structures +// it is better to immediately calculate and populate structure // that will store information about clusters -// so inside optimization problem we just retrieve these data +// so inside optimization problem we just retrieve these data with getters // not re-calculate them over and over again -// this structure stores cluster input data (optimization parameters) +// this structure stores cluster input data (optimization parameters) // that stays the same during optimizationS struct ClusterData { From 0b646e9eb89591e76b046e11f17cfd248c6cc012 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Sun, 26 Nov 2023 13:28:05 +0100 Subject: [PATCH 174/315] add separate cpp-s for post optimization --- src/solver/ts-generator/CMakeLists.txt | 2 ++ .../OptimizedGenerator.cpp | 1 + .../PostScenarioOptimization.cpp | 10 ++++++++++ .../PostTimeStepOptimization.cpp | 11 +++++++++++ 4 files changed, 24 insertions(+) create mode 100644 src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp create mode 100644 src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp diff --git a/src/solver/ts-generator/CMakeLists.txt b/src/solver/ts-generator/CMakeLists.txt index 4c0fa390fd..7163edd6a6 100644 --- a/src/solver/ts-generator/CMakeLists.txt +++ b/src/solver/ts-generator/CMakeLists.txt @@ -26,6 +26,8 @@ set(SRC_OPTIMIZEDGENERATORS optimized-thermal-generator/ResetProblem.cpp optimized-thermal-generator/SolveProbem.cpp optimized-thermal-generator/PrintProblemVarRes.cpp + optimized-thermal-generator/PostTimeStepOptimization.cpp + optimized-thermal-generator/PostScenarioOptimization.cpp ) source_group("ts-generator\\optimized-thermal-generator" FILES ${SRC_OPTIMIZEDGENERATORS}) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp index 240c819cf2..1255df0eb4 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp @@ -35,6 +35,7 @@ void OptimizedThermalGenerator::GenerateOptimizedThermalTimeSeries() // Update the time values for the next iteration optSett.firstDay += timeStep_; optSett.lastDay += timeStep_; + optSett.isFirstStep = false; } saveScenarioResults(optSett); } diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp new file mode 100644 index 0000000000..2478377ec4 --- /dev/null +++ b/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp @@ -0,0 +1,10 @@ +// +// Created by milos on 14/11/23. +// + +#include "OptimizedGenerator.h" + +namespace Antares::Solver::TSGenerator +{ + +} // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp new file mode 100644 index 0000000000..2c5a3841ac --- /dev/null +++ b/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp @@ -0,0 +1,11 @@ +// +// Created by milos on 14/11/23. +// + +#include "OptimizedGenerator.h" + +namespace Antares::Solver::TSGenerator +{ + + +} // namespace Antares::Solver::TSGenerator From 6eca1cb9f86e6562e2c0d31ba9a90eeb397d1945 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Sun, 26 Nov 2023 13:45:44 +0100 Subject: [PATCH 175/315] structure for postScenarioOptimization --- .../OptimizedGenerator.cpp | 27 +-------------- .../OptimizedGenerator.h | 9 +++-- .../PostScenarioOptimization.cpp | 34 +++++++++++++++++++ .../SolveProbem.cpp | 9 +---- 4 files changed, 42 insertions(+), 37 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp index 1255df0eb4..5377b57c06 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp @@ -37,7 +37,7 @@ void OptimizedThermalGenerator::GenerateOptimizedThermalTimeSeries() optSett.lastDay += timeStep_; optSett.isFirstStep = false; } - saveScenarioResults(optSett); + postScenarioOptimization(optSett); } } @@ -69,29 +69,4 @@ void OptimizedThermalGenerator::allocateWhereToWriteTs() return; } -void OptimizedThermalGenerator::saveScenarioResults(const OptProblemSettings& optSett) -{ - // do not save if optimization failed at some step - if (!optSett.solved) - return; - - // create a method to calculate all the Cluster outputs in MW - // using vectors of std::pairs per each cluster-unit - // that will contain maintenance start and duration - - // save results - - int colSaveFrom = optSett.scenario * scenarioLength_; - int colSaveTo = colSaveFrom + scenarioLength_ - 1; - - // loop through all areas and clusters and write results - - /* - // do not forget archive!! - if (archive) - writeResultsToDisk(area, cluster); - - */ -} - } // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 4b6de82fb7..9ff7b33f9c 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -103,9 +103,6 @@ class OptimizedThermalGenerator : public GeneratorTempData // reset problem and variable structure void resetProblem(); - // collect and store results from firstDay-lastDay - void appendStepResults(); - // print functions for debugging void printAllVariables(); void printObjectiveFunction(MPObjective* objective); @@ -116,8 +113,14 @@ class OptimizedThermalGenerator : public GeneratorTempData // Functions called in main method: void allocateWhereToWriteTs(); bool runOptimizationProblem(OptProblemSettings& optSett); + + // post-scenario optimization methods + void postScenarioOptimization(OptProblemSettings& optSett); + void calculateScenarioResults(const OptProblemSettings& optSett); void saveScenarioResults(const OptProblemSettings& optSett); + // post-timeStep optimization methods + // Calculate parameters methods - per maintenance group void setMaintenanceGroupParameters(); bool checkMaintenanceGroupParameters(); diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp index 2478377ec4..3305d24550 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp @@ -7,4 +7,38 @@ namespace Antares::Solver::TSGenerator { +void OptimizedThermalGenerator::postScenarioOptimization(OptProblemSettings& optSett) +{ + // do not save if optimization failed at some step + if (!optSett.solved) + return; + + calculateScenarioResults(optSett); + saveScenarioResults(optSett); + + return; +} + +void OptimizedThermalGenerator::calculateScenarioResults(const OptProblemSettings& optSett) +{ + return; +} + +void OptimizedThermalGenerator::saveScenarioResults(const OptProblemSettings& optSett) +{ + // save results + + int colSaveFrom = optSett.scenario * scenarioLength_; + int colSaveTo = colSaveFrom + scenarioLength_ - 1; + + // loop through all areas and clusters and write results + + /* + // do not forget archive!! + if (archive) + writeResultsToDisk(area, cluster); + + */ +} + } // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/SolveProbem.cpp b/src/solver/ts-generator/optimized-thermal-generator/SolveProbem.cpp index 0d9bcad97b..6833448537 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/SolveProbem.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/SolveProbem.cpp @@ -18,7 +18,7 @@ bool OptimizedThermalGenerator::runOptimizationProblem(OptProblemSettings& optSe if (!solveProblem(optSett)) return false; printProblemVarAndResults(); - appendStepResults(); + // appendStepResults(); return true; } @@ -41,11 +41,4 @@ bool OptimizedThermalGenerator::solveProblem(OptProblemSettings& optSett) return true; } -// TODO CR27: move this method somewhere else -// collect and store results form firstDay-lastDay -void OptimizedThermalGenerator::appendStepResults() -{ - return; -} - } // namespace Antares::Solver::TSGenerator From 1bb69bc0d6efff71da59a5bd60396c0b08aa7cc8 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Sun, 26 Nov 2023 13:57:48 +0100 Subject: [PATCH 176/315] post-timeStep optimization struct --- .../CalculateParameters.cpp | 15 ----------- .../OptimizedGenerator.h | 4 ++- .../PostTimeStepOptimization.cpp | 27 +++++++++++++++++++ .../SolveProbem.cpp | 3 +-- 4 files changed, 31 insertions(+), 18 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp index 8d60c7df7c..1ad2b1b30b 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp @@ -377,21 +377,6 @@ int OptimizedThermalGenerator::calculateUnitLatestStartOfFirstMaintenance( } } -// re-calculate parameters -void OptimizedThermalGenerator::reCalculateDaysSinceLastMnt(const OptProblemSettings& optSett) -{ - if (optSett.scenario == 0 && optSett.firstDay == 0) - return; - if (optSett.scenario != 0 && optSett.firstDay == 0) - { - // we are back in first step, but not first scenario we have messed up our values - // we need to re-do - // clusterVariables[&cluster].daysSinceLastMnt = cluster.daysSinceLastMaintenance; - // for all areas and clusters - } - // TODO CR27: re-calculate days since last maintenance inputs if necessary -} - // auxillary functions - for parameter calculations std::array OptimizedThermalGenerator::calculateDailySums( const std::array& hourlyValues) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 9ff7b33f9c..a7ed0a08a1 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -120,6 +120,9 @@ class OptimizedThermalGenerator : public GeneratorTempData void saveScenarioResults(const OptProblemSettings& optSett); // post-timeStep optimization methods + void postTimeStepOptimization(OptProblemSettings& optSett); + void appendTimeStepResults(const OptProblemSettings& optSett); + void reCalculateDaysSinceLastMnt(const OptProblemSettings& optSett); // Calculate parameters methods - per maintenance group void setMaintenanceGroupParameters(); @@ -150,7 +153,6 @@ class OptimizedThermalGenerator : public GeneratorTempData uint unitIndex); int calculateUnitLatestStartOfFirstMaintenance(const Data::ThermalCluster& cluster, uint unitIndex); - void reCalculateDaysSinceLastMnt(const OptProblemSettings& optSett); // auxillary functions static std::array calculateDailySums( diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp index 2c5a3841ac..376128a419 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp @@ -7,5 +7,32 @@ namespace Antares::Solver::TSGenerator { +void OptimizedThermalGenerator::postTimeStepOptimization(OptProblemSettings& optSett) +{ + appendTimeStepResults(optSett); + reCalculateDaysSinceLastMnt(optSett); + return; +} + +// save/append optimization results form range 0-timeStep +void OptimizedThermalGenerator::appendTimeStepResults(const OptProblemSettings& optSett) +{ + return; +} + +// re-calculate parameters +void OptimizedThermalGenerator::reCalculateDaysSinceLastMnt(const OptProblemSettings& optSett) +{ + if (optSett.scenario == 0 && optSett.isFirstStep) + return; + if (optSett.scenario != 0 && optSett.isFirstStep) + { + // we are back in first step, but not first scenario we have messed up our values + // we need to re-do + // clusterVariables[&cluster].daysSinceLastMnt = cluster.daysSinceLastMaintenance; + // for all areas and clusters + } + // TODO CR27: re-calculate days since last maintenance inputs if necessary +} } // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/SolveProbem.cpp b/src/solver/ts-generator/optimized-thermal-generator/SolveProbem.cpp index 6833448537..207e2734c5 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/SolveProbem.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/SolveProbem.cpp @@ -10,7 +10,6 @@ namespace Antares::Solver::TSGenerator bool OptimizedThermalGenerator::runOptimizationProblem(OptProblemSettings& optSett) { resetProblem(); - reCalculateDaysSinceLastMnt(optSett); buildProblemVariables(optSett); fixBounds(); buildProblemConstraints(optSett); @@ -18,7 +17,7 @@ bool OptimizedThermalGenerator::runOptimizationProblem(OptProblemSettings& optSe if (!solveProblem(optSett)) return false; printProblemVarAndResults(); - // appendStepResults(); + postTimeStepOptimization(optSett); return true; } From 07faba872bc59078a54fc374fe57470b0c348520 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Sun, 26 Nov 2023 13:59:28 +0100 Subject: [PATCH 177/315] comments --- .../optimized-thermal-generator/OptimizedGenerator.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index a7ed0a08a1..7df6cfc032 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -220,7 +220,8 @@ class OptimizedThermalGenerator : public GeneratorTempData ~OptimizedThermalGenerator() = default; - // Main functions - loop per scenarios and through the scenario length step by step + // Main functions - loop per scenarios and + // through the scenario length step by step // (moving window) void GenerateOptimizedThermalTimeSeries(); }; From 427b3418baea1c96bab637f10a4f60e8fe059189 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Sun, 26 Nov 2023 14:09:55 +0100 Subject: [PATCH 178/315] post scenario optimization clear storage --- .../optimized-thermal-generator/OptimizedGenerator.h | 2 ++ .../PostScenarioOptimization.cpp | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 7df6cfc032..51fc6eedef 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -118,6 +118,7 @@ class OptimizedThermalGenerator : public GeneratorTempData void postScenarioOptimization(OptProblemSettings& optSett); void calculateScenarioResults(const OptProblemSettings& optSett); void saveScenarioResults(const OptProblemSettings& optSett); + void resetResultStorage(); // post-timeStep optimization methods void postTimeStepOptimization(OptProblemSettings& optSett); @@ -182,6 +183,7 @@ class OptimizedThermalGenerator : public GeneratorTempData std::array residualLoadDailyValues_; MaintenanceData maintenanceData; OptimizationProblemVariables vars; + std::vector scenarioResults; // MPSolver instance MPSolver solver; diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp index 3305d24550..4706cbcbce 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp @@ -15,6 +15,7 @@ void OptimizedThermalGenerator::postScenarioOptimization(OptProblemSettings& opt calculateScenarioResults(optSett); saveScenarioResults(optSett); + resetResultStorage(); return; } @@ -41,4 +42,10 @@ void OptimizedThermalGenerator::saveScenarioResults(const OptProblemSettings& op */ } +void OptimizedThermalGenerator::resetResultStorage() +{ + scenarioResults.clear(); + return; +} + } // namespace Antares::Solver::TSGenerator From a9099ca4b4ae1292b62d91b1f94c56960f59bdbd Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Sun, 26 Nov 2023 14:22:03 +0100 Subject: [PATCH 179/315] add comments in OptimizedGenerator for clearer picture --- .../OptimizedGenerator.h | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 51fc6eedef..8898e8632b 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -22,7 +22,8 @@ namespace Antares::Solver::TSGenerator class OptimizedThermalGenerator : public GeneratorTempData { private: - // optimization problem construction methods + + /* ===================OPTIMIZATION=================== */ // functions to build problem variables void buildProblemVariables(const OptProblemSettings& optSett); @@ -110,10 +111,19 @@ class OptimizedThermalGenerator : public GeneratorTempData void printResults(); void printProblemVarAndResults(); + + /* ===================END-OPTIMIZATION=================== */ + + /* ===================MAIN=================== */ + // Functions called in main method: void allocateWhereToWriteTs(); bool runOptimizationProblem(OptProblemSettings& optSett); + /* ===================END-MAIN=================== */ + + /* ===================POST-OPTIMIZATION=================== */ + // post-scenario optimization methods void postScenarioOptimization(OptProblemSettings& optSett); void calculateScenarioResults(const OptProblemSettings& optSett); @@ -125,6 +135,10 @@ class OptimizedThermalGenerator : public GeneratorTempData void appendTimeStepResults(const OptProblemSettings& optSett); void reCalculateDaysSinceLastMnt(const OptProblemSettings& optSett); + /* ===================END-POST-OPTIMIZATION=================== */ + + /* ===================CALCULATE-OPTIMIZATION-PARAMETERS=================== */ + // Calculate parameters methods - per maintenance group void setMaintenanceGroupParameters(); bool checkMaintenanceGroupParameters(); @@ -171,6 +185,10 @@ class OptimizedThermalGenerator : public GeneratorTempData const Data::Area& area); std::array calculateAverageRenewableTsClusters(const Data::Area& area); + /* ===================END-CALCULATE-OPTIMIZATION-PARAMETERS=================== */ + + /* ===================CLASS-VARIABLES=================== */ + // variables Data::MaintenanceGroup& maintenanceGroup_; bool globalThermalTSgeneration_; @@ -189,6 +207,8 @@ class OptimizedThermalGenerator : public GeneratorTempData MPSolver solver; double solverInfinity; + /* ===================END-CLASS-VARIABLES=================== */ + public: explicit OptimizedThermalGenerator(Data::Study& study, Data::MaintenanceGroup& maintenanceGroup, From 3c1a9e1f4bf24726fdbf62598126349d559e71c3 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Sun, 26 Nov 2023 14:36:13 +0100 Subject: [PATCH 180/315] TODO-s refactoring ideas --- .../OptimizedGenerator.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 8898e8632b..2acbb21584 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -199,7 +199,21 @@ class OptimizedThermalGenerator : public GeneratorTempData double ensCost_; double spillCost_; std::array residualLoadDailyValues_; + /* + TODO CR27: + phase two - idea for refactoring - + make MaintenanceData a class + and then move all methods for optimization problem parameters calculation to that class + in addition lots of parameters calculation methods + (all auxillary functions + calculate parameters methods - per cluster) + do not need to be class - methods - just make them free functions! + */ MaintenanceData maintenanceData; + /* + TODO CR27: + same for OptimizationProblemVariables - maybe new class + and move optimization methods away from here + */ OptimizationProblemVariables vars; std::vector scenarioResults; From 1ca156fb7a6434ce92027bceb5b74e48ec566d18 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Sun, 26 Nov 2023 15:09:44 +0100 Subject: [PATCH 181/315] create instance for appending scenario results step by step --- .../optimized-thermal-generator/CreateVariables.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp b/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp index ec48f68020..992b00ae07 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp @@ -79,7 +79,7 @@ void OptimizedThermalGenerator::buildUnitPowerOutputVariables(const OptProblemSe // add new Unit vars.clusterUnits.push_back(Unit()); - // but we do not know the total count + // but we do not know the total unit count // so always retrieve the last one auto& unitRef = vars.clusterUnits.back(); @@ -88,6 +88,11 @@ void OptimizedThermalGenerator::buildUnitPowerOutputVariables(const OptProblemSe unitRef.index = unit; // local count inside the cluster unitRef.createStartEndVariables = true; + // if we are in the first step + // lets add Unit, with inputs, to the scenarioResults + if (optSett.isFirstStep) + scenarioResults.push_back(vars.clusterUnits.back()); + // loop per day for (int day = 0; day < timeHorizon_; ++day) { @@ -104,6 +109,7 @@ void OptimizedThermalGenerator::buildUnitPowerOutputVariables(const OptProblemSe if (!(cluster.doWeGenerateTS(globalThermalTSgeneration_) && cluster.optimizeMaintenance)) { unitRef.createStartEndVariables = false; + scenarioResults.back().createStartEndVariables = false; return; } From 8ded34c82ddcadeb54a7c669c625ef8c4b331b5a Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Sun, 26 Nov 2023 15:17:07 +0100 Subject: [PATCH 182/315] update todo comments --- .../optimized-thermal-generator/OptimizedGenerator.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 2acbb21584..5abdb46500 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -205,7 +205,8 @@ class OptimizedThermalGenerator : public GeneratorTempData make MaintenanceData a class and then move all methods for optimization problem parameters calculation to that class in addition lots of parameters calculation methods - (all auxillary functions + calculate parameters methods - per cluster) + (all auxillary functions + calculate parameters methods - per cluster + + calculate Average time-series functions) do not need to be class - methods - just make them free functions! */ MaintenanceData maintenanceData; From 739b7206db83171e851b5c96f2a0208997d9f7d8 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Sun, 26 Nov 2023 15:31:06 +0100 Subject: [PATCH 183/315] extract auxiliary methods out of the class --- .../CalculateParameters.cpp | 123 +++++++++--------- .../OptimizedGenerator.h | 16 +-- 2 files changed, 69 insertions(+), 70 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp index 1ad2b1b30b..7703dca442 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp @@ -377,68 +377,6 @@ int OptimizedThermalGenerator::calculateUnitLatestStartOfFirstMaintenance( } } -// auxillary functions - for parameter calculations -std::array OptimizedThermalGenerator::calculateDailySums( - const std::array& hourlyValues) -{ - std::array dailyValues; - auto hours_iter = hourlyValues.begin(); - - for (double& day_sum : dailyValues) - { - day_sum = std::accumulate(hours_iter, hours_iter + 24, 0.0); - hours_iter += 24; - } - - return dailyValues; -} - -std::array OptimizedThermalGenerator::calculateAverageTs( - const Matrix& tsValue, - const Matrix& tsNumbers) -{ - // define array - std::array averageTs = {}; - // calculate sum - for (std::size_t year = 0; year < tsNumbers.height; ++year) - { - for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) - { - averageTs[row] += tsValue[tsNumbers[0][year]][row]; - } - } - // calculate mean - for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) - { - averageTs[row] = averageTs[row] / tsNumbers.height; - } - // return - return averageTs; -} - -bool OptimizedThermalGenerator::checkClusterExist(const Data::ThermalCluster& cluster) -{ - if (!cluster.prepro) - { - logs.error() << "Cluster: " << cluster.getFullName() - << ": The timeseries will not be regenerated. All data " - "related to the ts-generator for " - << "'thermal' have been released."; - return false; - } - - if (0 == cluster.unitCount || 0 == cluster.nominalCapacity) - { - return false; - } - return true; -} - -int OptimizedThermalGenerator::dayOfTheYear(int optimizationDay) -{ - return optimizationDay % DAYS_PER_YEAR; -} - // calculate Average time-series functions std::array OptimizedThermalGenerator::calculateAverageLoadTs( const Data::Area& area) @@ -511,4 +449,65 @@ std::array OptimizedThermalGenerator::calculateAverageRe } } +// auxillary functions - for parameter calculations +std::array calculateDailySums( + const std::array& hourlyValues) +{ + std::array dailyValues; + auto hours_iter = hourlyValues.begin(); + + for (double& day_sum : dailyValues) + { + day_sum = std::accumulate(hours_iter, hours_iter + 24, 0.0); + hours_iter += 24; + } + + return dailyValues; +} + +std::array calculateAverageTs(const Matrix& tsValue, + const Matrix& tsNumbers) +{ + // define array + std::array averageTs = {}; + // calculate sum + for (std::size_t year = 0; year < tsNumbers.height; ++year) + { + for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) + { + averageTs[row] += tsValue[tsNumbers[0][year]][row]; + } + } + // calculate mean + for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) + { + averageTs[row] = averageTs[row] / tsNumbers.height; + } + // return + return averageTs; +} + +bool checkClusterExist(const Data::ThermalCluster& cluster) +{ + if (!cluster.prepro) + { + logs.error() << "Cluster: " << cluster.getFullName() + << ": The timeseries will not be regenerated. All data " + "related to the ts-generator for " + << "'thermal' have been released."; + return false; + } + + if (0 == cluster.unitCount || 0 == cluster.nominalCapacity) + { + return false; + } + return true; +} + +int dayOfTheYear(int optimizationDay) +{ + return optimizationDay % DAYS_PER_YEAR; +} + } // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 5abdb46500..ed0f4278c3 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -169,14 +169,6 @@ class OptimizedThermalGenerator : public GeneratorTempData int calculateUnitLatestStartOfFirstMaintenance(const Data::ThermalCluster& cluster, uint unitIndex); - // auxillary functions - static std::array calculateDailySums( - const std::array& hourlyValues); - std::array calculateAverageTs(const Matrix& tsValue, - const Matrix& tsNumbers); - bool checkClusterExist(const Data::ThermalCluster& cluster); - int dayOfTheYear(int optimizationDay); - // calculate Average time-series functions std::array calculateAverageLoadTs(const Data::Area& area); std::array calculateAverageRorTs(const Data::Area& area); @@ -268,4 +260,12 @@ class OptimizedThermalGenerator : public GeneratorTempData template void printColumnToFile(const std::vector>& data, const std::string& filename); +// auxillary functions +std::array calculateDailySums( + const std::array& hourlyValues); +std::array calculateAverageTs(const Matrix& tsValue, + const Matrix& tsNumbers); +bool checkClusterExist(const Data::ThermalCluster& cluster); +int dayOfTheYear(int optimizationDay); + } // namespace Antares::Solver::TSGenerator \ No newline at end of file From 998aba1afa132ee2098e84c802fc2a30a7fa88c8 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Sun, 26 Nov 2023 15:47:06 +0100 Subject: [PATCH 184/315] move calculate Average time-series functions out of class --- .../CalculateParameters.cpp | 19 ++++++++----------- .../OptimizedGenerator.h | 17 +++++++++-------- 2 files changed, 17 insertions(+), 19 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp index 7703dca442..b3c8c72d05 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp @@ -121,7 +121,7 @@ void OptimizedThermalGenerator::calculateResidualLoad() auto tmpLoad = calculateAverageLoadTs(area); auto tmpRor = calculateAverageRorTs(area); - auto tmpRenewable = calculateAverageRenewableTs(area); + auto tmpRenewable = calculateAverageRenewableTs(study.parameters.renewableGeneration, area); for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) { @@ -378,8 +378,7 @@ int OptimizedThermalGenerator::calculateUnitLatestStartOfFirstMaintenance( } // calculate Average time-series functions -std::array OptimizedThermalGenerator::calculateAverageLoadTs( - const Data::Area& area) +std::array calculateAverageLoadTs(const Data::Area& area) { // we assume ready-make TS - (pre-check exist for this!) const auto tsValues = area.load.series.timeSeries; @@ -387,16 +386,14 @@ std::array OptimizedThermalGenerator::calculateAverageLo return calculateAverageTs(tsValues, tsNumbers); } -std::array OptimizedThermalGenerator::calculateAverageRorTs( - const Data::Area& area) +std::array calculateAverageRorTs(const Data::Area& area) { const auto tsValues = area.hydro.series->ror.timeSeries; auto tsNumbers = area.hydro.series->ror.timeseriesNumbers; return calculateAverageTs(tsValues, tsNumbers); } -std::array OptimizedThermalGenerator::calculateAverageRenewableTsAggregated( - const Data::Area& area) +std::array calculateAverageRenewableTsAggregated(const Data::Area& area) { std::array averageTsSolar = calculateAverageTs(area.solar.series.timeSeries, area.solar.series.timeseriesNumbers); @@ -411,8 +408,7 @@ std::array OptimizedThermalGenerator::calculateAverageRe return averageTsRenewable; } -std::array OptimizedThermalGenerator::calculateAverageRenewableTsClusters( - const Data::Area& area) +std::array calculateAverageRenewableTsClusters(const Data::Area& area) { std::array averageTsRenewable = {}; for (const auto& entryCluster : area.renewable.clusters) @@ -436,10 +432,11 @@ std::array OptimizedThermalGenerator::calculateAverageRe return averageTsRenewable; } -std::array OptimizedThermalGenerator::calculateAverageRenewableTs( +std::array calculateAverageRenewableTs( + const Data::Parameters::RenewableGeneration modelingType, const Data::Area& area) { - if (study.parameters.renewableGeneration.isAggregated()) + if (modelingType.isAggregated()) { return calculateAverageRenewableTsAggregated(area); } diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index ed0f4278c3..ae160c389e 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -169,14 +169,6 @@ class OptimizedThermalGenerator : public GeneratorTempData int calculateUnitLatestStartOfFirstMaintenance(const Data::ThermalCluster& cluster, uint unitIndex); - // calculate Average time-series functions - std::array calculateAverageLoadTs(const Data::Area& area); - std::array calculateAverageRorTs(const Data::Area& area); - std::array calculateAverageRenewableTs(const Data::Area& area); - std::array calculateAverageRenewableTsAggregated( - const Data::Area& area); - std::array calculateAverageRenewableTsClusters(const Data::Area& area); - /* ===================END-CALCULATE-OPTIMIZATION-PARAMETERS=================== */ /* ===================CLASS-VARIABLES=================== */ @@ -268,4 +260,13 @@ std::array calculateAverageTs(const Matrix& tsVa bool checkClusterExist(const Data::ThermalCluster& cluster); int dayOfTheYear(int optimizationDay); +// calculate Average time-series functions +std::array calculateAverageLoadTs(const Data::Area& area); +std::array calculateAverageRorTs(const Data::Area& area); +std::array calculateAverageRenewableTs( + const Data::Parameters::RenewableGeneration modelingType, + const Data::Area& area); +std::array calculateAverageRenewableTsAggregated(const Data::Area& area); +std::array calculateAverageRenewableTsClusters(const Data::Area& area); + } // namespace Antares::Solver::TSGenerator \ No newline at end of file From 5eaca86e6f57885dc7badbca9b34513fe8aa6d90 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Sun, 26 Nov 2023 15:52:45 +0100 Subject: [PATCH 185/315] extract 2 calculate parameters methods - per cluster out of the class --- .../CalculateParameters.cpp | 61 +++++++++---------- .../OptimizedGenerator.h | 6 +- 2 files changed, 34 insertions(+), 33 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp index b3c8c72d05..da5a841821 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp @@ -173,37 +173,6 @@ void OptimizedThermalGenerator::setClusterData() } // calculate parameters methods - per cluster -int OptimizedThermalGenerator::calculateNumberOfMaintenances(const Data::ThermalCluster& cluster, - int timeHorizon) -{ - // timeHorizon cannot be 0. The whole maintenance group would be skipped if this happened - // on the other hand interPoPeriod can be 0. So we say at least 2 maintenance if this happens - // actually this cannot happen because checkMaintenanceGroupParameters() will kill it by now - if (cluster.interPoPeriod == 0) - { - logs.warning() << "Cluster: " << cluster.getFullName() - << "has interPoPeriod = 0. Number of maintenances for all units inside this " - "cluster will be set to 2"; - return minNumberOfMaintenances; - } - - return std::max(timeHorizon / cluster.interPoPeriod, minNumberOfMaintenances); // floor -} - -int OptimizedThermalGenerator::calculateAverageMaintenanceDuration( - const Data::ThermalCluster& cluster) -{ - double sum = 0.0; - for (std::size_t row = 0; row < DAYS_PER_YEAR; ++row) - { - sum += cluster.prepro->data[Data::PreproThermal::poDuration][row]; - } - // poDuration in Antares cannot be below 1.0 - // so it is redundant to check here if return value is above 1.0 - // that is why I did not use std::max() - return sum / static_cast(DAYS_PER_YEAR); -} - std::array OptimizedThermalGenerator::calculateMaxUnitOutput( const Data::ThermalCluster& cluster) { @@ -507,4 +476,34 @@ int dayOfTheYear(int optimizationDay) return optimizationDay % DAYS_PER_YEAR; } +// calculate parameters methods - per cluster +int calculateNumberOfMaintenances(const Data::ThermalCluster& cluster, int timeHorizon) +{ + // timeHorizon cannot be 0. The whole maintenance group would be skipped if this happened + // on the other hand interPoPeriod can be 0. So we say at least 2 maintenance if this happens + // actually this cannot happen because checkMaintenanceGroupParameters() will kill it by now + if (cluster.interPoPeriod == 0) + { + logs.warning() << "Cluster: " << cluster.getFullName() + << "has interPoPeriod = 0. Number of maintenances for all units inside this " + "cluster will be set to 2"; + return minNumberOfMaintenances; + } + + return std::max(timeHorizon / cluster.interPoPeriod, minNumberOfMaintenances); // floor +} + +int calculateAverageMaintenanceDuration(const Data::ThermalCluster& cluster) +{ + double sum = 0.0; + for (std::size_t row = 0; row < DAYS_PER_YEAR; ++row) + { + sum += cluster.prepro->data[Data::PreproThermal::poDuration][row]; + } + // poDuration in Antares cannot be below 1.0 + // so it is redundant to check here if return value is above 1.0 + // that is why I did not use std::max() + return sum / static_cast(DAYS_PER_YEAR); +} + } // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index ae160c389e..3657aaa3d4 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -148,8 +148,6 @@ class OptimizedThermalGenerator : public GeneratorTempData void setClusterData(); // calculate parameters methods - per cluster - int calculateNumberOfMaintenances(const Data::ThermalCluster& cluster, int timeHorizon); - int calculateAverageMaintenanceDuration(const Data::ThermalCluster& cluster); static std::array calculateMaxUnitOutput( const Data::ThermalCluster& cluster); static std::array calculateAvrUnitDailyCost( @@ -269,4 +267,8 @@ std::array calculateAverageRenewableTs( std::array calculateAverageRenewableTsAggregated(const Data::Area& area); std::array calculateAverageRenewableTsClusters(const Data::Area& area); +// calculate parameters methods - per cluster +int calculateNumberOfMaintenances(const Data::ThermalCluster& cluster, int timeHorizon); +int calculateAverageMaintenanceDuration(const Data::ThermalCluster& cluster); + } // namespace Antares::Solver::TSGenerator \ No newline at end of file From 6af86e9d603a49406bcb224fdb88eddafaecaa88 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Sun, 26 Nov 2023 15:58:20 +0100 Subject: [PATCH 186/315] move second part of calculate parameters methods - per cluster out of the class --- .../CalculateParameters.cpp | 86 +++++++++---------- .../OptimizedGenerator.h | 12 +-- 2 files changed, 43 insertions(+), 55 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp index da5a841821..2646426043 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp @@ -172,51 +172,6 @@ void OptimizedThermalGenerator::setClusterData() return; } -// calculate parameters methods - per cluster -std::array OptimizedThermalGenerator::calculateMaxUnitOutput( - const Data::ThermalCluster& cluster) -{ - std::array maxOutputDailyValues = {}; - std::array maxOutputHourlyValues = {}; - - // transfer to array - for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) - { - maxOutputHourlyValues[row] - = cluster.modulation[Data::ThermalModulation::thermalModulationCapacity][row]; - } - - maxOutputDailyValues = calculateDailySums(maxOutputHourlyValues); - // multiply by per unit power (nominal capacity) - for (double& num : maxOutputDailyValues) - { - num *= cluster.nominalCapacity; - } - return maxOutputDailyValues; -} - -std::array OptimizedThermalGenerator::calculateAvrUnitDailyCost( - const Data::ThermalCluster& cluster) -{ - std::array avrCostDailyValues = {}; - std::array costHourlyValues = {}; - - // transfer to array - for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) - { - costHourlyValues[row] - = cluster.modulation[Data::ThermalModulation::thermalModulationMarketBid][row]; - } - - avrCostDailyValues = calculateDailySums(costHourlyValues); - // multiply by per unit/cluster market bid cost + average this on 24 hours - for (double& num : avrCostDailyValues) - { - num *= cluster.marketBidCost / 24.0; - } - return avrCostDailyValues; -} - // Getters double OptimizedThermalGenerator::getPowerCost(const Data::ThermalCluster& cluster, int optimizationDay) @@ -506,4 +461,45 @@ int calculateAverageMaintenanceDuration(const Data::ThermalCluster& cluster) return sum / static_cast(DAYS_PER_YEAR); } +std::array calculateMaxUnitOutput(const Data::ThermalCluster& cluster) +{ + std::array maxOutputDailyValues = {}; + std::array maxOutputHourlyValues = {}; + + // transfer to array + for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) + { + maxOutputHourlyValues[row] + = cluster.modulation[Data::ThermalModulation::thermalModulationCapacity][row]; + } + + maxOutputDailyValues = calculateDailySums(maxOutputHourlyValues); + // multiply by per unit power (nominal capacity) + for (double& num : maxOutputDailyValues) + { + num *= cluster.nominalCapacity; + } + return maxOutputDailyValues; +} + +std::array calculateAvrUnitDailyCost(const Data::ThermalCluster& cluster) +{ + std::array avrCostDailyValues = {}; + std::array costHourlyValues = {}; + + // transfer to array + for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) + { + costHourlyValues[row] + = cluster.modulation[Data::ThermalModulation::thermalModulationMarketBid][row]; + } + + avrCostDailyValues = calculateDailySums(costHourlyValues); + // multiply by per unit/cluster market bid cost + average this on 24 hours + for (double& num : avrCostDailyValues) + { + num *= cluster.marketBidCost / 24.0; + } + return avrCostDailyValues; +} } // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 3657aaa3d4..ac883e4514 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -147,12 +147,6 @@ class OptimizedThermalGenerator : public GeneratorTempData void calculateResidualLoad(); void setClusterData(); - // calculate parameters methods - per cluster - static std::array calculateMaxUnitOutput( - const Data::ThermalCluster& cluster); - static std::array calculateAvrUnitDailyCost( - const Data::ThermalCluster& cluster); - // getters double getPowerCost(const Data::ThermalCluster& cluster, int optimizationDay); double getPowerOutput(const Data::ThermalCluster& cluster, int optimizationDay); @@ -186,10 +180,6 @@ class OptimizedThermalGenerator : public GeneratorTempData phase two - idea for refactoring - make MaintenanceData a class and then move all methods for optimization problem parameters calculation to that class - in addition lots of parameters calculation methods - (all auxillary functions + calculate parameters methods - per cluster - + calculate Average time-series functions) - do not need to be class - methods - just make them free functions! */ MaintenanceData maintenanceData; /* @@ -270,5 +260,7 @@ std::array calculateAverageRenewableTsClusters(const Dat // calculate parameters methods - per cluster int calculateNumberOfMaintenances(const Data::ThermalCluster& cluster, int timeHorizon); int calculateAverageMaintenanceDuration(const Data::ThermalCluster& cluster); +std::array calculateMaxUnitOutput(const Data::ThermalCluster& cluster); +std::array calculateAvrUnitDailyCost(const Data::ThermalCluster& cluster); } // namespace Antares::Solver::TSGenerator \ No newline at end of file From 3b96580b9b279e18f8c211c165ef6601fa3e39c5 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Sun, 26 Nov 2023 16:09:45 +0100 Subject: [PATCH 187/315] move free functions definition to separate cpp --- src/solver/ts-generator/CMakeLists.txt | 1 + .../AuxillaryFreeFunctions.cpp | 212 ++++++++++++++++++ .../CalculateParameters.cpp | 201 ----------------- 3 files changed, 213 insertions(+), 201 deletions(-) create mode 100644 src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.cpp diff --git a/src/solver/ts-generator/CMakeLists.txt b/src/solver/ts-generator/CMakeLists.txt index 7163edd6a6..7436f2d346 100644 --- a/src/solver/ts-generator/CMakeLists.txt +++ b/src/solver/ts-generator/CMakeLists.txt @@ -14,6 +14,7 @@ source_group("ts-generator\\randomized-thermal-generator" FILES ${SRC_RANDOMIZED # set(SRC_OPTIMIZEDGENERATORS optimized-thermal-generator/AuxillaryStructures.h + optimized-thermal-generator/AuxillaryFreeFunctions.cpp optimized-thermal-generator/pre-scenario-builder.h optimized-thermal-generator/pre-scenario-builder.cpp optimized-thermal-generator/OptimizedGenerator.h diff --git a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.cpp b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.cpp new file mode 100644 index 0000000000..5f9795b491 --- /dev/null +++ b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.cpp @@ -0,0 +1,212 @@ +// +// Created by milos on 14/11/23. +// + +#include "OptimizedGenerator.h" + +namespace Antares::Solver::TSGenerator +{ + +// calculate Average time-series functions +std::array calculateAverageLoadTs(const Data::Area& area) +{ + // we assume ready-make TS - (pre-check exist for this!) + const auto tsValues = area.load.series.timeSeries; + const auto tsNumbers = area.load.series.timeseriesNumbers; + return calculateAverageTs(tsValues, tsNumbers); +} + +std::array calculateAverageRorTs(const Data::Area& area) +{ + const auto tsValues = area.hydro.series->ror.timeSeries; + auto tsNumbers = area.hydro.series->ror.timeseriesNumbers; + return calculateAverageTs(tsValues, tsNumbers); +} + +std::array calculateAverageRenewableTsAggregated(const Data::Area& area) +{ + std::array averageTsSolar + = calculateAverageTs(area.solar.series.timeSeries, area.solar.series.timeseriesNumbers); + std::array averageTsWind + = calculateAverageTs(area.wind.series.timeSeries, area.wind.series.timeseriesNumbers); + + std::array averageTsRenewable = {}; + for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) + { + averageTsRenewable[row] = (averageTsSolar[row] + averageTsWind[row]); + } + return averageTsRenewable; +} + +std::array calculateAverageRenewableTsClusters(const Data::Area& area) +{ + std::array averageTsRenewable = {}; + for (const auto& entryCluster : area.renewable.clusters) + { + auto& cluster = *entryCluster; + // this is not even necessary - because area.renewable.clusters returns list of only + // ENABLED clusters but let's keep it for now + if (!cluster.enabled) + continue; + auto tmpArrayPerCluster + = calculateAverageTs(cluster.series.timeSeries, cluster.series.timeseriesNumbers); + for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) + { + if (cluster.tsMode == Data::RenewableCluster::productionFactor) + averageTsRenewable[row] + += tmpArrayPerCluster[row] * cluster.unitCount * cluster.nominalCapacity; + else + averageTsRenewable[row] += tmpArrayPerCluster[row]; + } + } + return averageTsRenewable; +} + +std::array calculateAverageRenewableTs( + const Data::Parameters::RenewableGeneration modelingType, + const Data::Area& area) +{ + if (modelingType.isAggregated()) + { + return calculateAverageRenewableTsAggregated(area); + } + else // clusters it is + { + return calculateAverageRenewableTsClusters(area); + } +} + +// auxillary functions - for parameter calculations +std::array calculateDailySums( + const std::array& hourlyValues) +{ + std::array dailyValues; + auto hours_iter = hourlyValues.begin(); + + for (double& day_sum : dailyValues) + { + day_sum = std::accumulate(hours_iter, hours_iter + 24, 0.0); + hours_iter += 24; + } + + return dailyValues; +} + +std::array calculateAverageTs(const Matrix& tsValue, + const Matrix& tsNumbers) +{ + // define array + std::array averageTs = {}; + // calculate sum + for (std::size_t year = 0; year < tsNumbers.height; ++year) + { + for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) + { + averageTs[row] += tsValue[tsNumbers[0][year]][row]; + } + } + // calculate mean + for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) + { + averageTs[row] = averageTs[row] / tsNumbers.height; + } + // return + return averageTs; +} + +bool checkClusterExist(const Data::ThermalCluster& cluster) +{ + if (!cluster.prepro) + { + logs.error() << "Cluster: " << cluster.getFullName() + << ": The timeseries will not be regenerated. All data " + "related to the ts-generator for " + << "'thermal' have been released."; + return false; + } + + if (0 == cluster.unitCount || 0 == cluster.nominalCapacity) + { + return false; + } + return true; +} + +int dayOfTheYear(int optimizationDay) +{ + return optimizationDay % DAYS_PER_YEAR; +} + +// calculate parameters methods - per cluster +int calculateNumberOfMaintenances(const Data::ThermalCluster& cluster, int timeHorizon) +{ + // timeHorizon cannot be 0. The whole maintenance group would be skipped if this happened + // on the other hand interPoPeriod can be 0. So we say at least 2 maintenance if this happens + // actually this cannot happen because checkMaintenanceGroupParameters() will kill it by now + if (cluster.interPoPeriod == 0) + { + logs.warning() << "Cluster: " << cluster.getFullName() + << "has interPoPeriod = 0. Number of maintenances for all units inside this " + "cluster will be set to 2"; + return minNumberOfMaintenances; + } + + return std::max(timeHorizon / cluster.interPoPeriod, minNumberOfMaintenances); // floor +} + +int calculateAverageMaintenanceDuration(const Data::ThermalCluster& cluster) +{ + double sum = 0.0; + for (std::size_t row = 0; row < DAYS_PER_YEAR; ++row) + { + sum += cluster.prepro->data[Data::PreproThermal::poDuration][row]; + } + // poDuration in Antares cannot be below 1.0 + // so it is redundant to check here if return value is above 1.0 + // that is why I did not use std::max() + return sum / static_cast(DAYS_PER_YEAR); +} + +std::array calculateMaxUnitOutput(const Data::ThermalCluster& cluster) +{ + std::array maxOutputDailyValues = {}; + std::array maxOutputHourlyValues = {}; + + // transfer to array + for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) + { + maxOutputHourlyValues[row] + = cluster.modulation[Data::ThermalModulation::thermalModulationCapacity][row]; + } + + maxOutputDailyValues = calculateDailySums(maxOutputHourlyValues); + // multiply by per unit power (nominal capacity) + for (double& num : maxOutputDailyValues) + { + num *= cluster.nominalCapacity; + } + return maxOutputDailyValues; +} + +std::array calculateAvrUnitDailyCost(const Data::ThermalCluster& cluster) +{ + std::array avrCostDailyValues = {}; + std::array costHourlyValues = {}; + + // transfer to array + for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) + { + costHourlyValues[row] + = cluster.modulation[Data::ThermalModulation::thermalModulationMarketBid][row]; + } + + avrCostDailyValues = calculateDailySums(costHourlyValues); + // multiply by per unit/cluster market bid cost + average this on 24 hours + for (double& num : avrCostDailyValues) + { + num *= cluster.marketBidCost / 24.0; + } + return avrCostDailyValues; +} + +} // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp index 2646426043..6bdae332e7 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp @@ -301,205 +301,4 @@ int OptimizedThermalGenerator::calculateUnitLatestStartOfFirstMaintenance( } } -// calculate Average time-series functions -std::array calculateAverageLoadTs(const Data::Area& area) -{ - // we assume ready-make TS - (pre-check exist for this!) - const auto tsValues = area.load.series.timeSeries; - const auto tsNumbers = area.load.series.timeseriesNumbers; - return calculateAverageTs(tsValues, tsNumbers); -} - -std::array calculateAverageRorTs(const Data::Area& area) -{ - const auto tsValues = area.hydro.series->ror.timeSeries; - auto tsNumbers = area.hydro.series->ror.timeseriesNumbers; - return calculateAverageTs(tsValues, tsNumbers); -} - -std::array calculateAverageRenewableTsAggregated(const Data::Area& area) -{ - std::array averageTsSolar - = calculateAverageTs(area.solar.series.timeSeries, area.solar.series.timeseriesNumbers); - std::array averageTsWind - = calculateAverageTs(area.wind.series.timeSeries, area.wind.series.timeseriesNumbers); - - std::array averageTsRenewable = {}; - for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) - { - averageTsRenewable[row] = (averageTsSolar[row] + averageTsWind[row]); - } - return averageTsRenewable; -} - -std::array calculateAverageRenewableTsClusters(const Data::Area& area) -{ - std::array averageTsRenewable = {}; - for (const auto& entryCluster : area.renewable.clusters) - { - auto& cluster = *entryCluster; - // this is not even necessary - because area.renewable.clusters returns list of only - // ENABLED clusters but let's keep it for now - if (!cluster.enabled) - continue; - auto tmpArrayPerCluster - = calculateAverageTs(cluster.series.timeSeries, cluster.series.timeseriesNumbers); - for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) - { - if (cluster.tsMode == Data::RenewableCluster::productionFactor) - averageTsRenewable[row] - += tmpArrayPerCluster[row] * cluster.unitCount * cluster.nominalCapacity; - else - averageTsRenewable[row] += tmpArrayPerCluster[row]; - } - } - return averageTsRenewable; -} - -std::array calculateAverageRenewableTs( - const Data::Parameters::RenewableGeneration modelingType, - const Data::Area& area) -{ - if (modelingType.isAggregated()) - { - return calculateAverageRenewableTsAggregated(area); - } - else // clusters it is - { - return calculateAverageRenewableTsClusters(area); - } -} - -// auxillary functions - for parameter calculations -std::array calculateDailySums( - const std::array& hourlyValues) -{ - std::array dailyValues; - auto hours_iter = hourlyValues.begin(); - - for (double& day_sum : dailyValues) - { - day_sum = std::accumulate(hours_iter, hours_iter + 24, 0.0); - hours_iter += 24; - } - - return dailyValues; -} - -std::array calculateAverageTs(const Matrix& tsValue, - const Matrix& tsNumbers) -{ - // define array - std::array averageTs = {}; - // calculate sum - for (std::size_t year = 0; year < tsNumbers.height; ++year) - { - for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) - { - averageTs[row] += tsValue[tsNumbers[0][year]][row]; - } - } - // calculate mean - for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) - { - averageTs[row] = averageTs[row] / tsNumbers.height; - } - // return - return averageTs; -} - -bool checkClusterExist(const Data::ThermalCluster& cluster) -{ - if (!cluster.prepro) - { - logs.error() << "Cluster: " << cluster.getFullName() - << ": The timeseries will not be regenerated. All data " - "related to the ts-generator for " - << "'thermal' have been released."; - return false; - } - - if (0 == cluster.unitCount || 0 == cluster.nominalCapacity) - { - return false; - } - return true; -} - -int dayOfTheYear(int optimizationDay) -{ - return optimizationDay % DAYS_PER_YEAR; -} - -// calculate parameters methods - per cluster -int calculateNumberOfMaintenances(const Data::ThermalCluster& cluster, int timeHorizon) -{ - // timeHorizon cannot be 0. The whole maintenance group would be skipped if this happened - // on the other hand interPoPeriod can be 0. So we say at least 2 maintenance if this happens - // actually this cannot happen because checkMaintenanceGroupParameters() will kill it by now - if (cluster.interPoPeriod == 0) - { - logs.warning() << "Cluster: " << cluster.getFullName() - << "has interPoPeriod = 0. Number of maintenances for all units inside this " - "cluster will be set to 2"; - return minNumberOfMaintenances; - } - - return std::max(timeHorizon / cluster.interPoPeriod, minNumberOfMaintenances); // floor -} - -int calculateAverageMaintenanceDuration(const Data::ThermalCluster& cluster) -{ - double sum = 0.0; - for (std::size_t row = 0; row < DAYS_PER_YEAR; ++row) - { - sum += cluster.prepro->data[Data::PreproThermal::poDuration][row]; - } - // poDuration in Antares cannot be below 1.0 - // so it is redundant to check here if return value is above 1.0 - // that is why I did not use std::max() - return sum / static_cast(DAYS_PER_YEAR); -} - -std::array calculateMaxUnitOutput(const Data::ThermalCluster& cluster) -{ - std::array maxOutputDailyValues = {}; - std::array maxOutputHourlyValues = {}; - - // transfer to array - for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) - { - maxOutputHourlyValues[row] - = cluster.modulation[Data::ThermalModulation::thermalModulationCapacity][row]; - } - - maxOutputDailyValues = calculateDailySums(maxOutputHourlyValues); - // multiply by per unit power (nominal capacity) - for (double& num : maxOutputDailyValues) - { - num *= cluster.nominalCapacity; - } - return maxOutputDailyValues; -} - -std::array calculateAvrUnitDailyCost(const Data::ThermalCluster& cluster) -{ - std::array avrCostDailyValues = {}; - std::array costHourlyValues = {}; - - // transfer to array - for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) - { - costHourlyValues[row] - = cluster.modulation[Data::ThermalModulation::thermalModulationMarketBid][row]; - } - - avrCostDailyValues = calculateDailySums(costHourlyValues); - // multiply by per unit/cluster market bid cost + average this on 24 hours - for (double& num : avrCostDailyValues) - { - num *= cluster.marketBidCost / 24.0; - } - return avrCostDailyValues; -} } // namespace Antares::Solver::TSGenerator From e567fcf70decb818ee3e05902c2aa94a04b50f48 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Sun, 26 Nov 2023 16:19:41 +0100 Subject: [PATCH 188/315] make header file for auxillary functions --- src/solver/ts-generator/CMakeLists.txt | 1 + .../AuxillaryFreeFunctions.cpp | 1 + .../AuxillaryFreeFunctions.h | 35 +++++++++++++++++++ .../OptimizedGenerator.h | 24 +------------ 4 files changed, 38 insertions(+), 23 deletions(-) create mode 100644 src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.h diff --git a/src/solver/ts-generator/CMakeLists.txt b/src/solver/ts-generator/CMakeLists.txt index 7436f2d346..4a40b1f987 100644 --- a/src/solver/ts-generator/CMakeLists.txt +++ b/src/solver/ts-generator/CMakeLists.txt @@ -14,6 +14,7 @@ source_group("ts-generator\\randomized-thermal-generator" FILES ${SRC_RANDOMIZED # set(SRC_OPTIMIZEDGENERATORS optimized-thermal-generator/AuxillaryStructures.h + optimized-thermal-generator/AuxillaryFreeFunctions.h optimized-thermal-generator/AuxillaryFreeFunctions.cpp optimized-thermal-generator/pre-scenario-builder.h optimized-thermal-generator/pre-scenario-builder.cpp diff --git a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.cpp b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.cpp index 5f9795b491..b81694a2ef 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.cpp @@ -3,6 +3,7 @@ // #include "OptimizedGenerator.h" +#include "AuxillaryFreeFunctions.h" namespace Antares::Solver::TSGenerator { diff --git a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.h b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.h new file mode 100644 index 0000000000..5b5fa5235b --- /dev/null +++ b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.h @@ -0,0 +1,35 @@ +// +// Created by milos on 14/11/23. +// + +#pragma once + +#include "OptimizedGenerator.h" + +namespace Antares::Solver::TSGenerator +{ + +// auxillary functions +std::array calculateDailySums( + const std::array& hourlyValues); +std::array calculateAverageTs(const Matrix& tsValue, + const Matrix& tsNumbers); +bool checkClusterExist(const Data::ThermalCluster& cluster); +int dayOfTheYear(int optimizationDay); + +// calculate Average time-series functions +std::array calculateAverageLoadTs(const Data::Area& area); +std::array calculateAverageRorTs(const Data::Area& area); +std::array calculateAverageRenewableTs( + const Data::Parameters::RenewableGeneration modelingType, + const Data::Area& area); +std::array calculateAverageRenewableTsAggregated(const Data::Area& area); +std::array calculateAverageRenewableTsClusters(const Data::Area& area); + +// calculate parameters methods - per cluster +int calculateNumberOfMaintenances(const Data::ThermalCluster& cluster, int timeHorizon); +int calculateAverageMaintenanceDuration(const Data::ThermalCluster& cluster); +std::array calculateMaxUnitOutput(const Data::ThermalCluster& cluster); +std::array calculateAvrUnitDailyCost(const Data::ThermalCluster& cluster); + +} // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index ac883e4514..cf25b8d28e 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -8,6 +8,7 @@ #include "../randomized-thermal-generator/RandomizedGenerator.h" #include "../../../libs/antares/study/maintenance_planning/MaintenanceGroup.h" #include "AuxillaryStructures.h" +#include "AuxillaryFreeFunctions.h" #include // static const std::string mntPlSolverName = "cbc"; @@ -240,27 +241,4 @@ class OptimizedThermalGenerator : public GeneratorTempData template void printColumnToFile(const std::vector>& data, const std::string& filename); -// auxillary functions -std::array calculateDailySums( - const std::array& hourlyValues); -std::array calculateAverageTs(const Matrix& tsValue, - const Matrix& tsNumbers); -bool checkClusterExist(const Data::ThermalCluster& cluster); -int dayOfTheYear(int optimizationDay); - -// calculate Average time-series functions -std::array calculateAverageLoadTs(const Data::Area& area); -std::array calculateAverageRorTs(const Data::Area& area); -std::array calculateAverageRenewableTs( - const Data::Parameters::RenewableGeneration modelingType, - const Data::Area& area); -std::array calculateAverageRenewableTsAggregated(const Data::Area& area); -std::array calculateAverageRenewableTsClusters(const Data::Area& area); - -// calculate parameters methods - per cluster -int calculateNumberOfMaintenances(const Data::ThermalCluster& cluster, int timeHorizon); -int calculateAverageMaintenanceDuration(const Data::ThermalCluster& cluster); -std::array calculateMaxUnitOutput(const Data::ThermalCluster& cluster); -std::array calculateAvrUnitDailyCost(const Data::ThermalCluster& cluster); - } // namespace Antares::Solver::TSGenerator \ No newline at end of file From 941dbc7132826c209b65ee98b9e2396757ca0514 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Sun, 26 Nov 2023 16:37:19 +0100 Subject: [PATCH 189/315] assert --- .../optimized-thermal-generator/AuxillaryStructures.h | 2 +- .../optimized-thermal-generator/SetProblemConstraints.cpp | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h index 3bfc41b6c7..2526cd7043 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h +++ b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h @@ -26,7 +26,7 @@ class OptProblemSettings final bool isFirstStep = true; }; -// this structure stores the data about optimization problem variables +// this structure stores the data about optimization problem variables and results struct Maintenances { // number of elements in the vector is number of days in optimization problem diff --git a/src/solver/ts-generator/optimized-thermal-generator/SetProblemConstraints.cpp b/src/solver/ts-generator/optimized-thermal-generator/SetProblemConstraints.cpp index 9900c0a3f7..aa5dcbf70a 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/SetProblemConstraints.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/SetProblemConstraints.cpp @@ -78,6 +78,8 @@ void OptimizedThermalGenerator::setStartEndMntLogicConstraints(const OptProblemS // loop per maintenances per unit for (int mnt = 0; mnt < unit.maintenances.size(); ++mnt) { + assert(unit.maintenances[mnt].start.size() == timeHorizon_); + assert(unit.maintenances[mnt].end.size() == timeHorizon_); setEndOfMaintenanceEventBasedOnAverageDurationOfMaintenanceEvent(optSett, unit, mnt); setOnceStartIsSetToOneItWillBeOneUntilEndOfOptimizationTimeHorizon(optSett, unit, mnt); } From 4891b6b67cb104ed76e744425ebb8a58bbc7f6db Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Sun, 26 Nov 2023 16:51:24 +0100 Subject: [PATCH 190/315] future tips --- .../PostScenarioOptimization.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp index 4706cbcbce..8f8278107e 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp @@ -35,10 +35,17 @@ void OptimizedThermalGenerator::saveScenarioResults(const OptProblemSettings& op // loop through all areas and clusters and write results /* - // do not forget archive!! + // this is not even post scenario optimization + // we do this after all the scenarios !!! + + if (derated) + cluster.series.timeSeries.averageTimeseries(); + if (archive) writeResultsToDisk(area, cluster); + cluster.calculationOfSpinning(); + */ } From 7b0fbc78f173be50158da06bbbaa8a826f9a507b Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Mon, 27 Nov 2023 12:32:37 +0100 Subject: [PATCH 191/315] auxillary function findFirstOne in vector --- .../AuxillaryFreeFunctions.cpp | 24 +++++++++++++++++++ .../AuxillaryFreeFunctions.h | 5 +++- .../PostTimeStepOptimization.cpp | 6 +++++ 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.cpp b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.cpp index b81694a2ef..7d089f1c44 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.cpp @@ -210,4 +210,28 @@ std::array calculateAvrUnitDailyCost(const Data::ThermalC return avrCostDailyValues; } +// post-time step optimization - functions +int findFirstOne(const std::vector vector, int limit) +{ + // this functions finds first 1 in a vector and returns its index + // if no 1, return -1 + // because 0 is a valid output - maintenance starts on first day + + for (int i = 0; i < vector.size(); ++i) + { + if (vector[i] == 1) + { + if (i < limit) + { + return i; + } + else + { + break; + } + } + } + return -1; +} + } // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.h b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.h index 5b5fa5235b..2f7e7e4c9a 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.h +++ b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.h @@ -26,10 +26,13 @@ std::array calculateAverageRenewableTs( std::array calculateAverageRenewableTsAggregated(const Data::Area& area); std::array calculateAverageRenewableTsClusters(const Data::Area& area); -// calculate parameters methods - per cluster +// calculate parameters functions - per cluster int calculateNumberOfMaintenances(const Data::ThermalCluster& cluster, int timeHorizon); int calculateAverageMaintenanceDuration(const Data::ThermalCluster& cluster); std::array calculateMaxUnitOutput(const Data::ThermalCluster& cluster); std::array calculateAvrUnitDailyCost(const Data::ThermalCluster& cluster); +// post-time step optimization - functions +int findFirstOne(const std::vector vector, int limit); + } // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp index 376128a419..195d6e71ec 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp @@ -17,6 +17,12 @@ void OptimizedThermalGenerator::postTimeStepOptimization(OptProblemSettings& opt // save/append optimization results form range 0-timeStep void OptimizedThermalGenerator::appendTimeStepResults(const OptProblemSettings& optSett) { + // we have vectors of start (zeros and ones) + // lets convert that into maintenance start day vector + // and then randomly generate maintenance duration + // and create std::pairs - of start_day + mnt_duration + + return; } From 8964fa6231403f588b9fbdad00fbaed7ab691ed6 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Mon, 27 Nov 2023 12:52:00 +0100 Subject: [PATCH 192/315] fix populating scenarioResults while creating variables --- .../optimized-thermal-generator/CreateVariables.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp b/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp index 992b00ae07..e82ca3a220 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp @@ -109,7 +109,8 @@ void OptimizedThermalGenerator::buildUnitPowerOutputVariables(const OptProblemSe if (!(cluster.doWeGenerateTS(globalThermalTSgeneration_) && cluster.optimizeMaintenance)) { unitRef.createStartEndVariables = false; - scenarioResults.back().createStartEndVariables = false; + if (optSett.isFirstStep) + scenarioResults.back().createStartEndVariables = false; return; } From 3e317f14981b4fb438e968da3f5a8c970c0c99c6 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Mon, 27 Nov 2023 16:13:43 +0100 Subject: [PATCH 193/315] appendTimeStepResults - collect mnt start values --- src/solver/ts-generator/CMakeLists.txt | 1 + .../AuxillaryFreeFunctions.cpp | 24 ---------- .../AuxillaryFreeFunctions.h | 3 -- .../AuxillaryStructures.cpp | 47 +++++++++++++++++++ .../AuxillaryStructures.h | 8 +++- .../PostTimeStepOptimization.cpp | 47 ++++++++++++++++++- 6 files changed, 99 insertions(+), 31 deletions(-) create mode 100644 src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.cpp diff --git a/src/solver/ts-generator/CMakeLists.txt b/src/solver/ts-generator/CMakeLists.txt index 4a40b1f987..4795656f26 100644 --- a/src/solver/ts-generator/CMakeLists.txt +++ b/src/solver/ts-generator/CMakeLists.txt @@ -14,6 +14,7 @@ source_group("ts-generator\\randomized-thermal-generator" FILES ${SRC_RANDOMIZED # set(SRC_OPTIMIZEDGENERATORS optimized-thermal-generator/AuxillaryStructures.h + optimized-thermal-generator/AuxillaryStructures.cpp optimized-thermal-generator/AuxillaryFreeFunctions.h optimized-thermal-generator/AuxillaryFreeFunctions.cpp optimized-thermal-generator/pre-scenario-builder.h diff --git a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.cpp b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.cpp index 7d089f1c44..b81694a2ef 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.cpp @@ -210,28 +210,4 @@ std::array calculateAvrUnitDailyCost(const Data::ThermalC return avrCostDailyValues; } -// post-time step optimization - functions -int findFirstOne(const std::vector vector, int limit) -{ - // this functions finds first 1 in a vector and returns its index - // if no 1, return -1 - // because 0 is a valid output - maintenance starts on first day - - for (int i = 0; i < vector.size(); ++i) - { - if (vector[i] == 1) - { - if (i < limit) - { - return i; - } - else - { - break; - } - } - } - return -1; -} - } // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.h b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.h index 2f7e7e4c9a..1a74c82a52 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.h +++ b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.h @@ -32,7 +32,4 @@ int calculateAverageMaintenanceDuration(const Data::ThermalCluster& cluster); std::array calculateMaxUnitOutput(const Data::ThermalCluster& cluster); std::array calculateAvrUnitDailyCost(const Data::ThermalCluster& cluster); -// post-time step optimization - functions -int findFirstOne(const std::vector vector, int limit); - } // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.cpp b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.cpp new file mode 100644 index 0000000000..164ef144c5 --- /dev/null +++ b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.cpp @@ -0,0 +1,47 @@ +// +// Created by milos on 14/11/23. +// + +#include "AuxillaryStructures.h" + +namespace Antares::Solver::TSGenerator +{ +// post-time step optimization - functions +int Maintenances::startDay(int limit) const +{ + // this functions finds first 1 in a vector and returns its index + // if no 1, return -1 + // because 0 is a valid output - maintenance starts on first day + + auto vector = getStartSolutionValues(); + + for (int i = 0; i < vector.size(); ++i) + { + if (vector[i] == 1) + { + if (i < limit) + { + return i; + } + else + { + break; + } + } + } + return -1; +} + +std::vector Maintenances::getStartSolutionValues() const +{ + std::vector solutionValues; + + for (const auto& variable : start) + { + solutionValues.push_back(static_cast(variable->solution_value())); + } + + return solutionValues; +} + +} // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h index 2526cd7043..c3285081cd 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h +++ b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h @@ -4,7 +4,7 @@ #pragma once -#include "OptimizedGenerator.h" +#include "ortools/linear_solver/linear_solver.h" #include "../../../src/libs/antares/study/area/area.h" using namespace operations_research; @@ -32,6 +32,10 @@ struct Maintenances // number of elements in the vector is number of days in optimization problem std::vector start; // pointer to s[u][m][t] variables std::vector end; // pointer to e[u][m][t] variables + + // methods + int startDay(int limit) const; + std::vector getStartSolutionValues() const; }; struct Unit @@ -58,7 +62,7 @@ struct Unit // number of elements in the vector is number of maintenances // first element of the pair is start of the maintenance // second element of the pair is randomly drawn maintenance duration - std::vector>> maintenanceResults; + std::vector> maintenanceResults; }; struct OptimizationProblemVariables diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp index 195d6e71ec..a32ade539f 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp @@ -21,8 +21,51 @@ void OptimizedThermalGenerator::appendTimeStepResults(const OptProblemSettings& // lets convert that into maintenance start day vector // and then randomly generate maintenance duration // and create std::pairs - of start_day + mnt_duration - - + + // loop per units + for (std::size_t unitIndexTotal = 0; unitIndexTotal < vars.clusterUnits.size(); + ++unitIndexTotal) + { + // Unit-unitIndexTotal - is index in a vector of all the units (area * cluster * units) + // not to be confused by Unit-index - index in cluster + + // variables structure: vars and result structure: scenarioResults + // are created at the same time in the same loop + // so the order of the units should be the same !!! + // so lets avoid creating some search/find method + // that will find the Unit in scenarioResults according to its parentCluster and index + // and just loop + // assert parentCluster and index + + const auto& readResultUnit = vars.clusterUnits[unitIndexTotal]; + auto& storeResultUnit = scenarioResults[unitIndexTotal]; + + assert(readResultUnit.parentCluster == storeResultUnit.parentCluster + && "Read and Store Units do not point to the same parent cluster."); + assert(readResultUnit.index == storeResultUnit.index + && "Read and Store Units do not point to the same unit index."); + + // loop per maintenances of unit + + // TODO CR27: do we even have to loop through maintenances + // or only see if first maintenance start before timeStep_ + // rest (second, third) maintenances will definitely happen after timeStep_ ?! + // Talk with Hugo + + // if createStartEndVariables for the readResultUnit is false + // maintenances.size() is going to be zero - so in a way there is our check + for (int mnt = 0; mnt < readResultUnit.maintenances.size(); ++mnt) + { + int localMaintenanceStart = readResultUnit.maintenances[mnt].startDay(timeStep_); + if (localMaintenanceStart == -1) + continue; + int globalMaintenanceStart = localMaintenanceStart + optSett.firstDay; + int maintenanceDuration = 50; // dummy + storeResultUnit.maintenanceResults.push_back( + std::make_pair(globalMaintenanceStart, maintenanceDuration)); + } + } + return; } From 222f672c9b1ce6cbf1c121faf97a3e67860b6868 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Mon, 27 Nov 2023 19:36:49 +0100 Subject: [PATCH 194/315] draw random maintenance duration [WIP] --- .../AuxillaryFreeFunctions.cpp | 6 ++++ .../AuxillaryFreeFunctions.h | 2 ++ .../PostTimeStepOptimization.cpp | 33 +++++++++++++++++-- 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.cpp b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.cpp index b81694a2ef..d3842ecc86 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.cpp @@ -210,4 +210,10 @@ std::array calculateAvrUnitDailyCost(const Data::ThermalC return avrCostDailyValues; } +// post timeStep_ optimization functions +void prepareRandomMaintenanceDurationData(const Data::ThermalCluster& cluster) +{ + return; +} + } // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.h b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.h index 1a74c82a52..10792e9b92 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.h +++ b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.h @@ -32,4 +32,6 @@ int calculateAverageMaintenanceDuration(const Data::ThermalCluster& cluster); std::array calculateMaxUnitOutput(const Data::ThermalCluster& cluster); std::array calculateAvrUnitDailyCost(const Data::ThermalCluster& cluster); +// post timeStep_ optimization functions +void prepareRandomMaintenanceDurationData(const Data::ThermalCluster& cluster); } // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp index a32ade539f..ca2fb7847d 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp @@ -22,6 +22,8 @@ void OptimizedThermalGenerator::appendTimeStepResults(const OptProblemSettings& // and then randomly generate maintenance duration // and create std::pairs - of start_day + mnt_duration + const Data::ThermalCluster* nextCluster = nullptr; + // loop per units for (std::size_t unitIndexTotal = 0; unitIndexTotal < vars.clusterUnits.size(); ++unitIndexTotal) @@ -45,11 +47,31 @@ void OptimizedThermalGenerator::appendTimeStepResults(const OptProblemSettings& assert(readResultUnit.index == storeResultUnit.index && "Read and Store Units do not point to the same unit index."); + // prepare data for random maintenance generator + const auto& cluster = *(readResultUnit.parentCluster); + const auto& preproData = *(cluster.prepro); + const auto& POD = preproData.data[Data::PreproThermal::poDuration]; + auto p_law = cluster.plannedLaw; + double p_volatility = cluster.plannedVolatility; + prepareRandomMaintenanceDurationData(cluster); + prepareIndispoFromLaw(p_law, p_volatility, ap, bp, POD); + + // we should prepare data for random maintenance generator + // once per Cluster, NOT once per UNIT + // so let's avoid generating same data over and over again for each unit + if (nextCluster != readResultUnit.parentCluster) + { + nextCluster = readResultUnit.parentCluster; + + prepareRandomMaintenanceDurationData(cluster); + prepareIndispoFromLaw(p_law, p_volatility, ap, bp, POD); + } + // loop per maintenances of unit // TODO CR27: do we even have to loop through maintenances // or only see if first maintenance start before timeStep_ - // rest (second, third) maintenances will definitely happen after timeStep_ ?! + // rest (second, third) maintenances will definitely happen after timeStep_ ?! // Talk with Hugo // if createStartEndVariables for the readResultUnit is false @@ -59,8 +81,15 @@ void OptimizedThermalGenerator::appendTimeStepResults(const OptProblemSettings& int localMaintenanceStart = readResultUnit.maintenances[mnt].startDay(timeStep_); if (localMaintenanceStart == -1) continue; + int globalMaintenanceStart = localMaintenanceStart + optSett.firstDay; - int maintenanceDuration = 50; // dummy + int dayInTheYear + = dayOfTheYear(globalMaintenanceStart); // TODO CR27: check this with Hugo! + + int PODOfTheDay = (int)POD[dayInTheYear]; + int maintenanceDuration = durationGenerator( + p_law, PODOfTheDay, p_volatility, ap[dayInTheYear], bp[dayInTheYear]); + storeResultUnit.maintenanceResults.push_back( std::make_pair(globalMaintenanceStart, maintenanceDuration)); } From 7690241fdebef469c0d5121be5317f17da4a97b8 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Mon, 27 Nov 2023 21:14:58 +0100 Subject: [PATCH 195/315] draw random maintenance duration --- .../AuxillaryFreeFunctions.cpp | 6 ----- .../AuxillaryFreeFunctions.h | 2 -- .../PostTimeStepOptimization.cpp | 23 ++++++++----------- 3 files changed, 9 insertions(+), 22 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.cpp b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.cpp index d3842ecc86..b81694a2ef 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.cpp @@ -210,10 +210,4 @@ std::array calculateAvrUnitDailyCost(const Data::ThermalC return avrCostDailyValues; } -// post timeStep_ optimization functions -void prepareRandomMaintenanceDurationData(const Data::ThermalCluster& cluster) -{ - return; -} - } // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.h b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.h index 10792e9b92..1a74c82a52 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.h +++ b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.h @@ -32,6 +32,4 @@ int calculateAverageMaintenanceDuration(const Data::ThermalCluster& cluster); std::array calculateMaxUnitOutput(const Data::ThermalCluster& cluster); std::array calculateAvrUnitDailyCost(const Data::ThermalCluster& cluster); -// post timeStep_ optimization functions -void prepareRandomMaintenanceDurationData(const Data::ThermalCluster& cluster); } // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp index ca2fb7847d..e341bf6d0e 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp @@ -23,6 +23,9 @@ void OptimizedThermalGenerator::appendTimeStepResults(const OptProblemSettings& // and create std::pairs - of start_day + mnt_duration const Data::ThermalCluster* nextCluster = nullptr; + double* POD; + Data::ThermalLaw p_law; + double p_volatility; // loop per units for (std::size_t unitIndexTotal = 0; unitIndexTotal < vars.clusterUnits.size(); @@ -47,23 +50,15 @@ void OptimizedThermalGenerator::appendTimeStepResults(const OptProblemSettings& assert(readResultUnit.index == storeResultUnit.index && "Read and Store Units do not point to the same unit index."); - // prepare data for random maintenance generator - const auto& cluster = *(readResultUnit.parentCluster); - const auto& preproData = *(cluster.prepro); - const auto& POD = preproData.data[Data::PreproThermal::poDuration]; - auto p_law = cluster.plannedLaw; - double p_volatility = cluster.plannedVolatility; - prepareRandomMaintenanceDurationData(cluster); - prepareIndispoFromLaw(p_law, p_volatility, ap, bp, POD); - // we should prepare data for random maintenance generator // once per Cluster, NOT once per UNIT // so let's avoid generating same data over and over again for each unit if (nextCluster != readResultUnit.parentCluster) { nextCluster = readResultUnit.parentCluster; - - prepareRandomMaintenanceDurationData(cluster); + POD = nextCluster->prepro->data[Data::PreproThermal::poDuration]; + p_law = nextCluster->plannedLaw; + p_volatility = nextCluster->plannedVolatility; prepareIndispoFromLaw(p_law, p_volatility, ap, bp, POD); } @@ -83,12 +78,12 @@ void OptimizedThermalGenerator::appendTimeStepResults(const OptProblemSettings& continue; int globalMaintenanceStart = localMaintenanceStart + optSett.firstDay; - int dayInTheYear + int dayInTheYearStart = dayOfTheYear(globalMaintenanceStart); // TODO CR27: check this with Hugo! - int PODOfTheDay = (int)POD[dayInTheYear]; + int PODOfTheDay = (int)POD[dayInTheYearStart]; int maintenanceDuration = durationGenerator( - p_law, PODOfTheDay, p_volatility, ap[dayInTheYear], bp[dayInTheYear]); + p_law, PODOfTheDay, p_volatility, ap[dayInTheYearStart], bp[dayInTheYearStart]); storeResultUnit.maintenanceResults.push_back( std::make_pair(globalMaintenanceStart, maintenanceDuration)); From 049d8c5b4f24592498a0358b47310fa752ce407a Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Mon, 27 Nov 2023 22:56:59 +0100 Subject: [PATCH 196/315] refactor - calculate and store all cluster data for rand gen before loops - we only do it once --- .../AuxillaryStructures.h | 4 +++ .../CalculateParameters.cpp | 7 +++++ .../PostTimeStepOptimization.cpp | 30 +++++++------------ 3 files changed, 22 insertions(+), 19 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h index c3285081cd..ca816691af 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h +++ b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h @@ -89,6 +89,10 @@ struct ClusterData std::vector daysSinceLastMnt; int numberOfMaintenances; int averageMaintenanceDuration; + + // for random generator + double AP[366]; + double BP[366]; }; struct AreaData diff --git a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp index 6bdae332e7..a1d99c6810 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp @@ -167,6 +167,13 @@ void OptimizedThermalGenerator::setClusterData() // since we will be updating daysSinceLastMaintenance values // lets create a copy here - this is copy by value! clusterData[&cluster].daysSinceLastMnt = cluster.daysSinceLastMaintenance; + + // random generator + prepareIndispoFromLaw(cluster.plannedLaw, + cluster.plannedVolatility, + clusterData[&cluster].AP, + clusterData[&cluster].BP, + cluster.prepro->data[Data::PreproThermal::poDuration]); } } return; diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp index e341bf6d0e..0ff939aa80 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp @@ -22,11 +22,6 @@ void OptimizedThermalGenerator::appendTimeStepResults(const OptProblemSettings& // and then randomly generate maintenance duration // and create std::pairs - of start_day + mnt_duration - const Data::ThermalCluster* nextCluster = nullptr; - double* POD; - Data::ThermalLaw p_law; - double p_volatility; - // loop per units for (std::size_t unitIndexTotal = 0; unitIndexTotal < vars.clusterUnits.size(); ++unitIndexTotal) @@ -50,17 +45,7 @@ void OptimizedThermalGenerator::appendTimeStepResults(const OptProblemSettings& assert(readResultUnit.index == storeResultUnit.index && "Read and Store Units do not point to the same unit index."); - // we should prepare data for random maintenance generator - // once per Cluster, NOT once per UNIT - // so let's avoid generating same data over and over again for each unit - if (nextCluster != readResultUnit.parentCluster) - { - nextCluster = readResultUnit.parentCluster; - POD = nextCluster->prepro->data[Data::PreproThermal::poDuration]; - p_law = nextCluster->plannedLaw; - p_volatility = nextCluster->plannedVolatility; - prepareIndispoFromLaw(p_law, p_volatility, ap, bp, POD); - } + auto& cluster = *(readResultUnit.parentCluster); // loop per maintenances of unit @@ -81,9 +66,16 @@ void OptimizedThermalGenerator::appendTimeStepResults(const OptProblemSettings& int dayInTheYearStart = dayOfTheYear(globalMaintenanceStart); // TODO CR27: check this with Hugo! - int PODOfTheDay = (int)POD[dayInTheYearStart]; + int PODOfTheDay + = (int)cluster.prepro->data[Data::PreproThermal::poDuration][dayInTheYearStart]; + double app = maintenanceData.areaMap[cluster.parentArea] + .clusterMap[&cluster] + .AP[dayInTheYearStart]; + double bpp = maintenanceData.areaMap[cluster.parentArea] + .clusterMap[&cluster] + .BP[dayInTheYearStart]; int maintenanceDuration = durationGenerator( - p_law, PODOfTheDay, p_volatility, ap[dayInTheYearStart], bp[dayInTheYearStart]); + cluster.plannedLaw, PODOfTheDay, cluster.plannedVolatility, app, bpp); storeResultUnit.maintenanceResults.push_back( std::make_pair(globalMaintenanceStart, maintenanceDuration)); @@ -104,8 +96,8 @@ void OptimizedThermalGenerator::reCalculateDaysSinceLastMnt(const OptProblemSett // we need to re-do // clusterVariables[&cluster].daysSinceLastMnt = cluster.daysSinceLastMaintenance; // for all areas and clusters + } - // TODO CR27: re-calculate days since last maintenance inputs if necessary } } // namespace Antares::Solver::TSGenerator From fbbd40abaa24e9dc527e277c778fbbbccdeaa6b3 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 28 Nov 2023 00:10:40 +0100 Subject: [PATCH 197/315] small refactor --- .../optimized-thermal-generator/CalculateParameters.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp index a1d99c6810..7f3371ca2b 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp @@ -48,10 +48,9 @@ std::pair OptimizedThermalGenerator::calculateTimeHorizonAndStep() for (const auto& entryWeightMap : maintenanceGroup_) { const auto& area = *(entryWeightMap.first); - for (auto it = area.thermal.list.mapping.begin(); it != area.thermal.list.mapping.end(); - ++it) + for (const auto& clusterEntry : area.thermal.list.mapping) { - const auto& cluster = *(it->second); + const auto& cluster = *(clusterEntry.second); if (checkClusterExist(cluster) && cluster.doWeGenerateTS(globalThermalTSgeneration_) && cluster.optimizeMaintenance) { From 481779c897f3f34e260b0368f4dc568fd521f002 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 28 Nov 2023 00:18:12 +0100 Subject: [PATCH 198/315] re-calculate days since last mnt [WIP] --- .../OptimizedGenerator.h | 14 ++-- .../PostTimeStepOptimization.cpp | 66 +++++++++++++++++-- 2 files changed, 72 insertions(+), 8 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index cf25b8d28e..3ad13befcf 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -135,13 +135,19 @@ class OptimizedThermalGenerator : public GeneratorTempData void postTimeStepOptimization(OptProblemSettings& optSett); void appendTimeStepResults(const OptProblemSettings& optSett); void reCalculateDaysSinceLastMnt(const OptProblemSettings& optSett); + void reSetDaysSinceLastMnt(); + int reCalculateDaysSinceLastMnt(const OptProblemSettings& optSett, + const Unit& unit, + bool maintenanceHappened, + int lastMaintenanceStart, + int lastMaintenanceDuration); - /* ===================END-POST-OPTIMIZATION=================== */ + /* ===================END-POST-OPTIMIZATION=================== */ - /* ===================CALCULATE-OPTIMIZATION-PARAMETERS=================== */ + /* ===================CALCULATE-OPTIMIZATION-PARAMETERS=================== */ - // Calculate parameters methods - per maintenance group - void setMaintenanceGroupParameters(); + // Calculate parameters methods - per maintenance group + void setMaintenanceGroupParameters(); bool checkMaintenanceGroupParameters(); std::pair calculateTimeHorizonAndStep(); std::pair calculateMaintenanceGroupENSandSpillageCost(); diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp index 0ff939aa80..472fd4c7b6 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp @@ -86,18 +86,76 @@ void OptimizedThermalGenerator::appendTimeStepResults(const OptProblemSettings& } // re-calculate parameters +void OptimizedThermalGenerator::reSetDaysSinceLastMnt() +{ + // we are back in first step, but not first scenario + // we have messed up our values + // we need to re-do + // clusterVariables[&cluster].daysSinceLastMnt = cluster.daysSinceLastMaintenance; + // for all areas and clusters + for (auto& area : maintenanceData.areaMap) + { + for (auto& cluster : area.second.clusterMap) + { + cluster.second.daysSinceLastMnt = cluster.first->daysSinceLastMaintenance; + } + } + return; +} + void OptimizedThermalGenerator::reCalculateDaysSinceLastMnt(const OptProblemSettings& optSett) { if (optSett.scenario == 0 && optSett.isFirstStep) return; if (optSett.scenario != 0 && optSett.isFirstStep) + reSetDaysSinceLastMnt(); + + // re-calculate days since last maintenance inputs if necessary + for (const auto& unit : scenarioResults) { - // we are back in first step, but not first scenario we have messed up our values - // we need to re-do - // clusterVariables[&cluster].daysSinceLastMnt = cluster.daysSinceLastMaintenance; - // for all areas and clusters + int newDaysSinceLastMaintenance = 0; + bool maintenanceHappened = false; + if (unit.maintenanceResults.empty()) + { + newDaysSinceLastMaintenance + = reCalculateDaysSinceLastMnt(optSett, unit, maintenanceHappened, 0, 0); + } + + int lastMaintenanceStart = unit.maintenanceResults.back().first; + // check if maintenance happened in the observed timeStep + // remember maintenanceResults - stores all the maintenances + // last maintenance may be from some earlier timeStep + if (lastMaintenanceStart < optSett.firstDay) + { + newDaysSinceLastMaintenance + = reCalculateDaysSinceLastMnt(optSett, unit, maintenanceHappened, 0, 0); + } + + maintenanceHappened = true; + int lastMaintenanceDuration = unit.maintenanceResults.back().second; + newDaysSinceLastMaintenance = reCalculateDaysSinceLastMnt( + optSett, unit, maintenanceHappened, lastMaintenanceStart, lastMaintenanceDuration); + + maintenanceData.areaMap[unit.parentCluster->parentArea] + .clusterMap[unit.parentCluster] + .daysSinceLastMnt[unit.index] + = newDaysSinceLastMaintenance; } } +int OptimizedThermalGenerator::reCalculateDaysSinceLastMnt(const OptProblemSettings& optSett, + const Unit& unit, + bool maintenanceHappened, + int lastMaintenanceStart, + int lastMaintenanceDuration) +{ + if (maintenanceHappened) + return std::max( + 0, optSett.firstDay + timeStep_ - (lastMaintenanceStart + lastMaintenanceDuration)); + else + return timeStep_ + unit.parentCluster->daysSinceLastMaintenance[unit.index]; + // this can lead LatestStartOfFirstMaintenance to negative!! +} + } // namespace Antares::Solver::TSGenerator From 1d6d1203ef6800eea4b25f18d0b0f3bf4eeee4d8 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 28 Nov 2023 14:31:01 +0100 Subject: [PATCH 199/315] rename-refactor --- .../antares/study/parts/thermal/cluster.cpp | 5 +- .../antares/study/parts/thermal/cluster.h | 4 +- .../study/parts/thermal/cluster_list.cpp | 2 +- .../AuxillaryStructures.h | 2 +- .../CalculateParameters.cpp | 47 ++++++++----------- .../PostTimeStepOptimization.cpp | 10 ++-- 6 files changed, 33 insertions(+), 37 deletions(-) diff --git a/src/libs/antares/study/parts/thermal/cluster.cpp b/src/libs/antares/study/parts/thermal/cluster.cpp index 8ae1f93c1b..c7366728b3 100644 --- a/src/libs/antares/study/parts/thermal/cluster.cpp +++ b/src/libs/antares/study/parts/thermal/cluster.cpp @@ -216,7 +216,8 @@ void Data::ThermalCluster::copyFrom(const ThermalCluster& cluster) optimizeMaintenance = cluster.optimizeMaintenance; interPoPeriod = cluster.interPoPeriod; poWindows = cluster.poWindows; - daysSinceLastMaintenance = cluster.daysSinceLastMaintenance; + originalRandomlyGeneratedDaysSinceLastMaintenance + = cluster.originalRandomlyGeneratedDaysSinceLastMaintenance; // Making sure that the data related to the prepro and timeseries are present // prepro @@ -486,7 +487,7 @@ void Data::ThermalCluster::reset() optimizeMaintenance = true; interPoPeriod = 365; poWindows = 0; - daysSinceLastMaintenance.clear(); + originalRandomlyGeneratedDaysSinceLastMaintenance.clear(); // prepro // warning: the variables `prepro` and `series` __must__ not be destroyed diff --git a/src/libs/antares/study/parts/thermal/cluster.h b/src/libs/antares/study/parts/thermal/cluster.h index 2bfceea4fb..bcddb6bb5f 100644 --- a/src/libs/antares/study/parts/thermal/cluster.h +++ b/src/libs/antares/study/parts/thermal/cluster.h @@ -303,10 +303,10 @@ class ThermalCluster final : public Cluster, public std::enable_shared_from_this //! PO windows (+/- days) // Acceptable maintenance window (+/- N days, 0 as default value) int poWindows = 0; // TODO CR27: keep this here for now - // maybe create something like PreproThermal for Maintenance - and move everything there!!! + // maybe create something like PreproThermal for Maintenance - and move everything there!!! // days since last maintenance - random int number between 0-interPoPeriod // defined per each unit of the cluster - std::vector daysSinceLastMaintenance; + std::vector originalRandomlyGeneratedDaysSinceLastMaintenance; //! \name Costs // Marginal (€/MWh) MA diff --git a/src/libs/antares/study/parts/thermal/cluster_list.cpp b/src/libs/antares/study/parts/thermal/cluster_list.cpp index 6598e9eee0..3c3af49e90 100644 --- a/src/libs/antares/study/parts/thermal/cluster_list.cpp +++ b/src/libs/antares/study/parts/thermal/cluster_list.cpp @@ -563,7 +563,7 @@ bool ThermalClusterList::generateRandomDaysSinceLastMaintenance(Study& study) for (uint unitIndex = 0; unitIndex < c->unitCount; ++unitIndex) { - c->daysSinceLastMaintenance.push_back( + c->originalRandomlyGeneratedDaysSinceLastMaintenance.push_back( (uint32_t)(floor(random[seedTsGenThermal].next() * c->interPoPeriod))); } } diff --git a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h index ca816691af..9b9a502f1d 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h +++ b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h @@ -86,7 +86,7 @@ struct ClusterData { std::array maxPower; std::array avgCost; - std::vector daysSinceLastMnt; + std::vector daysSinceLastMaintenance; int numberOfMaintenances; int averageMaintenanceDuration; diff --git a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp index 7f3371ca2b..0d1f065e82 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp @@ -165,7 +165,8 @@ void OptimizedThermalGenerator::setClusterData() // since we will be updating daysSinceLastMaintenance values // lets create a copy here - this is copy by value! - clusterData[&cluster].daysSinceLastMnt = cluster.daysSinceLastMaintenance; + clusterData[&cluster].daysSinceLastMaintenance + = cluster.originalRandomlyGeneratedDaysSinceLastMaintenance; // random generator prepareIndispoFromLaw(cluster.plannedLaw, @@ -250,26 +251,14 @@ int OptimizedThermalGenerator::calculateUnitEarliestStartOfFirstMaintenance( { // earliest start of the first maintenance of unit u (beginning of the window, can be negative): // let it return negative value - if it returns negative value we wont implement constraint: - // s[tauLower-1][u][1] = 0 + // s[u][0][tauLower-1] = 0 - // TODO CR27: - // if the approach above breaks the solver - // we force the start of the first maintenance to be after day=0 - // s[fixed = 0][u][1] = 0 + auto& daysSinceLastMaintenance + = maintenanceData.areaMap[cluster.parentArea].clusterMap[&cluster].daysSinceLastMaintenance; - // TODO CR27: - // we need to store cluster.daysSinceLastMaintenance[unitIndex] - // somewhere locally - since we need to update the values after each timeStep_ - // and we do not want to change values inside "cluster" that will later be used for UI & txt - - if (unitIndex < cluster.daysSinceLastMaintenance.size()) + if (unitIndex < daysSinceLastMaintenance.size()) { - return std::min(cluster.interPoPeriod - - maintenanceData.areaMap[cluster.parentArea] - .clusterMap[&cluster] - .daysSinceLastMnt[unitIndex] - - cluster.poWindows, - timeHorizon_ - 1); + return (cluster.interPoPeriod - daysSinceLastMaintenance[unitIndex] - cluster.poWindows); } else { @@ -284,20 +273,24 @@ int OptimizedThermalGenerator::calculateUnitLatestStartOfFirstMaintenance( uint unitIndex) { // latest start of the first maintenance of unit u (end of the window, must be positive): - if (unitIndex < cluster.daysSinceLastMaintenance.size()) + + auto& daysSinceLastMaintenance + = maintenanceData.areaMap[cluster.parentArea].clusterMap[&cluster].daysSinceLastMaintenance; + + if (unitIndex < daysSinceLastMaintenance.size()) { - // this cannot be negative: - // cluster.interPoPeriod - cluster.daysSinceLastMaintenance[unitIndex] - is always positive + // this cannot be negative: FIRST STEP ONLY + // cluster.interPoPeriod - + // cluster.originalRandomlyGeneratedDaysSinceLastMaintenance[unitIndex] - is always positive // or zero // cluster.poWindows is positive or zero // however we will make sure it does not surpass timeHorizon_ - 1 value + // AFTER FIRST STEP it can go to negative value - return std::min(cluster.interPoPeriod - - maintenanceData.areaMap[cluster.parentArea] - .clusterMap[&cluster] - .daysSinceLastMnt[unitIndex] - + cluster.poWindows, - timeHorizon_ - 1); + return std::min( + std::max(0, + cluster.interPoPeriod - daysSinceLastMaintenance[unitIndex] + cluster.poWindows), + timeHorizon_ - 1); } else { diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp index 472fd4c7b6..3e59bf5681 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp @@ -91,13 +91,14 @@ void OptimizedThermalGenerator::reSetDaysSinceLastMnt() // we are back in first step, but not first scenario // we have messed up our values // we need to re-do - // clusterVariables[&cluster].daysSinceLastMnt = cluster.daysSinceLastMaintenance; + // daysSinceLastMaintenance = cluster.originalRandomlyGeneratedDaysSinceLastMaintenance; // for all areas and clusters for (auto& area : maintenanceData.areaMap) { for (auto& cluster : area.second.clusterMap) { - cluster.second.daysSinceLastMnt = cluster.first->daysSinceLastMaintenance; + cluster.second.daysSinceLastMaintenance + = cluster.first->originalRandomlyGeneratedDaysSinceLastMaintenance; } } return; @@ -139,7 +140,7 @@ void OptimizedThermalGenerator::reCalculateDaysSinceLastMnt(const OptProblemSett maintenanceData.areaMap[unit.parentCluster->parentArea] .clusterMap[unit.parentCluster] - .daysSinceLastMnt[unit.index] + .daysSinceLastMaintenance[unit.index] = newDaysSinceLastMaintenance; } } @@ -154,7 +155,8 @@ int OptimizedThermalGenerator::reCalculateDaysSinceLastMnt(const OptProblemSetti return std::max( 0, optSett.firstDay + timeStep_ - (lastMaintenanceStart + lastMaintenanceDuration)); else - return timeStep_ + unit.parentCluster->daysSinceLastMaintenance[unit.index]; + return timeStep_ + + unit.parentCluster->originalRandomlyGeneratedDaysSinceLastMaintenance[unit.index]; // this can lead LatestStartOfFirstMaintenance to negative!! } From f1527265da3e1fdd72a1c86d6fcb62f2295324a1 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 28 Nov 2023 15:15:47 +0100 Subject: [PATCH 200/315] writeTsResults - final call after all scenarios - includes: derated, archive and spinn calc --- .../OptimizedGenerator.cpp | 1 + .../OptimizedGenerator.h | 1 + .../PostScenarioOptimization.cpp | 51 +++++++++++++------ 3 files changed, 38 insertions(+), 15 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp index 5377b57c06..dbadc8bfa8 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp @@ -39,6 +39,7 @@ void OptimizedThermalGenerator::GenerateOptimizedThermalTimeSeries() } postScenarioOptimization(optSett); } + writeTsResults(); } void OptimizedThermalGenerator::allocateWhereToWriteTs() diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 3ad13befcf..b0a658ffda 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -130,6 +130,7 @@ class OptimizedThermalGenerator : public GeneratorTempData void calculateScenarioResults(const OptProblemSettings& optSett); void saveScenarioResults(const OptProblemSettings& optSett); void resetResultStorage(); + void writeTsResults(); // post-timeStep optimization methods void postTimeStepOptimization(OptProblemSettings& optSett); diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp index 8f8278107e..0bfc8a280d 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp @@ -32,21 +32,7 @@ void OptimizedThermalGenerator::saveScenarioResults(const OptProblemSettings& op int colSaveFrom = optSett.scenario * scenarioLength_; int colSaveTo = colSaveFrom + scenarioLength_ - 1; - // loop through all areas and clusters and write results - - /* - // this is not even post scenario optimization - // we do this after all the scenarios !!! - - if (derated) - cluster.series.timeSeries.averageTimeseries(); - - if (archive) - writeResultsToDisk(area, cluster); - - cluster.calculationOfSpinning(); - - */ + // loop through all areas and clusters and write results for one scenario } void OptimizedThermalGenerator::resetResultStorage() @@ -55,4 +41,39 @@ void OptimizedThermalGenerator::resetResultStorage() return; } +// this method is called at the very end +// after all time-steps and scenarios +void OptimizedThermalGenerator::writeTsResults() +{ + // we need to loop through all the clusters + // and write the results + // it would be much easier to loop using MaintenanceData structure + // inside of it we already excluded all the non-important clusters + // however it is const Data::ThermalCluster* + // so we cannot modify cluster values + + for (auto& entryWeightMap : maintenanceGroup_) + { + auto& area = *(entryWeightMap.first); + + for (auto& clusterEntry : area.thermal.list.mapping) + { + auto& cluster = *(clusterEntry.second); + + if (!(checkClusterExist(cluster) && cluster.doWeGenerateTS(globalThermalTSgeneration_) + && cluster.optimizeMaintenance)) + continue; + + if (derated) + cluster.series.timeSeries.averageTimeseries(); + + if (archive) + writeResultsToDisk(area, cluster); + + cluster.calculationOfSpinning(); + } + } + return; +} + } // namespace Antares::Solver::TSGenerator From df1a047afaab9efac5918e1c7d177e056bb3ee9b Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 28 Nov 2023 16:40:36 +0100 Subject: [PATCH 201/315] post scenario optimization auxillary functions [WIP] - expandAndMean availableDailyPower --- .../AuxillaryFreeFunctions.cpp | 20 +++++++++++++- .../AuxillaryFreeFunctions.h | 2 ++ .../AuxillaryStructures.cpp | 26 +++++++++++++++++++ .../AuxillaryStructures.h | 3 +++ .../PostScenarioOptimization.cpp | 4 +++ 5 files changed, 54 insertions(+), 1 deletion(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.cpp b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.cpp index b81694a2ef..d914847008 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.cpp @@ -1,7 +1,9 @@ // // Created by milos on 14/11/23. // - +#include +#include +#include #include "OptimizedGenerator.h" #include "AuxillaryFreeFunctions.h" @@ -210,4 +212,20 @@ std::array calculateAvrUnitDailyCost(const Data::ThermalC return avrCostDailyValues; } +// post -optimization functions +std::array expandAndMean( + const std::array& inputArray) +{ + std::array outputArray; + + auto outputIter = outputArray.begin(); + for (auto value : inputArray) + { + double meanValue = value / 24.0; + std::fill(outputIter, outputIter + 24, meanValue); + outputIter += 24; + } + + return outputArray; +} } // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.h b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.h index 1a74c82a52..bd7d38770b 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.h +++ b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.h @@ -32,4 +32,6 @@ int calculateAverageMaintenanceDuration(const Data::ThermalCluster& cluster); std::array calculateMaxUnitOutput(const Data::ThermalCluster& cluster); std::array calculateAvrUnitDailyCost(const Data::ThermalCluster& cluster); +// post -optimization functions +std::array expandAndMean(const std::array& inputArray); } // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.cpp b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.cpp index 164ef144c5..66e8819abe 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.cpp @@ -44,4 +44,30 @@ std::vector Maintenances::getStartSolutionValues() const return solutionValues; } +std::vector> Unit::availableDailyPower(int tsCount) const +{ + std::vector> result(tsCount, + std::array{}); + for (auto& arr : result) + { + arr.fill(100.0); // Set each array to the value 100.0 + } + + for (const auto& maintenance : maintenanceResults) + { + int start = maintenance.first; + int duration = maintenance.second; + + int end = start + duration; + if (end > DAYS_PER_YEAR) + end = DAYS_PER_YEAR; + + for (int i = start; i < end; ++i) + { + result[0][i] = 0.0; // Assuming index is in range [0, 8760) + } + } + return result; +} + } // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h index 9b9a502f1d..16d08b1b43 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h +++ b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h @@ -63,6 +63,9 @@ struct Unit // first element of the pair is start of the maintenance // second element of the pair is randomly drawn maintenance duration std::vector> maintenanceResults; + + // methods + std::vector> availableDailyPower(int tsCount) const; }; struct OptimizationProblemVariables diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp index 0bfc8a280d..6c536ac3d1 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp @@ -22,6 +22,10 @@ void OptimizedThermalGenerator::postScenarioOptimization(OptProblemSettings& opt void OptimizedThermalGenerator::calculateScenarioResults(const OptProblemSettings& optSett) { + // for each unit we have now scenarioResults + // which contains std::pairs of all [maintenanceStart, maintenanceDuration] + // lets transfer that into arrays of UNIT availability + return; } From 44a9eca06150d9ba2e3610e46551f559868a555d Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 28 Nov 2023 16:54:53 +0100 Subject: [PATCH 202/315] refactor availableDailyPower --- .../AuxillaryStructures.cpp | 18 +++++++----------- .../AuxillaryStructures.h | 2 +- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.cpp b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.cpp index 66e8819abe..11a8e2ccac 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.cpp @@ -44,14 +44,10 @@ std::vector Maintenances::getStartSolutionValues() const return solutionValues; } -std::vector> Unit::availableDailyPower(int tsCount) const +std::vector Unit::availableDailyPower(int tsCount) const { - std::vector> result(tsCount, - std::array{}); - for (auto& arr : result) - { - arr.fill(100.0); // Set each array to the value 100.0 - } + int totalDays = tsCount * DAYS_PER_YEAR; + std::vector result(totalDays, 10); for (const auto& maintenance : maintenanceResults) { @@ -59,12 +55,12 @@ std::vector> Unit::availableDailyPower(int tsC int duration = maintenance.second; int end = start + duration; - if (end > DAYS_PER_YEAR) - end = DAYS_PER_YEAR; + if (end > totalDays) + end = totalDays; - for (int i = start; i < end; ++i) + for (int mnt = start; mnt < end; ++mnt) { - result[0][i] = 0.0; // Assuming index is in range [0, 8760) + result[mnt] = 0.0; } } return result; diff --git a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h index 16d08b1b43..08a9805f33 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h +++ b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h @@ -65,7 +65,7 @@ struct Unit std::vector> maintenanceResults; // methods - std::vector> availableDailyPower(int tsCount) const; + std::vector availableDailyPower(int tsCount) const; }; struct OptimizationProblemVariables From 631503d1228d35119b9d0c33753b75f245ceba24 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 28 Nov 2023 17:07:31 +0100 Subject: [PATCH 203/315] upgrade calculateAvailableDailyPower --- .../optimized-thermal-generator/AuxillaryStructures.cpp | 9 +++++---- .../optimized-thermal-generator/AuxillaryStructures.h | 3 ++- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.cpp b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.cpp index 11a8e2ccac..bcec0db41e 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.cpp @@ -44,10 +44,12 @@ std::vector Maintenances::getStartSolutionValues() const return solutionValues; } -std::vector Unit::availableDailyPower(int tsCount) const +void Unit::calculateAvailableDailyPower(int tsCount) { int totalDays = tsCount * DAYS_PER_YEAR; - std::vector result(totalDays, 10); + double maxPower = parentCluster->nominalCapacity; + availableDailyPower.resize(totalDays); + std::fill(availableDailyPower.begin(), availableDailyPower.end(), maxPower); for (const auto& maintenance : maintenanceResults) { @@ -60,10 +62,9 @@ std::vector Unit::availableDailyPower(int tsCount) const for (int mnt = start; mnt < end; ++mnt) { - result[mnt] = 0.0; + availableDailyPower[mnt] = 0.0; } } - return result; } } // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h index 08a9805f33..76363c9550 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h +++ b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h @@ -63,9 +63,10 @@ struct Unit // first element of the pair is start of the maintenance // second element of the pair is randomly drawn maintenance duration std::vector> maintenanceResults; + std::vector availableDailyPower; // methods - std::vector availableDailyPower(int tsCount) const; + void calculateAvailableDailyPower(int tsCount); }; struct OptimizationProblemVariables From d6f50f046a9cb29b0715d98ecc71520626eb275c Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 28 Nov 2023 17:28:45 +0100 Subject: [PATCH 204/315] fix - reCalculateDaysSinceLastMnt --- .../OptimizedGenerator.h | 11 ++-- .../PostTimeStepOptimization.cpp | 56 ++++++++++--------- 2 files changed, 37 insertions(+), 30 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index b0a658ffda..508ab978bd 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -135,20 +135,21 @@ class OptimizedThermalGenerator : public GeneratorTempData // post-timeStep optimization methods void postTimeStepOptimization(OptProblemSettings& optSett); void appendTimeStepResults(const OptProblemSettings& optSett); - void reCalculateDaysSinceLastMnt(const OptProblemSettings& optSett); void reSetDaysSinceLastMnt(); + void reCalculateDaysSinceLastMnt(const OptProblemSettings& optSett); + void reCalculateDaysSinceLastMnt(const OptProblemSettings& optSett, const Unit& unit); int reCalculateDaysSinceLastMnt(const OptProblemSettings& optSett, const Unit& unit, bool maintenanceHappened, int lastMaintenanceStart, int lastMaintenanceDuration); - /* ===================END-POST-OPTIMIZATION=================== */ + /* ===================END-POST-OPTIMIZATION=================== */ - /* ===================CALCULATE-OPTIMIZATION-PARAMETERS=================== */ + /* ===================CALCULATE-OPTIMIZATION-PARAMETERS=================== */ - // Calculate parameters methods - per maintenance group - void setMaintenanceGroupParameters(); + // Calculate parameters methods - per maintenance group + void setMaintenanceGroupParameters(); bool checkMaintenanceGroupParameters(); std::pair calculateTimeHorizonAndStep(); std::pair calculateMaintenanceGroupENSandSpillageCost(); diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp index 3e59bf5681..2809ee9fa5 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp @@ -114,35 +114,41 @@ void OptimizedThermalGenerator::reCalculateDaysSinceLastMnt(const OptProblemSett // re-calculate days since last maintenance inputs if necessary for (const auto& unit : scenarioResults) { - int newDaysSinceLastMaintenance = 0; - bool maintenanceHappened = false; - - if (unit.maintenanceResults.empty()) - { - newDaysSinceLastMaintenance - = reCalculateDaysSinceLastMnt(optSett, unit, maintenanceHappened, 0, 0); - } + reCalculateDaysSinceLastMnt(optSett, unit); + } +} - int lastMaintenanceStart = unit.maintenanceResults.back().first; - // check if maintenance happened in the observed timeStep - // remember maintenanceResults - stores all the maintenances - // last maintenance may be from some earlier timeStep - if (lastMaintenanceStart < optSett.firstDay) - { - newDaysSinceLastMaintenance - = reCalculateDaysSinceLastMnt(optSett, unit, maintenanceHappened, 0, 0); - } +void OptimizedThermalGenerator::reCalculateDaysSinceLastMnt(const OptProblemSettings& optSett, + const Unit& unit) +{ + auto& daysSinceLastMaintenance = maintenanceData.areaMap[unit.parentCluster->parentArea] + .clusterMap[unit.parentCluster] + .daysSinceLastMaintenance[unit.index]; + bool maintenanceHappened = false; - maintenanceHappened = true; - int lastMaintenanceDuration = unit.maintenanceResults.back().second; - newDaysSinceLastMaintenance = reCalculateDaysSinceLastMnt( - optSett, unit, maintenanceHappened, lastMaintenanceStart, lastMaintenanceDuration); + if (unit.maintenanceResults.empty()) + { + daysSinceLastMaintenance + = reCalculateDaysSinceLastMnt(optSett, unit, maintenanceHappened, 0, 0); + return; + } - maintenanceData.areaMap[unit.parentCluster->parentArea] - .clusterMap[unit.parentCluster] - .daysSinceLastMaintenance[unit.index] - = newDaysSinceLastMaintenance; + int lastMaintenanceStart = unit.maintenanceResults.back().first; + // check if maintenance happened in the observed timeStep + // remember maintenanceResults - stores all the maintenances + // last maintenance may be from some earlier timeStep + if (lastMaintenanceStart < optSett.firstDay) + { + daysSinceLastMaintenance + = reCalculateDaysSinceLastMnt(optSett, unit, maintenanceHappened, 0, 0); + return; } + + maintenanceHappened = true; + int lastMaintenanceDuration = unit.maintenanceResults.back().second; + daysSinceLastMaintenance = reCalculateDaysSinceLastMnt( + optSett, unit, maintenanceHappened, lastMaintenanceStart, lastMaintenanceDuration); + return; } int OptimizedThermalGenerator::reCalculateDaysSinceLastMnt(const OptProblemSettings& optSett, From ed6ed080dd913cd7f5966580627a3b4dd80d04d8 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 28 Nov 2023 17:41:06 +0100 Subject: [PATCH 205/315] TODO --- .../optimized-thermal-generator/AuxillaryStructures.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.cpp b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.cpp index bcec0db41e..43ae6418da 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.cpp @@ -47,6 +47,7 @@ std::vector Maintenances::getStartSolutionValues() const void Unit::calculateAvailableDailyPower(int tsCount) { int totalDays = tsCount * DAYS_PER_YEAR; + // TODO CR27: ask Hugo. Do we take nom capacity or dailyPower. - and then later do mean for hourly values double maxPower = parentCluster->nominalCapacity; availableDailyPower.resize(totalDays); std::fill(availableDailyPower.begin(), availableDailyPower.end(), maxPower); From 636e28236ddb2bf007f62363537a3cfcf4ced279 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 28 Nov 2023 17:41:33 +0100 Subject: [PATCH 206/315] call and test calculateAvailableDailyPower - ok --- .../PostScenarioOptimization.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp index 6c536ac3d1..f6257f6122 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp @@ -24,7 +24,13 @@ void OptimizedThermalGenerator::calculateScenarioResults(const OptProblemSetting { // for each unit we have now scenarioResults // which contains std::pairs of all [maintenanceStart, maintenanceDuration] - // lets transfer that into arrays of UNIT availability + // lets transfer that into vectors of UNIT availability + + // loop per units + for (auto& unit : scenarioResults) + { + unit.calculateAvailableDailyPower(scenarioLength_); + } return; } From 5063434ef006b3eb8dacd07056b7ab0b8dce7da0 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 28 Nov 2023 18:59:07 +0100 Subject: [PATCH 207/315] calculateScenarioResults tested ok --- .../AuxillaryStructures.h | 18 +++++++-- .../PostScenarioOptimization.cpp | 40 +++++++++++++++++++ 2 files changed, 55 insertions(+), 3 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h index 76363c9550..107ef94b21 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h +++ b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h @@ -56,13 +56,16 @@ struct Unit // results // we will store results in the same structure // however we need separate instance of this struct - // since the object that stores optimization variables is cleared after each timeStep - // and the results need to be saved/appended for each timeStep + // since the object that stores optimization variables is cleared after each optimization + // and the results need to be saved/appended for all optimizations (time steps) - // number of elements in the vector is number of maintenances + // number of elements in the vector is TOTAL number of maintenances + // all the maintenances after all the time steps - not just one optimization // first element of the pair is start of the maintenance // second element of the pair is randomly drawn maintenance duration std::vector> maintenanceResults; + // after all the maintenances are determined + // we calculate UNIT availability - we do this once after all optimizations std::vector availableDailyPower; // methods @@ -86,8 +89,11 @@ struct OptimizationProblemVariables // this structure stores cluster input data (optimization parameters) // that stays the same during optimizationS +// also temporary stores cluster output/results for one scenario struct ClusterData { + // input data + // calculated once before all loops std::array maxPower; std::array avgCost; std::vector daysSinceLastMaintenance; @@ -97,6 +103,12 @@ struct ClusterData // for random generator double AP[366]; double BP[366]; + + // scenario results + // temporary store scenario results + // before writing them to output + // reset after each scenario + std::vector availableClusterDailyPower; }; struct AreaData diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp index f6257f6122..533d06517a 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp @@ -32,6 +32,35 @@ void OptimizedThermalGenerator::calculateScenarioResults(const OptProblemSetting unit.calculateAvailableDailyPower(scenarioLength_); } + // now lets get CLUSTER availability by summing up UNIT availability + + // fill in with zeros + for (auto& area : maintenanceData.areaMap) + { + for (auto& cluster : area.second.clusterMap) + { + cluster.second.availableClusterDailyPower.resize(scenarioLength_ * DAYS_PER_YEAR); + } + } + + // add one by one unit availability + for (auto& unit : scenarioResults) + { + auto& availableClusterDailyPower = maintenanceData.areaMap[unit.parentCluster->parentArea] + .clusterMap[unit.parentCluster] + .availableClusterDailyPower; + + std::transform(availableClusterDailyPower.begin(), + availableClusterDailyPower.end(), + unit.availableDailyPower.begin(), + availableClusterDailyPower.begin(), + std::plus()); + } + + // do not convert to hourly values yet + // why waste memory - convert to hourly just before writing to ts + // and then delete - local variable + return; } @@ -47,7 +76,18 @@ void OptimizedThermalGenerator::saveScenarioResults(const OptProblemSettings& op void OptimizedThermalGenerator::resetResultStorage() { + // clear units result structure scenarioResults.clear(); + // clear cluster result structure + // do not clear whole maintenanceData + // we store input data here as well + for (auto& area : maintenanceData.areaMap) + { + for (auto& cluster : area.second.clusterMap) + { + cluster.second.availableClusterDailyPower.clear(); + } + } return; } From fdb701013c9a1b957dec42d1076dffdceec7b147 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 28 Nov 2023 19:05:09 +0100 Subject: [PATCH 208/315] small rename --- .../optimized-thermal-generator/AuxillaryStructures.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.cpp b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.cpp index 43ae6418da..53ceb95f35 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.cpp @@ -61,9 +61,9 @@ void Unit::calculateAvailableDailyPower(int tsCount) if (end > totalDays) end = totalDays; - for (int mnt = start; mnt < end; ++mnt) + for (int day = start; day < end; ++day) { - availableDailyPower[mnt] = 0.0; + availableDailyPower[day] = 0.0; } } } From 75f0aa5153747342bb636dcb89cbaecffa88e846 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 28 Nov 2023 20:10:17 +0100 Subject: [PATCH 209/315] move reSetDaysSinceLastMnt to postScenario actions fix - reCalculateDaysSinceLastMnt - it is called first time after first optimization but before optSett.firstDay is set to false --- .../OptimizedGenerator.h | 2 +- .../PostScenarioOptimization.cpp | 19 ++++++++++++++++ .../PostTimeStepOptimization.cpp | 22 ------------------- 3 files changed, 20 insertions(+), 23 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 508ab978bd..d640ce76a0 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -130,12 +130,12 @@ class OptimizedThermalGenerator : public GeneratorTempData void calculateScenarioResults(const OptProblemSettings& optSett); void saveScenarioResults(const OptProblemSettings& optSett); void resetResultStorage(); + void reSetDaysSinceLastMnt(); void writeTsResults(); // post-timeStep optimization methods void postTimeStepOptimization(OptProblemSettings& optSett); void appendTimeStepResults(const OptProblemSettings& optSett); - void reSetDaysSinceLastMnt(); void reCalculateDaysSinceLastMnt(const OptProblemSettings& optSett); void reCalculateDaysSinceLastMnt(const OptProblemSettings& optSett, const Unit& unit); int reCalculateDaysSinceLastMnt(const OptProblemSettings& optSett, diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp index 533d06517a..c4510c86b5 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp @@ -16,6 +16,7 @@ void OptimizedThermalGenerator::postScenarioOptimization(OptProblemSettings& opt calculateScenarioResults(optSett); saveScenarioResults(optSett); resetResultStorage(); + reSetDaysSinceLastMnt(); return; } @@ -91,6 +92,24 @@ void OptimizedThermalGenerator::resetResultStorage() return; } +void OptimizedThermalGenerator::reSetDaysSinceLastMnt() +{ + // we are back in first step, but not first scenario + // we have messed up our values + // we need to re-do + // daysSinceLastMaintenance = cluster.originalRandomlyGeneratedDaysSinceLastMaintenance; + // for all areas and clusters + for (auto& area : maintenanceData.areaMap) + { + for (auto& cluster : area.second.clusterMap) + { + cluster.second.daysSinceLastMaintenance + = cluster.first->originalRandomlyGeneratedDaysSinceLastMaintenance; + } + } + return; +} + // this method is called at the very end // after all time-steps and scenarios void OptimizedThermalGenerator::writeTsResults() diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp index 2809ee9fa5..fd224f19d0 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp @@ -86,31 +86,9 @@ void OptimizedThermalGenerator::appendTimeStepResults(const OptProblemSettings& } // re-calculate parameters -void OptimizedThermalGenerator::reSetDaysSinceLastMnt() -{ - // we are back in first step, but not first scenario - // we have messed up our values - // we need to re-do - // daysSinceLastMaintenance = cluster.originalRandomlyGeneratedDaysSinceLastMaintenance; - // for all areas and clusters - for (auto& area : maintenanceData.areaMap) - { - for (auto& cluster : area.second.clusterMap) - { - cluster.second.daysSinceLastMaintenance - = cluster.first->originalRandomlyGeneratedDaysSinceLastMaintenance; - } - } - return; -} void OptimizedThermalGenerator::reCalculateDaysSinceLastMnt(const OptProblemSettings& optSett) { - if (optSett.scenario == 0 && optSett.isFirstStep) - return; - if (optSett.scenario != 0 && optSett.isFirstStep) - reSetDaysSinceLastMnt(); - // re-calculate days since last maintenance inputs if necessary for (const auto& unit : scenarioResults) { From 2b231dd0f15decbe5d5c515248195532444d43cc Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 28 Nov 2023 20:57:59 +0100 Subject: [PATCH 210/315] refactor - simplify maintenanceData structure - one loop only --- .../AuxillaryStructures.h | 11 ------ .../CalculateParameters.cpp | 39 +++++++------------ .../OptimizedGenerator.h | 35 +++++++---------- .../PostScenarioOptimization.cpp | 34 +++++++--------- .../PostTimeStepOptimization.cpp | 13 ++----- 5 files changed, 47 insertions(+), 85 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h index 107ef94b21..0c826f489d 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h +++ b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h @@ -111,16 +111,5 @@ struct ClusterData std::vector availableClusterDailyPower; }; -struct AreaData -{ - // number of elements in the map is total number of cluster in area - std::map clusterMap; -}; - -struct MaintenanceData -{ - // number of elements in the map is total number of areas in maintenance group - std::map areaMap; -}; } // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp index 0d1f065e82..a8c4995705 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp @@ -141,8 +141,6 @@ void OptimizedThermalGenerator::setClusterData() for (const auto& entryWeightMap : maintenanceGroup_) { const auto& area = *(entryWeightMap.first); - auto& areaData = maintenanceData.areaMap; - areaData[&area] = AreaData(); // loop per thermal clusters inside the area - fill in the structure for (const auto& clusterEntry : area.thermal.list.mapping) { @@ -153,26 +151,25 @@ void OptimizedThermalGenerator::setClusterData() if (!checkClusterExist(cluster)) continue; - auto& clusterData = areaData[&area].clusterMap; - clusterData[&cluster] = ClusterData(); - clusterData[&cluster].maxPower = calculateMaxUnitOutput(cluster); - clusterData[&cluster].avgCost = calculateAvrUnitDailyCost(cluster); + maintenanceData[&cluster] = ClusterData(); + maintenanceData[&cluster].maxPower = calculateMaxUnitOutput(cluster); + maintenanceData[&cluster].avgCost = calculateAvrUnitDailyCost(cluster); - clusterData[&cluster].numberOfMaintenances + maintenanceData[&cluster].numberOfMaintenances = calculateNumberOfMaintenances(cluster, timeHorizon_); - clusterData[&cluster].averageMaintenanceDuration + maintenanceData[&cluster].averageMaintenanceDuration = calculateAverageMaintenanceDuration(cluster); // since we will be updating daysSinceLastMaintenance values // lets create a copy here - this is copy by value! - clusterData[&cluster].daysSinceLastMaintenance + maintenanceData[&cluster].daysSinceLastMaintenance = cluster.originalRandomlyGeneratedDaysSinceLastMaintenance; // random generator prepareIndispoFromLaw(cluster.plannedLaw, cluster.plannedVolatility, - clusterData[&cluster].AP, - clusterData[&cluster].BP, + maintenanceData[&cluster].AP, + maintenanceData[&cluster].BP, cluster.prepro->data[Data::PreproThermal::poDuration]); } } @@ -208,17 +205,13 @@ double OptimizedThermalGenerator::getPowerCost(const Data::ThermalCluster& clust return 0.; } - return maintenanceData.areaMap[cluster.parentArea] - .clusterMap[&cluster] - .avgCost[dayOfTheYear(optimizationDay)]; + return maintenanceData[&cluster].avgCost[dayOfTheYear(optimizationDay)]; } double OptimizedThermalGenerator::getPowerOutput(const Data::ThermalCluster& cluster, int optimizationDay) { - return maintenanceData.areaMap[cluster.parentArea] - .clusterMap[&cluster] - .maxPower[dayOfTheYear(optimizationDay)]; + return maintenanceData[&cluster].maxPower[dayOfTheYear(optimizationDay)]; } double OptimizedThermalGenerator::getResidualLoad(int optimizationDay) @@ -228,14 +221,12 @@ double OptimizedThermalGenerator::getResidualLoad(int optimizationDay) int OptimizedThermalGenerator::getNumberOfMaintenances(const Data::ThermalCluster& cluster) { - return maintenanceData.areaMap[cluster.parentArea].clusterMap[&cluster].numberOfMaintenances; + return maintenanceData[&cluster].numberOfMaintenances; } int OptimizedThermalGenerator::getAverageMaintenanceDuration(const Data::ThermalCluster& cluster) { - return maintenanceData.areaMap[cluster.parentArea] - .clusterMap[&cluster] - .averageMaintenanceDuration; + return maintenanceData[&cluster].averageMaintenanceDuration; } int OptimizedThermalGenerator::getAverageDurationBetweenMaintenances( @@ -253,8 +244,7 @@ int OptimizedThermalGenerator::calculateUnitEarliestStartOfFirstMaintenance( // let it return negative value - if it returns negative value we wont implement constraint: // s[u][0][tauLower-1] = 0 - auto& daysSinceLastMaintenance - = maintenanceData.areaMap[cluster.parentArea].clusterMap[&cluster].daysSinceLastMaintenance; + auto& daysSinceLastMaintenance = maintenanceData[&cluster].daysSinceLastMaintenance; if (unitIndex < daysSinceLastMaintenance.size()) { @@ -274,8 +264,7 @@ int OptimizedThermalGenerator::calculateUnitLatestStartOfFirstMaintenance( { // latest start of the first maintenance of unit u (end of the window, must be positive): - auto& daysSinceLastMaintenance - = maintenanceData.areaMap[cluster.parentArea].clusterMap[&cluster].daysSinceLastMaintenance; + auto& daysSinceLastMaintenance = maintenanceData[&cluster].daysSinceLastMaintenance; if (unitIndex < daysSinceLastMaintenance.size()) { diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index d640ce76a0..1148752139 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -22,9 +22,11 @@ namespace Antares::Solver::TSGenerator class OptimizedThermalGenerator : public GeneratorTempData { + using MaintenanceClusterStorage = std::map; + using ScenarioResults = std::vector; + private: - - /* ===================OPTIMIZATION=================== */ + /* ===================OPTIMIZATION=================== */ // functions to build problem variables void buildProblemVariables(const OptProblemSettings& optSett); @@ -112,18 +114,17 @@ class OptimizedThermalGenerator : public GeneratorTempData void printResults(); void printProblemVarAndResults(); + /* ===================END-OPTIMIZATION=================== */ - /* ===================END-OPTIMIZATION=================== */ - - /* ===================MAIN=================== */ + /* ===================MAIN=================== */ // Functions called in main method: void allocateWhereToWriteTs(); bool runOptimizationProblem(OptProblemSettings& optSett); - /* ===================END-MAIN=================== */ + /* ===================END-MAIN=================== */ - /* ===================POST-OPTIMIZATION=================== */ + /* ===================POST-OPTIMIZATION=================== */ // post-scenario optimization methods void postScenarioOptimization(OptProblemSettings& optSett); @@ -170,9 +171,9 @@ class OptimizedThermalGenerator : public GeneratorTempData int calculateUnitLatestStartOfFirstMaintenance(const Data::ThermalCluster& cluster, uint unitIndex); - /* ===================END-CALCULATE-OPTIMIZATION-PARAMETERS=================== */ + /* ===================END-CALCULATE-OPTIMIZATION-PARAMETERS=================== */ - /* ===================CLASS-VARIABLES=================== */ + /* ===================CLASS-VARIABLES=================== */ // variables Data::MaintenanceGroup& maintenanceGroup_; @@ -184,26 +185,20 @@ class OptimizedThermalGenerator : public GeneratorTempData double ensCost_; double spillCost_; std::array residualLoadDailyValues_; - /* - TODO CR27: - phase two - idea for refactoring - - make MaintenanceData a class - and then move all methods for optimization problem parameters calculation to that class - */ - MaintenanceData maintenanceData; + MaintenanceClusterStorage maintenanceData; /* TODO CR27: same for OptimizationProblemVariables - maybe new class - and move optimization methods away from here + and move optimization methods away from here */ OptimizationProblemVariables vars; - std::vector scenarioResults; + ScenarioResults scenarioResults; // MPSolver instance MPSolver solver; double solverInfinity; - /* ===================END-CLASS-VARIABLES=================== */ + /* ===================END-CLASS-VARIABLES=================== */ public: explicit OptimizedThermalGenerator(Data::Study& study, @@ -238,7 +233,7 @@ class OptimizedThermalGenerator : public GeneratorTempData ~OptimizedThermalGenerator() = default; - // Main functions - loop per scenarios and + // Main functions - loop per scenarios and // through the scenario length step by step // (moving window) void GenerateOptimizedThermalTimeSeries(); diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp index c4510c86b5..6bc997ae95 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp @@ -36,20 +36,16 @@ void OptimizedThermalGenerator::calculateScenarioResults(const OptProblemSetting // now lets get CLUSTER availability by summing up UNIT availability // fill in with zeros - for (auto& area : maintenanceData.areaMap) + for (auto& cluster : maintenanceData) { - for (auto& cluster : area.second.clusterMap) - { - cluster.second.availableClusterDailyPower.resize(scenarioLength_ * DAYS_PER_YEAR); - } + cluster.second.availableClusterDailyPower.resize(scenarioLength_ * DAYS_PER_YEAR); } // add one by one unit availability for (auto& unit : scenarioResults) { - auto& availableClusterDailyPower = maintenanceData.areaMap[unit.parentCluster->parentArea] - .clusterMap[unit.parentCluster] - .availableClusterDailyPower; + auto& availableClusterDailyPower + = maintenanceData[unit.parentCluster].availableClusterDailyPower; std::transform(availableClusterDailyPower.begin(), availableClusterDailyPower.end(), @@ -82,13 +78,12 @@ void OptimizedThermalGenerator::resetResultStorage() // clear cluster result structure // do not clear whole maintenanceData // we store input data here as well - for (auto& area : maintenanceData.areaMap) + + for (auto& cluster : maintenanceData) { - for (auto& cluster : area.second.clusterMap) - { - cluster.second.availableClusterDailyPower.clear(); - } + cluster.second.availableClusterDailyPower.clear(); } + return; } @@ -99,14 +94,13 @@ void OptimizedThermalGenerator::reSetDaysSinceLastMnt() // we need to re-do // daysSinceLastMaintenance = cluster.originalRandomlyGeneratedDaysSinceLastMaintenance; // for all areas and clusters - for (auto& area : maintenanceData.areaMap) + + for (auto& cluster : maintenanceData) { - for (auto& cluster : area.second.clusterMap) - { - cluster.second.daysSinceLastMaintenance - = cluster.first->originalRandomlyGeneratedDaysSinceLastMaintenance; - } + cluster.second.daysSinceLastMaintenance + = cluster.first->originalRandomlyGeneratedDaysSinceLastMaintenance; } + return; } @@ -116,7 +110,7 @@ void OptimizedThermalGenerator::writeTsResults() { // we need to loop through all the clusters // and write the results - // it would be much easier to loop using MaintenanceData structure + // it would be much easier to loop using maintenanceData // inside of it we already excluded all the non-important clusters // however it is const Data::ThermalCluster* // so we cannot modify cluster values diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp index fd224f19d0..8514a059a8 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp @@ -68,12 +68,8 @@ void OptimizedThermalGenerator::appendTimeStepResults(const OptProblemSettings& int PODOfTheDay = (int)cluster.prepro->data[Data::PreproThermal::poDuration][dayInTheYearStart]; - double app = maintenanceData.areaMap[cluster.parentArea] - .clusterMap[&cluster] - .AP[dayInTheYearStart]; - double bpp = maintenanceData.areaMap[cluster.parentArea] - .clusterMap[&cluster] - .BP[dayInTheYearStart]; + double app = maintenanceData[&cluster].AP[dayInTheYearStart]; + double bpp = maintenanceData[&cluster].BP[dayInTheYearStart]; int maintenanceDuration = durationGenerator( cluster.plannedLaw, PODOfTheDay, cluster.plannedVolatility, app, bpp); @@ -99,9 +95,8 @@ void OptimizedThermalGenerator::reCalculateDaysSinceLastMnt(const OptProblemSett void OptimizedThermalGenerator::reCalculateDaysSinceLastMnt(const OptProblemSettings& optSett, const Unit& unit) { - auto& daysSinceLastMaintenance = maintenanceData.areaMap[unit.parentCluster->parentArea] - .clusterMap[unit.parentCluster] - .daysSinceLastMaintenance[unit.index]; + auto& daysSinceLastMaintenance + = maintenanceData[unit.parentCluster].daysSinceLastMaintenance[unit.index]; bool maintenanceHappened = false; if (unit.maintenanceResults.empty()) From 9472bcbf2bdb59f50606ef5a8e4721dc1280cc05 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 28 Nov 2023 21:12:01 +0100 Subject: [PATCH 211/315] small refactor - simplification in build variables --- .../CreateVariables.cpp | 25 +++---------------- .../OptimizedGenerator.h | 1 - 2 files changed, 3 insertions(+), 23 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp b/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp index e82ca3a220..0ce8bcf5e6 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp @@ -28,36 +28,17 @@ void OptimizedThermalGenerator::buildEnsAndSpillageVariables(const OptProblemSet vars.spill.push_back(solver.MakeNumVar( 0.0, solverInfinity, "Spill_[" + std::to_string(day + optSett.firstDay) + "]")); } - return; } // create VARIABLES per day and per cluster-unit - P[u][t] -void OptimizedThermalGenerator::buildUnitPowerOutputVariables(const OptProblemSettings& optSett) -{ - // loop per areas inside maintenance group - for (const auto& entryWeightMap : maintenanceGroup_) - { - const auto& area = *(entryWeightMap.first); - buildUnitPowerOutputVariables(optSett, area); - } -} -void OptimizedThermalGenerator::buildUnitPowerOutputVariables(const OptProblemSettings& optSett, - const Data::Area& area) +void OptimizedThermalGenerator::buildUnitPowerOutputVariables(const OptProblemSettings& optSett) { // loop per thermal clusters inside the area - for (const auto& clusterEntry : area.thermal.list.mapping) + for (const auto& clusterEntry : maintenanceData) { - const auto& cluster = *(clusterEntry.second); - - // we do not check if cluster.optimizeMaintenance = true here - // we add all the clusters Power inside maintenance group - // into optimization problem - // we will exclude only start & end variables if optimizeMaintenance = false - if (!checkClusterExist(cluster)) - continue; - + const auto& cluster = *(clusterEntry.first); buildUnitPowerOutputVariables(optSett, cluster); } } diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 1148752139..a6e01cfb1a 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -32,7 +32,6 @@ class OptimizedThermalGenerator : public GeneratorTempData void buildProblemVariables(const OptProblemSettings& optSett); void buildEnsAndSpillageVariables(const OptProblemSettings& optSett); void buildUnitPowerOutputVariables(const OptProblemSettings& optSett); - void buildUnitPowerOutputVariables(const OptProblemSettings& optSett, const Data::Area& area); void buildUnitPowerOutputVariables(const OptProblemSettings& optSett, const Data::ThermalCluster& cluster); void buildUnitPowerOutputVariables(const OptProblemSettings& optSett, From e28fd38134872c259ec5d2ce036e5239b4a299ba Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 28 Nov 2023 21:14:24 +0100 Subject: [PATCH 212/315] small refactor --- .../optimized-thermal-generator/OptimizedGenerator.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp index dbadc8bfa8..624e426f51 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp @@ -45,14 +45,13 @@ void OptimizedThermalGenerator::GenerateOptimizedThermalTimeSeries() void OptimizedThermalGenerator::allocateWhereToWriteTs() { // loop per areas inside maintenance group - for (const auto& entryWeightMap : maintenanceGroup_) + for (auto& entryWeightMap : maintenanceGroup_) { - const auto& area = *(entryWeightMap.first); + auto& area = *(entryWeightMap.first); // loop per thermal clusters inside the area - for (auto it = area.thermal.list.mapping.begin(); it != area.thermal.list.mapping.end(); - ++it) + for (auto& clusterEntry : area.thermal.list.mapping) { - auto& cluster = *(it->second); + auto& cluster = *(clusterEntry.second); // check if cluster exist, do we generate + optimizeMaintenance // create start end variables only for these clusters From d69175d6e46648220d4209d167b55ed9cca911e3 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 28 Nov 2023 21:46:10 +0100 Subject: [PATCH 213/315] saveScenarioResults [WIP] --- .../OptimizedGenerator.h | 1 + .../PostScenarioOptimization.cpp | 31 +++++++++++++++++-- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index a6e01cfb1a..d7bbea6399 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -129,6 +129,7 @@ class OptimizedThermalGenerator : public GeneratorTempData void postScenarioOptimization(OptProblemSettings& optSett); void calculateScenarioResults(const OptProblemSettings& optSett); void saveScenarioResults(const OptProblemSettings& optSett); + void saveScenarioResults(int from, int to, Data::ThermalCluster& cluster); void resetResultStorage(); void reSetDaysSinceLastMnt(); void writeTsResults(); diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp index 6bc997ae95..eb835b389d 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp @@ -63,12 +63,39 @@ void OptimizedThermalGenerator::calculateScenarioResults(const OptProblemSetting void OptimizedThermalGenerator::saveScenarioResults(const OptProblemSettings& optSett) { - // save results + // loop through all clusters and write results + // for one scenario into designated columns + // daily results are in maintenanceData.availableClusterDailyPower + // convert to hourly values and store in cluster ts int colSaveFrom = optSett.scenario * scenarioLength_; int colSaveTo = colSaveFrom + scenarioLength_ - 1; - // loop through all areas and clusters and write results for one scenario + // using on purpose this double loop + // because looping through maintenanceData we cannot change cluster + // const Data::ThermalCluster* + for (auto& entryWeightMap : maintenanceGroup_) + { + auto& area = *(entryWeightMap.first); + for (auto& clusterEntry : area.thermal.list.mapping) + { + auto& cluster = *(clusterEntry.second); + bool genTS = checkClusterExist(cluster) + && cluster.doWeGenerateTS(globalThermalTSgeneration_) + && cluster.optimizeMaintenance; + if (!genTS) + continue; + + // write results + saveScenarioResults(colSaveFrom, colSaveTo, cluster); + } + } + return; +} + +void OptimizedThermalGenerator::saveScenarioResults(int from, int to, Data::ThermalCluster& cluster) +{ + cluster.series.timeSeries.fill(777.); // dummy for now } void OptimizedThermalGenerator::resetResultStorage() From 9e9474e0d8ac50d08b3409ffe2955e483c82633e Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 28 Nov 2023 23:15:58 +0100 Subject: [PATCH 214/315] saveScenarioResults - per cluster - not tested remove unused auxillary function --- .../AuxillaryFreeFunctions.cpp | 16 ----------- .../AuxillaryFreeFunctions.h | 2 -- .../OptimizedGenerator.cpp | 1 - .../OptimizedGenerator.h | 2 +- .../PostScenarioOptimization.cpp | 27 +++++++++++++++---- 5 files changed, 23 insertions(+), 25 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.cpp b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.cpp index d914847008..42e98c406f 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.cpp @@ -212,20 +212,4 @@ std::array calculateAvrUnitDailyCost(const Data::ThermalC return avrCostDailyValues; } -// post -optimization functions -std::array expandAndMean( - const std::array& inputArray) -{ - std::array outputArray; - - auto outputIter = outputArray.begin(); - for (auto value : inputArray) - { - double meanValue = value / 24.0; - std::fill(outputIter, outputIter + 24, meanValue); - outputIter += 24; - } - - return outputArray; -} } // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.h b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.h index bd7d38770b..1a74c82a52 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.h +++ b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.h @@ -32,6 +32,4 @@ int calculateAverageMaintenanceDuration(const Data::ThermalCluster& cluster); std::array calculateMaxUnitOutput(const Data::ThermalCluster& cluster); std::array calculateAvrUnitDailyCost(const Data::ThermalCluster& cluster); -// post -optimization functions -std::array expandAndMean(const std::array& inputArray); } // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp index 624e426f51..365a046a5c 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp @@ -63,7 +63,6 @@ void OptimizedThermalGenerator::allocateWhereToWriteTs() // allocate space cluster.series.timeSeries.reset(nbThermalTimeseries, 8760); - cluster.series.timeSeries.fill(777.); // dummy for now } } return; diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index d7bbea6399..16ab89a319 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -129,7 +129,7 @@ class OptimizedThermalGenerator : public GeneratorTempData void postScenarioOptimization(OptProblemSettings& optSett); void calculateScenarioResults(const OptProblemSettings& optSett); void saveScenarioResults(const OptProblemSettings& optSett); - void saveScenarioResults(int from, int to, Data::ThermalCluster& cluster); + void saveScenarioResults(int fromCol, int toCol, Data::ThermalCluster& cluster); void resetResultStorage(); void reSetDaysSinceLastMnt(); void writeTsResults(); diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp index eb835b389d..49ae5955af 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp @@ -65,11 +65,9 @@ void OptimizedThermalGenerator::saveScenarioResults(const OptProblemSettings& op { // loop through all clusters and write results // for one scenario into designated columns - // daily results are in maintenanceData.availableClusterDailyPower - // convert to hourly values and store in cluster ts int colSaveFrom = optSett.scenario * scenarioLength_; - int colSaveTo = colSaveFrom + scenarioLength_ - 1; + int colSaveTo = colSaveFrom + scenarioLength_; // using on purpose this double loop // because looping through maintenanceData we cannot change cluster @@ -93,9 +91,28 @@ void OptimizedThermalGenerator::saveScenarioResults(const OptProblemSettings& op return; } -void OptimizedThermalGenerator::saveScenarioResults(int from, int to, Data::ThermalCluster& cluster) +void OptimizedThermalGenerator::saveScenarioResults(int fromCol, + int toCol, + Data::ThermalCluster& cluster) { - cluster.series.timeSeries.fill(777.); // dummy for now + // daily results are in maintenanceData.availableClusterDailyPower + // convert to hourly values and store in cluster ts + // we assume that vector availableClusterDailyPower has: + // scenarioLength_ * DAYS_PER_YEAR element + // that we need to store inside columns from-to + + auto& availability = maintenanceData[&cluster].availableClusterDailyPower; + assert((toCol - fromCol) * DAYS_PER_YEAR == availability.size()); + + int vctCol = 0; + for (int col = fromCol; col < toCol; ++col) + { + for (int row = 0; row < HOURS_PER_YEAR; ++row) + { + cluster.series.timeSeries[col][row] = availability[vctCol * 365 + (int)(row / 24)]; + } + vctCol++; + } } void OptimizedThermalGenerator::resetResultStorage() From 4a25197d6fddc146ceec9e9ef4d2dd5a9cc90fed Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 29 Nov 2023 09:47:47 +0100 Subject: [PATCH 215/315] print maintenances - debug only - to be reverted --- .../OptimizedGenerator.h | 1 + .../PostScenarioOptimization.cpp | 1 + .../PrintProblemVarRes.cpp | 19 +++++++++++++++++++ 3 files changed, 21 insertions(+) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 16ab89a319..dea04a48f6 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -112,6 +112,7 @@ class OptimizedThermalGenerator : public GeneratorTempData void printConstraints(); void printResults(); void printProblemVarAndResults(); + void printMaintenances(); /* ===================END-OPTIMIZATION=================== */ diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp index 49ae5955af..fc5fe10e24 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp @@ -15,6 +15,7 @@ void OptimizedThermalGenerator::postScenarioOptimization(OptProblemSettings& opt calculateScenarioResults(optSett); saveScenarioResults(optSett); + printMaintenances(); resetResultStorage(); reSetDaysSinceLastMnt(); diff --git a/src/solver/ts-generator/optimized-thermal-generator/PrintProblemVarRes.cpp b/src/solver/ts-generator/optimized-thermal-generator/PrintProblemVarRes.cpp index 684920abbb..77bd0d23b9 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PrintProblemVarRes.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PrintProblemVarRes.cpp @@ -141,6 +141,25 @@ void OptimizedThermalGenerator::printResults() return; } +void OptimizedThermalGenerator::printMaintenances() +{ + std::vector> dataToPrint; + for (auto& unit : scenarioResults) + { + for (auto& mnt : unit.maintenanceResults) + { + std::vector RED; + RED.push_back(mnt.first); + RED.push_back(mnt.second); + dataToPrint.push_back(RED); + } + } + + printColumnToFile( + dataToPrint, + "/home/milos/Documents/RTEi/01-Antares/04-TestModels/REFACTOR-CR27-Maintenances.csv"); +} + // Define the auxiliary function outside the class template void printColumnToFile(const std::vector>& data, const std::string& filename) From 98c11ef6ddb68ba732754c1831b03b3a93f4a335 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 29 Nov 2023 14:54:41 +0100 Subject: [PATCH 216/315] clean TODOs --- .../optimized-thermal-generator/AuxillaryStructures.cpp | 1 - .../optimized-thermal-generator/CalculateParameters.cpp | 5 +++-- .../optimized-thermal-generator/OptimizedGenerator.h | 7 ++++--- .../randomized-thermal-generator/RandomizedGenerator.cpp | 4 ++-- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.cpp b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.cpp index 53ceb95f35..78a482dcf4 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.cpp @@ -47,7 +47,6 @@ std::vector Maintenances::getStartSolutionValues() const void Unit::calculateAvailableDailyPower(int tsCount) { int totalDays = tsCount * DAYS_PER_YEAR; - // TODO CR27: ask Hugo. Do we take nom capacity or dailyPower. - and then later do mean for hourly values double maxPower = parentCluster->nominalCapacity; availableDailyPower.resize(totalDays); std::fill(availableDailyPower.begin(), availableDailyPower.end(), maxPower); diff --git a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp index a8c4995705..f442076a49 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp @@ -262,7 +262,8 @@ int OptimizedThermalGenerator::calculateUnitLatestStartOfFirstMaintenance( const Data::ThermalCluster& cluster, uint unitIndex) { - // latest start of the first maintenance of unit u (end of the window, must be positive): + // latest start of the first maintenance of unit u (end of the window, must be positive - + // FIRST STEP ONLY): auto& daysSinceLastMaintenance = maintenanceData[&cluster].daysSinceLastMaintenance; @@ -274,7 +275,7 @@ int OptimizedThermalGenerator::calculateUnitLatestStartOfFirstMaintenance( // or zero // cluster.poWindows is positive or zero // however we will make sure it does not surpass timeHorizon_ - 1 value - // AFTER FIRST STEP it can go to negative value + // AFTER FIRST STEP it can go to negative value - so we will floor it to zero return std::min( std::max(0, diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index dea04a48f6..4eee122edc 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -186,12 +186,13 @@ class OptimizedThermalGenerator : public GeneratorTempData double ensCost_; double spillCost_; std::array residualLoadDailyValues_; - MaintenanceClusterStorage maintenanceData; /* TODO CR27: - same for OptimizationProblemVariables - maybe new class - and move optimization methods away from here + make MaintenanceClusterStorage and + OptimizationProblemVariables new classes + and move their methods away from here */ + MaintenanceClusterStorage maintenanceData; OptimizationProblemVariables vars; ScenarioResults scenarioResults; diff --git a/src/solver/ts-generator/randomized-thermal-generator/RandomizedGenerator.cpp b/src/solver/ts-generator/randomized-thermal-generator/RandomizedGenerator.cpp index 5644408c22..8a31b1ac84 100644 --- a/src/solver/ts-generator/randomized-thermal-generator/RandomizedGenerator.cpp +++ b/src/solver/ts-generator/randomized-thermal-generator/RandomizedGenerator.cpp @@ -492,13 +492,13 @@ void GeneratorTempData::operator()(Data::Area& area, Data::ThermalCluster& clust } } - if (derated) // TMP.INFO CR27: derated mode - averaging - keep it like this! + if (derated) cluster.series.timeSeries.averageTimeseries(); if (archive) writeResultsToDisk(area, cluster); - cluster.calculationOfSpinning(); // TODO CR27 // do we still need to call this function?! + cluster.calculationOfSpinning(); } } // namespace Antares::Solver::TSGenerator From 026127f5f81d0be3845bb019e6f388645c2bb322 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 29 Nov 2023 15:02:25 +0100 Subject: [PATCH 217/315] only first maintenance can happen in timeStep - do not loop mnt --- .../PostTimeStepOptimization.cpp | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp index 8514a059a8..72a66aef89 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp @@ -47,24 +47,21 @@ void OptimizedThermalGenerator::appendTimeStepResults(const OptProblemSettings& auto& cluster = *(readResultUnit.parentCluster); - // loop per maintenances of unit - - // TODO CR27: do we even have to loop through maintenances - // or only see if first maintenance start before timeStep_ - // rest (second, third) maintenances will definitely happen after timeStep_ ?! - // Talk with Hugo - // if createStartEndVariables for the readResultUnit is false // maintenances.size() is going to be zero - so in a way there is our check - for (int mnt = 0; mnt < readResultUnit.maintenances.size(); ++mnt) + if (readResultUnit.maintenances.empty()) + continue; + + // NO need to loop through maintenances + // only one maintenance can happen in the timeStep_ + // TODO CR27: in phase-II we may change this and looping will be necessary { - int localMaintenanceStart = readResultUnit.maintenances[mnt].startDay(timeStep_); + int localMaintenanceStart = readResultUnit.maintenances[0].startDay(timeStep_); if (localMaintenanceStart == -1) continue; int globalMaintenanceStart = localMaintenanceStart + optSett.firstDay; - int dayInTheYearStart - = dayOfTheYear(globalMaintenanceStart); // TODO CR27: check this with Hugo! + int dayInTheYearStart = dayOfTheYear(globalMaintenanceStart); int PODOfTheDay = (int)cluster.prepro->data[Data::PreproThermal::poDuration][dayInTheYearStart]; From 48f7327526fe4f814f092a7bde5405db2dbca1fd Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 29 Nov 2023 15:25:47 +0100 Subject: [PATCH 218/315] update comments --- .../optimized-thermal-generator/CalculateParameters.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp index f442076a49..83fa77a27c 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp @@ -161,6 +161,7 @@ void OptimizedThermalGenerator::setClusterData() = calculateAverageMaintenanceDuration(cluster); // since we will be updating daysSinceLastMaintenance values + // after every optimization // lets create a copy here - this is copy by value! maintenanceData[&cluster].daysSinceLastMaintenance = cluster.originalRandomlyGeneratedDaysSinceLastMaintenance; @@ -262,14 +263,14 @@ int OptimizedThermalGenerator::calculateUnitLatestStartOfFirstMaintenance( const Data::ThermalCluster& cluster, uint unitIndex) { - // latest start of the first maintenance of unit u (end of the window, must be positive - - // FIRST STEP ONLY): + // latest start of the first maintenance of unit u, must be positive - + // FIRST STEP ONLY! auto& daysSinceLastMaintenance = maintenanceData[&cluster].daysSinceLastMaintenance; if (unitIndex < daysSinceLastMaintenance.size()) { - // this cannot be negative: FIRST STEP ONLY + // cannot be negative: FIRST STEP ONLY // cluster.interPoPeriod - // cluster.originalRandomlyGeneratedDaysSinceLastMaintenance[unitIndex] - is always positive // or zero From 95a031b684f9c31acc4bfb698e1c7c797caf1123 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 29 Nov 2023 15:42:57 +0100 Subject: [PATCH 219/315] fix reCalculateDaysSinceLastMnt - as discussed with Hugo - not tested --- .../PostTimeStepOptimization.cpp | 22 +++++++------------ 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp index 72a66aef89..a4c15d3064 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp @@ -103,19 +103,10 @@ void OptimizedThermalGenerator::reCalculateDaysSinceLastMnt(const OptProblemSett return; } - int lastMaintenanceStart = unit.maintenanceResults.back().first; - // check if maintenance happened in the observed timeStep - // remember maintenanceResults - stores all the maintenances - // last maintenance may be from some earlier timeStep - if (lastMaintenanceStart < optSett.firstDay) - { - daysSinceLastMaintenance - = reCalculateDaysSinceLastMnt(optSett, unit, maintenanceHappened, 0, 0); - return; - } - maintenanceHappened = true; + int lastMaintenanceStart = unit.maintenanceResults.back().first; int lastMaintenanceDuration = unit.maintenanceResults.back().second; + daysSinceLastMaintenance = reCalculateDaysSinceLastMnt( optSett, unit, maintenanceHappened, lastMaintenanceStart, lastMaintenanceDuration); return; @@ -127,13 +118,16 @@ int OptimizedThermalGenerator::reCalculateDaysSinceLastMnt(const OptProblemSetti int lastMaintenanceStart, int lastMaintenanceDuration) { + int nextOptimizationFirstDay = optSett.firstDay + timeStep_; if (maintenanceHappened) return std::max( - 0, optSett.firstDay + timeStep_ - (lastMaintenanceStart + lastMaintenanceDuration)); + 0, nextOptimizationFirstDay - (lastMaintenanceStart + lastMaintenanceDuration)); + // we let this go into negative value + // it will only move the maintenance in the next optimization + // further away from start else - return timeStep_ + return nextOptimizationFirstDay + unit.parentCluster->originalRandomlyGeneratedDaysSinceLastMaintenance[unit.index]; - // this can lead LatestStartOfFirstMaintenance to negative!! } } // namespace Antares::Solver::TSGenerator From fb95d39ce102679e8b618527536c6ad47b0501a4 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 29 Nov 2023 15:43:54 +0100 Subject: [PATCH 220/315] todo comments --- .../optimized-thermal-generator/PostTimeStepOptimization.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp index a4c15d3064..5924044c4b 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp @@ -125,6 +125,7 @@ int OptimizedThermalGenerator::reCalculateDaysSinceLastMnt(const OptProblemSetti // we let this go into negative value // it will only move the maintenance in the next optimization // further away from start + // TODO CR27: no we don't! It broke the solver - we keep std::max for now! else return nextOptimizationFirstDay + unit.parentCluster->originalRandomlyGeneratedDaysSinceLastMaintenance[unit.index]; From e924a0481158840487a371713150856b192adbfb Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 29 Nov 2023 16:00:50 +0100 Subject: [PATCH 221/315] improve printing for debug --- .../OptimizedGenerator.h | 6 +++--- .../PostScenarioOptimization.cpp | 2 +- .../PrintProblemVarRes.cpp | 21 +++++++++++-------- .../SolveProbem.cpp | 2 +- 4 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 4eee122edc..a83a64a80b 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -110,9 +110,9 @@ class OptimizedThermalGenerator : public GeneratorTempData void printAllVariables(); void printObjectiveFunction(MPObjective* objective); void printConstraints(); - void printResults(); - void printProblemVarAndResults(); - void printMaintenances(); + void printResults(OptProblemSettings& optSett); + void printProblemVarAndResults(OptProblemSettings& optSett); + void printMaintenances(OptProblemSettings& optSett); /* ===================END-OPTIMIZATION=================== */ diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp index fc5fe10e24..a7928c5b0c 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp @@ -15,7 +15,7 @@ void OptimizedThermalGenerator::postScenarioOptimization(OptProblemSettings& opt calculateScenarioResults(optSett); saveScenarioResults(optSett); - printMaintenances(); + printMaintenances(optSett); resetResultStorage(); reSetDaysSinceLastMnt(); diff --git a/src/solver/ts-generator/optimized-thermal-generator/PrintProblemVarRes.cpp b/src/solver/ts-generator/optimized-thermal-generator/PrintProblemVarRes.cpp index 77bd0d23b9..334d0d368f 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PrintProblemVarRes.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PrintProblemVarRes.cpp @@ -12,12 +12,12 @@ namespace Antares::Solver::TSGenerator { -void OptimizedThermalGenerator::printProblemVarAndResults() +void OptimizedThermalGenerator::printProblemVarAndResults(OptProblemSettings& optSett) { printAllVariables(); printConstraints(); printObjectiveFunction(solver.MutableObjective()); - printResults(); + printResults(optSett); } void OptimizedThermalGenerator::printAllVariables() @@ -100,7 +100,7 @@ void OptimizedThermalGenerator::printObjectiveFunction(MPObjective* objective) return; } -void OptimizedThermalGenerator::printResults() +void OptimizedThermalGenerator::printResults(OptProblemSettings& optSett) { std::vector> dataToPrint; @@ -135,13 +135,15 @@ void OptimizedThermalGenerator::printResults() printf("Optimal objective value = %.2f\n", solver.MutableObjective()->Value()); - printColumnToFile( - dataToPrint, "/home/milos/Documents/RTEi/01-Antares/04-TestModels/REFACTOR-CR27-Results.csv"); + std::string fileName = "/home/milos/Documents/RTEi/01-Antares/04-TestModels/" + + std::to_string(optSett.firstDay) + "-Results.csv"; + + printColumnToFile(dataToPrint, fileName); return; } -void OptimizedThermalGenerator::printMaintenances() +void OptimizedThermalGenerator::printMaintenances(OptProblemSettings& optSett) { std::vector> dataToPrint; for (auto& unit : scenarioResults) @@ -155,9 +157,10 @@ void OptimizedThermalGenerator::printMaintenances() } } - printColumnToFile( - dataToPrint, - "/home/milos/Documents/RTEi/01-Antares/04-TestModels/REFACTOR-CR27-Maintenances.csv"); + std::string fileName = "/home/milos/Documents/RTEi/01-Antares/04-TestModels/" + + std::to_string(optSett.firstDay) + "-Maintenances.csv"; + + printColumnToFile(dataToPrint, fileName); } // Define the auxiliary function outside the class diff --git a/src/solver/ts-generator/optimized-thermal-generator/SolveProbem.cpp b/src/solver/ts-generator/optimized-thermal-generator/SolveProbem.cpp index 207e2734c5..78c6afa07f 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/SolveProbem.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/SolveProbem.cpp @@ -16,7 +16,7 @@ bool OptimizedThermalGenerator::runOptimizationProblem(OptProblemSettings& optSe setProblemCost(optSett); if (!solveProblem(optSett)) return false; - printProblemVarAndResults(); + printProblemVarAndResults(optSett); postTimeStepOptimization(optSett); return true; } From b713d37a8f7c5730a4736f4b29268f37c53a5e08 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 29 Nov 2023 16:02:16 +0100 Subject: [PATCH 222/315] remove unused parameters --- .../optimized-thermal-generator/OptimizedGenerator.h | 2 +- .../optimized-thermal-generator/PostScenarioOptimization.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index a83a64a80b..3462e1584d 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -128,7 +128,7 @@ class OptimizedThermalGenerator : public GeneratorTempData // post-scenario optimization methods void postScenarioOptimization(OptProblemSettings& optSett); - void calculateScenarioResults(const OptProblemSettings& optSett); + void calculateScenarioResults(); void saveScenarioResults(const OptProblemSettings& optSett); void saveScenarioResults(int fromCol, int toCol, Data::ThermalCluster& cluster); void resetResultStorage(); diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp index a7928c5b0c..02418b38ea 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp @@ -13,7 +13,7 @@ void OptimizedThermalGenerator::postScenarioOptimization(OptProblemSettings& opt if (!optSett.solved) return; - calculateScenarioResults(optSett); + calculateScenarioResults(); saveScenarioResults(optSett); printMaintenances(optSett); resetResultStorage(); @@ -22,7 +22,7 @@ void OptimizedThermalGenerator::postScenarioOptimization(OptProblemSettings& opt return; } -void OptimizedThermalGenerator::calculateScenarioResults(const OptProblemSettings& optSett) +void OptimizedThermalGenerator::calculateScenarioResults() { // for each unit we have now scenarioResults // which contains std::pairs of all [maintenanceStart, maintenanceDuration] From 1274bb6a7d64c461fae039e73f3c35927ecac27e Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 29 Nov 2023 16:35:42 +0100 Subject: [PATCH 223/315] print availability vector --- .../OptimizedGenerator.h | 1 + .../PostScenarioOptimization.cpp | 1 + .../PrintProblemVarRes.cpp | 27 ++++++++++++++++++- 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 3462e1584d..009e5d3526 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -113,6 +113,7 @@ class OptimizedThermalGenerator : public GeneratorTempData void printResults(OptProblemSettings& optSett); void printProblemVarAndResults(OptProblemSettings& optSett); void printMaintenances(OptProblemSettings& optSett); + void printAvailability(OptProblemSettings& optSett); /* ===================END-OPTIMIZATION=================== */ diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp index 02418b38ea..87ada01257 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp @@ -16,6 +16,7 @@ void OptimizedThermalGenerator::postScenarioOptimization(OptProblemSettings& opt calculateScenarioResults(); saveScenarioResults(optSett); printMaintenances(optSett); + printAvailability(optSett); resetResultStorage(); reSetDaysSinceLastMnt(); diff --git a/src/solver/ts-generator/optimized-thermal-generator/PrintProblemVarRes.cpp b/src/solver/ts-generator/optimized-thermal-generator/PrintProblemVarRes.cpp index 334d0d368f..a387861c54 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PrintProblemVarRes.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PrintProblemVarRes.cpp @@ -148,9 +148,13 @@ void OptimizedThermalGenerator::printMaintenances(OptProblemSettings& optSett) std::vector> dataToPrint; for (auto& unit : scenarioResults) { + std::vector RED; + RED.push_back(9999); + RED.push_back(9999); + dataToPrint.push_back(RED); for (auto& mnt : unit.maintenanceResults) { - std::vector RED; + RED.clear(); RED.push_back(mnt.first); RED.push_back(mnt.second); dataToPrint.push_back(RED); @@ -163,6 +167,27 @@ void OptimizedThermalGenerator::printMaintenances(OptProblemSettings& optSett) printColumnToFile(dataToPrint, fileName); } +void OptimizedThermalGenerator::printAvailability(OptProblemSettings& optSett) +{ + std::vector> dataToPrint; + + for (int day = 0; day != scenarioLength_ * 365; ++day) + { + std::vector RED; + for (auto& cluster : maintenanceData) + { + RED.push_back(cluster.second.availableClusterDailyPower[day]); + } + + dataToPrint.push_back(RED); + } + + std::string fileName = "/home/milos/Documents/RTEi/01-Antares/04-TestModels/" + + std::to_string(optSett.firstDay) + "-Availability.csv"; + + printColumnToFile(dataToPrint, fileName); +} + // Define the auxiliary function outside the class template void printColumnToFile(const std::vector>& data, const std::string& filename) From 58d26c656865ed67cb6bd0b4b1fe0b016dadcee6 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 29 Nov 2023 20:01:51 +0100 Subject: [PATCH 224/315] Big refactor before changing logic for number of maintenances - checked for same results- OK --- .../AuxillaryFreeFunctions.cpp | 16 ----- .../AuxillaryFreeFunctions.h | 1 - .../AuxillaryStructures.h | 25 +++++-- .../CalculateParameters.cpp | 72 ++++++++++++------- .../CreateVariables.cpp | 2 +- .../OptimizedGenerator.h | 4 +- .../PostScenarioOptimization.cpp | 30 +++++--- .../PostTimeStepOptimization.cpp | 6 +- .../PrintProblemVarRes.cpp | 2 +- 9 files changed, 99 insertions(+), 59 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.cpp b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.cpp index 42e98c406f..8a6d61072b 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.cpp @@ -141,22 +141,6 @@ int dayOfTheYear(int optimizationDay) } // calculate parameters methods - per cluster -int calculateNumberOfMaintenances(const Data::ThermalCluster& cluster, int timeHorizon) -{ - // timeHorizon cannot be 0. The whole maintenance group would be skipped if this happened - // on the other hand interPoPeriod can be 0. So we say at least 2 maintenance if this happens - // actually this cannot happen because checkMaintenanceGroupParameters() will kill it by now - if (cluster.interPoPeriod == 0) - { - logs.warning() << "Cluster: " << cluster.getFullName() - << "has interPoPeriod = 0. Number of maintenances for all units inside this " - "cluster will be set to 2"; - return minNumberOfMaintenances; - } - - return std::max(timeHorizon / cluster.interPoPeriod, minNumberOfMaintenances); // floor -} - int calculateAverageMaintenanceDuration(const Data::ThermalCluster& cluster) { double sum = 0.0; diff --git a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.h b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.h index 1a74c82a52..b4d727a8f5 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.h +++ b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.h @@ -27,7 +27,6 @@ std::array calculateAverageRenewableTsAggregated(const D std::array calculateAverageRenewableTsClusters(const Data::Area& area); // calculate parameters functions - per cluster -int calculateNumberOfMaintenances(const Data::ThermalCluster& cluster, int timeHorizon); int calculateAverageMaintenanceDuration(const Data::ThermalCluster& cluster); std::array calculateMaxUnitOutput(const Data::ThermalCluster& cluster); std::array calculateAvrUnitDailyCost(const Data::ThermalCluster& cluster); diff --git a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h index 0c826f489d..74dfec398c 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h +++ b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h @@ -90,20 +90,31 @@ struct OptimizationProblemVariables // this structure stores cluster input data (optimization parameters) // that stays the same during optimizationS // also temporary stores cluster output/results for one scenario -struct ClusterData + +struct StaticInputs { - // input data + // static input data // calculated once before all loops std::array maxPower; std::array avgCost; - std::vector daysSinceLastMaintenance; - int numberOfMaintenances; + std::vector numberOfMaintenancesFirstStep; int averageMaintenanceDuration; // for random generator double AP[366]; double BP[366]; +}; + +struct DynamicInputs +{ + // dynamic input data + // re-calculated after each optimization time-step + std::vector daysSinceLastMaintenance; + std::vector numberOfMaintenances; +}; +struct DynamicResults +{ // scenario results // temporary store scenario results // before writing them to output @@ -111,5 +122,11 @@ struct ClusterData std::vector availableClusterDailyPower; }; +struct ClusterData +{ + StaticInputs staticInputs; + DynamicInputs dynamicInputs; + DynamicResults dynamicResults; +}; } // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp index 83fa77a27c..43b291cbd6 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp @@ -151,27 +151,27 @@ void OptimizedThermalGenerator::setClusterData() if (!checkClusterExist(cluster)) continue; + // create struct maintenanceData[&cluster] = ClusterData(); - maintenanceData[&cluster].maxPower = calculateMaxUnitOutput(cluster); - maintenanceData[&cluster].avgCost = calculateAvrUnitDailyCost(cluster); - - maintenanceData[&cluster].numberOfMaintenances - = calculateNumberOfMaintenances(cluster, timeHorizon_); - maintenanceData[&cluster].averageMaintenanceDuration + // static Inputs + maintenanceData[&cluster].staticInputs.maxPower = calculateMaxUnitOutput(cluster); + maintenanceData[&cluster].staticInputs.avgCost = calculateAvrUnitDailyCost(cluster); + maintenanceData[&cluster].staticInputs.averageMaintenanceDuration = calculateAverageMaintenanceDuration(cluster); - - // since we will be updating daysSinceLastMaintenance values - // after every optimization - // lets create a copy here - this is copy by value! - maintenanceData[&cluster].daysSinceLastMaintenance - = cluster.originalRandomlyGeneratedDaysSinceLastMaintenance; - - // random generator + maintenanceData[&cluster].staticInputs.numberOfMaintenancesFirstStep + = calculateNumberOfMaintenances(cluster); + // static inputs for random generator prepareIndispoFromLaw(cluster.plannedLaw, cluster.plannedVolatility, - maintenanceData[&cluster].AP, - maintenanceData[&cluster].BP, + maintenanceData[&cluster].staticInputs.AP, + maintenanceData[&cluster].staticInputs.BP, cluster.prepro->data[Data::PreproThermal::poDuration]); + + // dynamic inputs + maintenanceData[&cluster].dynamicInputs.daysSinceLastMaintenance + = cluster.originalRandomlyGeneratedDaysSinceLastMaintenance; + maintenanceData[&cluster].dynamicInputs.numberOfMaintenances + = maintenanceData[&cluster].staticInputs.numberOfMaintenancesFirstStep; } } return; @@ -206,13 +206,13 @@ double OptimizedThermalGenerator::getPowerCost(const Data::ThermalCluster& clust return 0.; } - return maintenanceData[&cluster].avgCost[dayOfTheYear(optimizationDay)]; + return maintenanceData[&cluster].staticInputs.avgCost[dayOfTheYear(optimizationDay)]; } double OptimizedThermalGenerator::getPowerOutput(const Data::ThermalCluster& cluster, int optimizationDay) { - return maintenanceData[&cluster].maxPower[dayOfTheYear(optimizationDay)]; + return maintenanceData[&cluster].staticInputs.maxPower[dayOfTheYear(optimizationDay)]; } double OptimizedThermalGenerator::getResidualLoad(int optimizationDay) @@ -220,14 +220,15 @@ double OptimizedThermalGenerator::getResidualLoad(int optimizationDay) return residualLoadDailyValues_[dayOfTheYear(optimizationDay)]; } -int OptimizedThermalGenerator::getNumberOfMaintenances(const Data::ThermalCluster& cluster) +int OptimizedThermalGenerator::getNumberOfMaintenances(const Data::ThermalCluster& cluster, + int unit) { - return maintenanceData[&cluster].numberOfMaintenances; + return maintenanceData[&cluster].dynamicInputs.numberOfMaintenances[unit]; } int OptimizedThermalGenerator::getAverageMaintenanceDuration(const Data::ThermalCluster& cluster) { - return maintenanceData[&cluster].averageMaintenanceDuration; + return maintenanceData[&cluster].staticInputs.averageMaintenanceDuration; } int OptimizedThermalGenerator::getAverageDurationBetweenMaintenances( @@ -245,7 +246,8 @@ int OptimizedThermalGenerator::calculateUnitEarliestStartOfFirstMaintenance( // let it return negative value - if it returns negative value we wont implement constraint: // s[u][0][tauLower-1] = 0 - auto& daysSinceLastMaintenance = maintenanceData[&cluster].daysSinceLastMaintenance; + auto& daysSinceLastMaintenance + = maintenanceData[&cluster].dynamicInputs.daysSinceLastMaintenance; if (unitIndex < daysSinceLastMaintenance.size()) { @@ -263,10 +265,11 @@ int OptimizedThermalGenerator::calculateUnitLatestStartOfFirstMaintenance( const Data::ThermalCluster& cluster, uint unitIndex) { - // latest start of the first maintenance of unit u, must be positive - + // latest start of the first maintenance of unit u, must be positive - // FIRST STEP ONLY! - auto& daysSinceLastMaintenance = maintenanceData[&cluster].daysSinceLastMaintenance; + auto& daysSinceLastMaintenance + = maintenanceData[&cluster].dynamicInputs.daysSinceLastMaintenance; if (unitIndex < daysSinceLastMaintenance.size()) { @@ -291,4 +294,25 @@ int OptimizedThermalGenerator::calculateUnitLatestStartOfFirstMaintenance( } } +std::vector OptimizedThermalGenerator::calculateNumberOfMaintenances( + const Data::ThermalCluster& cluster) +{ + // if (cluster.interPoPeriod + maintenanceData[&cluster].staticInputs.averageMaintenanceDuration + // == 0) + // { + // logs.warning() << "Cluster: " << cluster.getFullName() + // << "has interPoPeriod = 0. Number of maintenances for all units inside + // this " + // "cluster will be set to 2"; + // return minNumberOfMaintenances; + // } + + std::vector numberOfMaintenances; + numberOfMaintenances.resize(cluster.unitCount); + int value = std::max(2, timeHorizon_ / cluster.interPoPeriod); + std::fill(numberOfMaintenances.begin(), numberOfMaintenances.end(), value); + + return numberOfMaintenances; +} + } // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp b/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp index 0ce8bcf5e6..0b3a19da77 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp @@ -105,7 +105,7 @@ void OptimizedThermalGenerator::buildStartEndMntVariables(const OptProblemSettin int unit, Unit& unitRef) { - int totalMntNumber = getNumberOfMaintenances(cluster); + int totalMntNumber = getNumberOfMaintenances(cluster, unit); // loop per maintenances per unit for (int mnt = 0; mnt < totalMntNumber; ++mnt) { diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 009e5d3526..3846bbfb14 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -134,6 +134,7 @@ class OptimizedThermalGenerator : public GeneratorTempData void saveScenarioResults(int fromCol, int toCol, Data::ThermalCluster& cluster); void resetResultStorage(); void reSetDaysSinceLastMnt(); + void reSetNumberOfMaintenances(); void writeTsResults(); // post-timeStep optimization methods @@ -163,7 +164,7 @@ class OptimizedThermalGenerator : public GeneratorTempData double getPowerCost(const Data::ThermalCluster& cluster, int optimizationDay); double getPowerOutput(const Data::ThermalCluster& cluster, int optimizationDay); double getResidualLoad(int optimizationDay); - int getNumberOfMaintenances(const Data::ThermalCluster& cluster); + int getNumberOfMaintenances(const Data::ThermalCluster& cluster, int unit); int getAverageMaintenanceDuration(const Data::ThermalCluster& cluster); int getAverageDurationBetweenMaintenances(const Data::ThermalCluster& cluster); @@ -172,6 +173,7 @@ class OptimizedThermalGenerator : public GeneratorTempData uint unitIndex); int calculateUnitLatestStartOfFirstMaintenance(const Data::ThermalCluster& cluster, uint unitIndex); + std::vector calculateNumberOfMaintenances(const Data::ThermalCluster& cluster); /* ===================END-CALCULATE-OPTIMIZATION-PARAMETERS=================== */ diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp index 87ada01257..0b72919588 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp @@ -19,6 +19,7 @@ void OptimizedThermalGenerator::postScenarioOptimization(OptProblemSettings& opt printAvailability(optSett); resetResultStorage(); reSetDaysSinceLastMnt(); + reSetNumberOfMaintenances(); return; } @@ -40,14 +41,14 @@ void OptimizedThermalGenerator::calculateScenarioResults() // fill in with zeros for (auto& cluster : maintenanceData) { - cluster.second.availableClusterDailyPower.resize(scenarioLength_ * DAYS_PER_YEAR); + cluster.second.dynamicResults.availableClusterDailyPower.resize(scenarioLength_ * DAYS_PER_YEAR); } // add one by one unit availability for (auto& unit : scenarioResults) { auto& availableClusterDailyPower - = maintenanceData[unit.parentCluster].availableClusterDailyPower; + = maintenanceData[unit.parentCluster].dynamicResults.availableClusterDailyPower; std::transform(availableClusterDailyPower.begin(), availableClusterDailyPower.end(), @@ -103,7 +104,7 @@ void OptimizedThermalGenerator::saveScenarioResults(int fromCol, // scenarioLength_ * DAYS_PER_YEAR element // that we need to store inside columns from-to - auto& availability = maintenanceData[&cluster].availableClusterDailyPower; + auto& availability = maintenanceData[&cluster].dynamicResults.availableClusterDailyPower; assert((toCol - fromCol) * DAYS_PER_YEAR == availability.size()); int vctCol = 0; @@ -127,7 +128,7 @@ void OptimizedThermalGenerator::resetResultStorage() for (auto& cluster : maintenanceData) { - cluster.second.availableClusterDailyPower.clear(); + cluster.second.dynamicResults.availableClusterDailyPower.clear(); } return; @@ -137,19 +138,32 @@ void OptimizedThermalGenerator::reSetDaysSinceLastMnt() { // we are back in first step, but not first scenario // we have messed up our values - // we need to re-do - // daysSinceLastMaintenance = cluster.originalRandomlyGeneratedDaysSinceLastMaintenance; - // for all areas and clusters + // we need to reset for (auto& cluster : maintenanceData) { - cluster.second.daysSinceLastMaintenance + cluster.second.dynamicInputs.daysSinceLastMaintenance = cluster.first->originalRandomlyGeneratedDaysSinceLastMaintenance; } return; } +void OptimizedThermalGenerator::reSetNumberOfMaintenances() +{ + // we are back in first step, but not first scenario + // we have messed up our values + // we need to reset + + for (auto& cluster : maintenanceData) + { + cluster.second.dynamicInputs.numberOfMaintenances + = cluster.second.staticInputs.numberOfMaintenancesFirstStep; + } + + return; +} + // this method is called at the very end // after all time-steps and scenarios void OptimizedThermalGenerator::writeTsResults() diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp index 5924044c4b..7543b55374 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp @@ -65,8 +65,8 @@ void OptimizedThermalGenerator::appendTimeStepResults(const OptProblemSettings& int PODOfTheDay = (int)cluster.prepro->data[Data::PreproThermal::poDuration][dayInTheYearStart]; - double app = maintenanceData[&cluster].AP[dayInTheYearStart]; - double bpp = maintenanceData[&cluster].BP[dayInTheYearStart]; + double app = maintenanceData[&cluster].staticInputs.AP[dayInTheYearStart]; + double bpp = maintenanceData[&cluster].staticInputs.BP[dayInTheYearStart]; int maintenanceDuration = durationGenerator( cluster.plannedLaw, PODOfTheDay, cluster.plannedVolatility, app, bpp); @@ -93,7 +93,7 @@ void OptimizedThermalGenerator::reCalculateDaysSinceLastMnt(const OptProblemSett const Unit& unit) { auto& daysSinceLastMaintenance - = maintenanceData[unit.parentCluster].daysSinceLastMaintenance[unit.index]; + = maintenanceData[unit.parentCluster].dynamicInputs.daysSinceLastMaintenance[unit.index]; bool maintenanceHappened = false; if (unit.maintenanceResults.empty()) diff --git a/src/solver/ts-generator/optimized-thermal-generator/PrintProblemVarRes.cpp b/src/solver/ts-generator/optimized-thermal-generator/PrintProblemVarRes.cpp index a387861c54..0bfc6a347f 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PrintProblemVarRes.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PrintProblemVarRes.cpp @@ -176,7 +176,7 @@ void OptimizedThermalGenerator::printAvailability(OptProblemSettings& optSett) std::vector RED; for (auto& cluster : maintenanceData) { - RED.push_back(cluster.second.availableClusterDailyPower[day]); + RED.push_back(cluster.second.dynamicResults.availableClusterDailyPower[day]); } dataToPrint.push_back(RED); From 98afa15a4344179a166990591f98b872ec810e48 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 29 Nov 2023 23:48:39 +0100 Subject: [PATCH 225/315] reminders to remove debug print --- .../optimized-thermal-generator/OptimizedGenerator.h | 6 +++--- .../PostScenarioOptimization.cpp | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 3846bbfb14..0db4dd6a77 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -164,11 +164,11 @@ class OptimizedThermalGenerator : public GeneratorTempData double getPowerCost(const Data::ThermalCluster& cluster, int optimizationDay); double getPowerOutput(const Data::ThermalCluster& cluster, int optimizationDay); double getResidualLoad(int optimizationDay); - int getNumberOfMaintenances(const Data::ThermalCluster& cluster, int unit); int getAverageMaintenanceDuration(const Data::ThermalCluster& cluster); int getAverageDurationBetweenMaintenances(const Data::ThermalCluster& cluster); - - // calculate parameters methods - per cluster-Unit + int getNumberOfMaintenances(const Data::ThermalCluster& cluster, int unit); + int getDaysSinceLastMaintenance(const Data::ThermalCluster& cluster, int unit); + // re-calculate parameters methods - per cluster-Unit int calculateUnitEarliestStartOfFirstMaintenance(const Data::ThermalCluster& cluster, uint unitIndex); int calculateUnitLatestStartOfFirstMaintenance(const Data::ThermalCluster& cluster, diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp index 0b72919588..7a620ff2d2 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp @@ -15,8 +15,8 @@ void OptimizedThermalGenerator::postScenarioOptimization(OptProblemSettings& opt calculateScenarioResults(); saveScenarioResults(optSett); - printMaintenances(optSett); - printAvailability(optSett); + printMaintenances(optSett); // to be removed + printAvailability(optSett); // to be removed resetResultStorage(); reSetDaysSinceLastMnt(); reSetNumberOfMaintenances(); From cf4c4b2999391836ac1173d98380fa31d403c857 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Wed, 29 Nov 2023 23:49:26 +0100 Subject: [PATCH 226/315] calculateNumberOfMaintenances - new approach --- .../CalculateParameters.cpp | 80 ++++++++----------- 1 file changed, 32 insertions(+), 48 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp index 43b291cbd6..a831c6c933 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp @@ -237,6 +237,12 @@ int OptimizedThermalGenerator::getAverageDurationBetweenMaintenances( return cluster.interPoPeriod; } +int OptimizedThermalGenerator::getDaysSinceLastMaintenance(const Data::ThermalCluster& cluster, + int unit) +{ + return maintenanceData[&cluster].dynamicInputs.daysSinceLastMaintenance[unit]; +} + // calculate parameters methods - per cluster-Unit int OptimizedThermalGenerator::calculateUnitEarliestStartOfFirstMaintenance( const Data::ThermalCluster& cluster, @@ -246,19 +252,8 @@ int OptimizedThermalGenerator::calculateUnitEarliestStartOfFirstMaintenance( // let it return negative value - if it returns negative value we wont implement constraint: // s[u][0][tauLower-1] = 0 - auto& daysSinceLastMaintenance - = maintenanceData[&cluster].dynamicInputs.daysSinceLastMaintenance; - - if (unitIndex < daysSinceLastMaintenance.size()) - { - return (cluster.interPoPeriod - daysSinceLastMaintenance[unitIndex] - cluster.poWindows); - } - else - { - logs.error() << "Cluster: " << cluster.getFullName() - << " does not have unit: " << unitIndex; - return 0; - } + return (getAverageDurationBetweenMaintenances(cluster) + - getDaysSinceLastMaintenance(cluster, unitIndex) - cluster.poWindows); } int OptimizedThermalGenerator::calculateUnitLatestStartOfFirstMaintenance( @@ -268,49 +263,38 @@ int OptimizedThermalGenerator::calculateUnitLatestStartOfFirstMaintenance( // latest start of the first maintenance of unit u, must be positive - // FIRST STEP ONLY! - auto& daysSinceLastMaintenance - = maintenanceData[&cluster].dynamicInputs.daysSinceLastMaintenance; - - if (unitIndex < daysSinceLastMaintenance.size()) - { - // cannot be negative: FIRST STEP ONLY - // cluster.interPoPeriod - - // cluster.originalRandomlyGeneratedDaysSinceLastMaintenance[unitIndex] - is always positive - // or zero - // cluster.poWindows is positive or zero - // however we will make sure it does not surpass timeHorizon_ - 1 value - // AFTER FIRST STEP it can go to negative value - so we will floor it to zero - - return std::min( - std::max(0, - cluster.interPoPeriod - daysSinceLastMaintenance[unitIndex] + cluster.poWindows), - timeHorizon_ - 1); - } - else - { - logs.error() << "Cluster: " << cluster.getFullName() - << " does not have unit: " << unitIndex; - return 0; - } + // cannot be negative: FIRST STEP ONLY + // cluster.interPoPeriod - + // cluster.originalRandomlyGeneratedDaysSinceLastMaintenance[unitIndex] - is always positive + // or zero + // cluster.poWindows is positive or zero + // however we will make sure it does not surpass timeHorizon_ - 1 value + // AFTER FIRST STEP it can go to negative value - so we will floor it to zero + + return std::min( + std::max(0, + getAverageDurationBetweenMaintenances(cluster) + - getDaysSinceLastMaintenance(cluster, unitIndex) + cluster.poWindows), + timeHorizon_ - 1); } std::vector OptimizedThermalGenerator::calculateNumberOfMaintenances( const Data::ThermalCluster& cluster) { - // if (cluster.interPoPeriod + maintenanceData[&cluster].staticInputs.averageMaintenanceDuration - // == 0) - // { - // logs.warning() << "Cluster: " << cluster.getFullName() - // << "has interPoPeriod = 0. Number of maintenances for all units inside - // this " - // "cluster will be set to 2"; - // return minNumberOfMaintenances; - // } + // getAverageMaintenanceDuration must be at least 1 + // so we do not need to check if div / 0 std::vector numberOfMaintenances; numberOfMaintenances.resize(cluster.unitCount); - int value = std::max(2, timeHorizon_ / cluster.interPoPeriod); - std::fill(numberOfMaintenances.begin(), numberOfMaintenances.end(), value); + + for (int unit = 0; unit != cluster.unitCount; ++unit) + { + int div = (timeHorizon_ + getDaysSinceLastMaintenance(cluster, unit) + - getAverageDurationBetweenMaintenances(cluster)) + / (getAverageDurationBetweenMaintenances(cluster) + + getAverageMaintenanceDuration(cluster)); + numberOfMaintenances[unit] = 1 + div; + } return numberOfMaintenances; } From d03c3bddfcf281343954e405425054d2ae611447 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Thu, 30 Nov 2023 00:00:12 +0100 Subject: [PATCH 227/315] reCalculateNumberOfMaintenances --- .../optimized-thermal-generator/OptimizedGenerator.h | 1 + .../PostTimeStepOptimization.cpp | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 0db4dd6a77..50b0749f10 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -147,6 +147,7 @@ class OptimizedThermalGenerator : public GeneratorTempData bool maintenanceHappened, int lastMaintenanceStart, int lastMaintenanceDuration); + void reCalculateNumberOfMaintenances(); /* ===================END-POST-OPTIMIZATION=================== */ diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp index 7543b55374..dd246e0f29 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp @@ -11,6 +11,7 @@ void OptimizedThermalGenerator::postTimeStepOptimization(OptProblemSettings& opt { appendTimeStepResults(optSett); reCalculateDaysSinceLastMnt(optSett); + reCalculateNumberOfMaintenances(); return; } @@ -131,4 +132,14 @@ int OptimizedThermalGenerator::reCalculateDaysSinceLastMnt(const OptProblemSetti + unit.parentCluster->originalRandomlyGeneratedDaysSinceLastMaintenance[unit.index]; } +void OptimizedThermalGenerator::reCalculateNumberOfMaintenances() +{ + // re-calculate days since last maintenance inputs if necessary + for (auto& cluster : maintenanceData) + { + cluster.second.dynamicInputs.numberOfMaintenances + = calculateNumberOfMaintenances(*(cluster.first)); + } +} + } // namespace Antares::Solver::TSGenerator From 26b2ddf07a02eb3775503ad8afb6bc91823387de Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Thu, 30 Nov 2023 00:33:44 +0100 Subject: [PATCH 228/315] fix order of caclulating parameters --- .../CalculateParameters.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp index a831c6c933..32eb028c54 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp @@ -153,11 +153,18 @@ void OptimizedThermalGenerator::setClusterData() // create struct maintenanceData[&cluster] = ClusterData(); + // static Inputs maintenanceData[&cluster].staticInputs.maxPower = calculateMaxUnitOutput(cluster); maintenanceData[&cluster].staticInputs.avgCost = calculateAvrUnitDailyCost(cluster); maintenanceData[&cluster].staticInputs.averageMaintenanceDuration = calculateAverageMaintenanceDuration(cluster); + + // dynamic inputs -- must calculate before number of maintenance + maintenanceData[&cluster].dynamicInputs.daysSinceLastMaintenance + = cluster.originalRandomlyGeneratedDaysSinceLastMaintenance; + + // back to static input data maintenanceData[&cluster].staticInputs.numberOfMaintenancesFirstStep = calculateNumberOfMaintenances(cluster); // static inputs for random generator @@ -167,9 +174,7 @@ void OptimizedThermalGenerator::setClusterData() maintenanceData[&cluster].staticInputs.BP, cluster.prepro->data[Data::PreproThermal::poDuration]); - // dynamic inputs - maintenanceData[&cluster].dynamicInputs.daysSinceLastMaintenance - = cluster.originalRandomlyGeneratedDaysSinceLastMaintenance; + // back to dynamic inputs maintenanceData[&cluster].dynamicInputs.numberOfMaintenances = maintenanceData[&cluster].staticInputs.numberOfMaintenancesFirstStep; } @@ -293,7 +298,7 @@ std::vector OptimizedThermalGenerator::calculateNumberOfMaintenances( - getAverageDurationBetweenMaintenances(cluster)) / (getAverageDurationBetweenMaintenances(cluster) + getAverageMaintenanceDuration(cluster)); - numberOfMaintenances[unit] = 1 + div; + numberOfMaintenances[unit] = std::max(1 + div, minNumberOfMaintenances); } return numberOfMaintenances; From da2edbe702d7d2ef48fe918056b740766da3056f Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Thu, 30 Nov 2023 01:12:25 +0100 Subject: [PATCH 229/315] todo comment --- .../optimized-thermal-generator/CalculateParameters.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp index 32eb028c54..3fceee3a1b 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp @@ -298,7 +298,7 @@ std::vector OptimizedThermalGenerator::calculateNumberOfMaintenances( - getAverageDurationBetweenMaintenances(cluster)) / (getAverageDurationBetweenMaintenances(cluster) + getAverageMaintenanceDuration(cluster)); - numberOfMaintenances[unit] = std::max(1 + div, minNumberOfMaintenances); + numberOfMaintenances[unit] = std::max(1 + div, minNumberOfMaintenances); // TODO CR27: keep here min=2 did not see it in python } return numberOfMaintenances; From 2d54b6577564e8136da6203abfc61065ecda7326 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Thu, 30 Nov 2023 01:17:59 +0100 Subject: [PATCH 230/315] re-name --- .../AuxillaryStructures.h | 2 +- .../PostScenarioOptimization.cpp | 20 +++++++++---------- .../PrintProblemVarRes.cpp | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h index 74dfec398c..037e130798 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h +++ b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h @@ -119,7 +119,7 @@ struct DynamicResults // temporary store scenario results // before writing them to output // reset after each scenario - std::vector availableClusterDailyPower; + std::vector availableDailyPower; }; struct ClusterData diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp index 7a620ff2d2..e5b119877e 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp @@ -41,19 +41,19 @@ void OptimizedThermalGenerator::calculateScenarioResults() // fill in with zeros for (auto& cluster : maintenanceData) { - cluster.second.dynamicResults.availableClusterDailyPower.resize(scenarioLength_ * DAYS_PER_YEAR); + cluster.second.dynamicResults.availableDailyPower.resize(scenarioLength_ * DAYS_PER_YEAR); } // add one by one unit availability for (auto& unit : scenarioResults) { - auto& availableClusterDailyPower - = maintenanceData[unit.parentCluster].dynamicResults.availableClusterDailyPower; + auto& availableDailyPower + = maintenanceData[unit.parentCluster].dynamicResults.availableDailyPower; - std::transform(availableClusterDailyPower.begin(), - availableClusterDailyPower.end(), + std::transform(availableDailyPower.begin(), + availableDailyPower.end(), unit.availableDailyPower.begin(), - availableClusterDailyPower.begin(), + availableDailyPower.begin(), std::plus()); } @@ -98,13 +98,13 @@ void OptimizedThermalGenerator::saveScenarioResults(int fromCol, int toCol, Data::ThermalCluster& cluster) { - // daily results are in maintenanceData.availableClusterDailyPower + // daily results are in maintenanceData.availableDailyPower // convert to hourly values and store in cluster ts - // we assume that vector availableClusterDailyPower has: + // we assume that vector availableDailyPower has: // scenarioLength_ * DAYS_PER_YEAR element // that we need to store inside columns from-to - auto& availability = maintenanceData[&cluster].dynamicResults.availableClusterDailyPower; + auto& availability = maintenanceData[&cluster].dynamicResults.availableDailyPower; assert((toCol - fromCol) * DAYS_PER_YEAR == availability.size()); int vctCol = 0; @@ -128,7 +128,7 @@ void OptimizedThermalGenerator::resetResultStorage() for (auto& cluster : maintenanceData) { - cluster.second.dynamicResults.availableClusterDailyPower.clear(); + cluster.second.dynamicResults.availableDailyPower.clear(); } return; diff --git a/src/solver/ts-generator/optimized-thermal-generator/PrintProblemVarRes.cpp b/src/solver/ts-generator/optimized-thermal-generator/PrintProblemVarRes.cpp index 0bfc6a347f..c0280f2bc8 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PrintProblemVarRes.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PrintProblemVarRes.cpp @@ -176,7 +176,7 @@ void OptimizedThermalGenerator::printAvailability(OptProblemSettings& optSett) std::vector RED; for (auto& cluster : maintenanceData) { - RED.push_back(cluster.second.dynamicResults.availableClusterDailyPower[day]); + RED.push_back(cluster.second.dynamicResults.availableDailyPower[day]); } dataToPrint.push_back(RED); From edff7fc47ecbed91b4389810fcc645e41f3ef00e Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Thu, 30 Nov 2023 10:33:49 +0100 Subject: [PATCH 231/315] refactor - wrap up optimization parameters - preparation to make timeHorizon_ non const parameter --- .../AuxillaryStructures.h | 15 +++++- .../CalculateParameters.cpp | 49 ++++++++++--------- .../CreateVariables.cpp | 12 ++--- .../OptimizedGenerator.cpp | 6 +-- .../OptimizedGenerator.h | 21 ++------ .../PostScenarioOptimization.cpp | 20 ++++---- .../PostTimeStepOptimization.cpp | 12 ++--- .../PrintProblemVarRes.cpp | 2 +- .../SetProblemConstraints.cpp | 16 +++--- .../SetProblemCost.cpp | 4 +- .../SetVariableBounds.cpp | 2 +- 11 files changed, 80 insertions(+), 79 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h index 037e130798..878915ad6a 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h +++ b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h @@ -26,7 +26,6 @@ class OptProblemSettings final bool isFirstStep = true; }; -// this structure stores the data about optimization problem variables and results struct Maintenances { // number of elements in the vector is number of days in optimization problem @@ -72,7 +71,8 @@ struct Unit void calculateAvailableDailyPower(int tsCount); }; -struct OptimizationProblemVariables +// this structure stores the data about optimization problem variables and results +struct OptimizationVariables { // number of elements in the vector is number units (areas*cluster*units) std::vector clusterUnits; @@ -129,4 +129,15 @@ struct ClusterData DynamicResults dynamicResults; }; +struct OptimizationParameters +{ + int timeHorizon_; + int timeStep_; + double ensCost_; + double spillCost_; + std::array residualLoadDailyValues_; + + std::map clusterData; +}; + } // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp index 3fceee3a1b..9963451b5f 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp @@ -13,15 +13,15 @@ void OptimizedThermalGenerator::setMaintenanceGroupParameters() // timeHorizon, timeStep ENS and Spillage are defined per one MaintenanceGroup // Residual Load (or reference value) array is defined per one MaintenanceGroup calculateResidualLoad(); - residualLoadDailyValues_ = calculateDailySums(maintenanceGroup_.getUsedResidualLoadTS()); - std::tie(ensCost_, spillCost_) = calculateMaintenanceGroupENSandSpillageCost(); - std::tie(timeStep_, timeHorizon_) = calculateTimeHorizonAndStep(); + par.residualLoadDailyValues_ = calculateDailySums(maintenanceGroup_.getUsedResidualLoadTS()); + std::tie(par.ensCost_, par.spillCost_) = calculateMaintenanceGroupENSandSpillageCost(); + std::tie(par.timeStep_, par.timeHorizon_) = calculateTimeHorizonAndStep(); setClusterData(); } bool OptimizedThermalGenerator::checkMaintenanceGroupParameters() { - if (timeStep_ == 0) + if (par.timeStep_ == 0) { logs.info() << "Maintenance group: " << maintenanceGroup_.name() << ": The timeseries generation will be skiped: timeStep = 0. It is possible " @@ -29,7 +29,7 @@ bool OptimizedThermalGenerator::checkMaintenanceGroupParameters() "planning, or at least one cluster has interPoPeriod = 0"; return false; } - if (timeHorizon_ == 0) + if (par.timeHorizon_ == 0) { logs.info() << "Maintenance group: " << maintenanceGroup_.name() @@ -152,31 +152,31 @@ void OptimizedThermalGenerator::setClusterData() continue; // create struct - maintenanceData[&cluster] = ClusterData(); + par.clusterData[&cluster] = ClusterData(); // static Inputs - maintenanceData[&cluster].staticInputs.maxPower = calculateMaxUnitOutput(cluster); - maintenanceData[&cluster].staticInputs.avgCost = calculateAvrUnitDailyCost(cluster); - maintenanceData[&cluster].staticInputs.averageMaintenanceDuration + par.clusterData[&cluster].staticInputs.maxPower = calculateMaxUnitOutput(cluster); + par.clusterData[&cluster].staticInputs.avgCost = calculateAvrUnitDailyCost(cluster); + par.clusterData[&cluster].staticInputs.averageMaintenanceDuration = calculateAverageMaintenanceDuration(cluster); // dynamic inputs -- must calculate before number of maintenance - maintenanceData[&cluster].dynamicInputs.daysSinceLastMaintenance + par.clusterData[&cluster].dynamicInputs.daysSinceLastMaintenance = cluster.originalRandomlyGeneratedDaysSinceLastMaintenance; // back to static input data - maintenanceData[&cluster].staticInputs.numberOfMaintenancesFirstStep + par.clusterData[&cluster].staticInputs.numberOfMaintenancesFirstStep = calculateNumberOfMaintenances(cluster); // static inputs for random generator prepareIndispoFromLaw(cluster.plannedLaw, cluster.plannedVolatility, - maintenanceData[&cluster].staticInputs.AP, - maintenanceData[&cluster].staticInputs.BP, + par.clusterData[&cluster].staticInputs.AP, + par.clusterData[&cluster].staticInputs.BP, cluster.prepro->data[Data::PreproThermal::poDuration]); // back to dynamic inputs - maintenanceData[&cluster].dynamicInputs.numberOfMaintenances - = maintenanceData[&cluster].staticInputs.numberOfMaintenancesFirstStep; + par.clusterData[&cluster].dynamicInputs.numberOfMaintenances + = par.clusterData[&cluster].staticInputs.numberOfMaintenancesFirstStep; } } return; @@ -211,29 +211,29 @@ double OptimizedThermalGenerator::getPowerCost(const Data::ThermalCluster& clust return 0.; } - return maintenanceData[&cluster].staticInputs.avgCost[dayOfTheYear(optimizationDay)]; + return par.clusterData[&cluster].staticInputs.avgCost[dayOfTheYear(optimizationDay)]; } double OptimizedThermalGenerator::getPowerOutput(const Data::ThermalCluster& cluster, int optimizationDay) { - return maintenanceData[&cluster].staticInputs.maxPower[dayOfTheYear(optimizationDay)]; + return par.clusterData[&cluster].staticInputs.maxPower[dayOfTheYear(optimizationDay)]; } double OptimizedThermalGenerator::getResidualLoad(int optimizationDay) { - return residualLoadDailyValues_[dayOfTheYear(optimizationDay)]; + return par.residualLoadDailyValues_[dayOfTheYear(optimizationDay)]; } int OptimizedThermalGenerator::getNumberOfMaintenances(const Data::ThermalCluster& cluster, int unit) { - return maintenanceData[&cluster].dynamicInputs.numberOfMaintenances[unit]; + return par.clusterData[&cluster].dynamicInputs.numberOfMaintenances[unit]; } int OptimizedThermalGenerator::getAverageMaintenanceDuration(const Data::ThermalCluster& cluster) { - return maintenanceData[&cluster].staticInputs.averageMaintenanceDuration; + return par.clusterData[&cluster].staticInputs.averageMaintenanceDuration; } int OptimizedThermalGenerator::getAverageDurationBetweenMaintenances( @@ -245,7 +245,7 @@ int OptimizedThermalGenerator::getAverageDurationBetweenMaintenances( int OptimizedThermalGenerator::getDaysSinceLastMaintenance(const Data::ThermalCluster& cluster, int unit) { - return maintenanceData[&cluster].dynamicInputs.daysSinceLastMaintenance[unit]; + return par.clusterData[&cluster].dynamicInputs.daysSinceLastMaintenance[unit]; } // calculate parameters methods - per cluster-Unit @@ -280,7 +280,7 @@ int OptimizedThermalGenerator::calculateUnitLatestStartOfFirstMaintenance( std::max(0, getAverageDurationBetweenMaintenances(cluster) - getDaysSinceLastMaintenance(cluster, unitIndex) + cluster.poWindows), - timeHorizon_ - 1); + par.timeHorizon_ - 1); } std::vector OptimizedThermalGenerator::calculateNumberOfMaintenances( @@ -294,11 +294,12 @@ std::vector OptimizedThermalGenerator::calculateNumberOfMaintenances( for (int unit = 0; unit != cluster.unitCount; ++unit) { - int div = (timeHorizon_ + getDaysSinceLastMaintenance(cluster, unit) + int div = (par.timeHorizon_ + getDaysSinceLastMaintenance(cluster, unit) - getAverageDurationBetweenMaintenances(cluster)) / (getAverageDurationBetweenMaintenances(cluster) + getAverageMaintenanceDuration(cluster)); - numberOfMaintenances[unit] = std::max(1 + div, minNumberOfMaintenances); // TODO CR27: keep here min=2 did not see it in python + numberOfMaintenances[unit] = std::max( + 1 + div, minNumberOfMaintenances); // TODO CR27: keep here min=2 did not see it in python } return numberOfMaintenances; diff --git a/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp b/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp index 0b3a19da77..60ffb2e014 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp @@ -15,14 +15,14 @@ void OptimizedThermalGenerator::buildProblemVariables(const OptProblemSettings& // create VARIABLES per day - ENS[t], Spill[t] void OptimizedThermalGenerator::buildEnsAndSpillageVariables(const OptProblemSettings& optSett) { - for (int day = 0; day < timeHorizon_; ++day) + for (int day = 0; day < par.timeHorizon_; ++day) { // add ENS[t] variables vars.ens.push_back(solver.MakeNumVar( 0.0, solverInfinity, "ENS_[" + std::to_string(day + optSett.firstDay) + "]")); } - for (int day = 0; day < timeHorizon_; ++day) + for (int day = 0; day < par.timeHorizon_; ++day) { // add Spillage[t] variables vars.spill.push_back(solver.MakeNumVar( @@ -36,7 +36,7 @@ void OptimizedThermalGenerator::buildEnsAndSpillageVariables(const OptProblemSet void OptimizedThermalGenerator::buildUnitPowerOutputVariables(const OptProblemSettings& optSett) { // loop per thermal clusters inside the area - for (const auto& clusterEntry : maintenanceData) + for (const auto& clusterEntry : par.clusterData) { const auto& cluster = *(clusterEntry.first); buildUnitPowerOutputVariables(optSett, cluster); @@ -75,7 +75,7 @@ void OptimizedThermalGenerator::buildUnitPowerOutputVariables(const OptProblemSe scenarioResults.push_back(vars.clusterUnits.back()); // loop per day - for (int day = 0; day < timeHorizon_; ++day) + for (int day = 0; day < par.timeHorizon_; ++day) { // add P[u][t] variables unitRef.P.push_back(solver.MakeNumVar(0.0, @@ -122,7 +122,7 @@ void OptimizedThermalGenerator::buildStartVariables(const OptProblemSettings& op int mnt) { // loop per day - for (int day = 0; day < timeHorizon_; ++day) + for (int day = 0; day < par.timeHorizon_; ++day) { // add start[u][m][t] variables unitRef.maintenances.back().start.push_back(solver.MakeIntVar( @@ -141,7 +141,7 @@ void OptimizedThermalGenerator::buildEndVariables(const OptProblemSettings& optS int mnt) { // loop per day - for (int day = 0; day < timeHorizon_; ++day) + for (int day = 0; day < par.timeHorizon_; ++day) { // add end[u][m][t] variables unitRef.maintenances.back().end.push_back(solver.MakeIntVar( diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp index 365a046a5c..1e297faa48 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp @@ -22,7 +22,7 @@ void OptimizedThermalGenerator::GenerateOptimizedThermalTimeSeries() { OptProblemSettings optSett; optSett.firstDay = 0; - optSett.lastDay = timeHorizon_; + optSett.lastDay = par.timeHorizon_; optSett.scenario = scenarioIndex; // loop till the end of scenario length @@ -33,8 +33,8 @@ void OptimizedThermalGenerator::GenerateOptimizedThermalTimeSeries() break; // Update the time values for the next iteration - optSett.firstDay += timeStep_; - optSett.lastDay += timeStep_; + optSett.firstDay += par.timeStep_; + optSett.lastDay += par.timeStep_; optSett.isFirstStep = false; } postScenarioOptimization(optSett); diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 50b0749f10..2ed70dd7c2 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -22,8 +22,7 @@ namespace Antares::Solver::TSGenerator class OptimizedThermalGenerator : public GeneratorTempData { - using MaintenanceClusterStorage = std::map; - using ScenarioResults = std::vector; + using OptimizationResults = std::vector; private: /* ===================OPTIMIZATION=================== */ @@ -185,20 +184,10 @@ class OptimizedThermalGenerator : public GeneratorTempData bool globalThermalTSgeneration_; int scenarioLength_; int scenarioNumber_; - int timeHorizon_; - int timeStep_; - double ensCost_; - double spillCost_; - std::array residualLoadDailyValues_; - /* - TODO CR27: - make MaintenanceClusterStorage and - OptimizationProblemVariables new classes - and move their methods away from here - */ - MaintenanceClusterStorage maintenanceData; - OptimizationProblemVariables vars; - ScenarioResults scenarioResults; + + OptimizationParameters par; + OptimizationVariables vars; + OptimizationResults scenarioResults; // MPSolver instance MPSolver solver; diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp index e5b119877e..82f45e66dc 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp @@ -39,7 +39,7 @@ void OptimizedThermalGenerator::calculateScenarioResults() // now lets get CLUSTER availability by summing up UNIT availability // fill in with zeros - for (auto& cluster : maintenanceData) + for (auto& cluster : par.clusterData) { cluster.second.dynamicResults.availableDailyPower.resize(scenarioLength_ * DAYS_PER_YEAR); } @@ -48,7 +48,7 @@ void OptimizedThermalGenerator::calculateScenarioResults() for (auto& unit : scenarioResults) { auto& availableDailyPower - = maintenanceData[unit.parentCluster].dynamicResults.availableDailyPower; + = par.clusterData[unit.parentCluster].dynamicResults.availableDailyPower; std::transform(availableDailyPower.begin(), availableDailyPower.end(), @@ -73,7 +73,7 @@ void OptimizedThermalGenerator::saveScenarioResults(const OptProblemSettings& op int colSaveTo = colSaveFrom + scenarioLength_; // using on purpose this double loop - // because looping through maintenanceData we cannot change cluster + // because looping through par.clusterData we cannot change cluster // const Data::ThermalCluster* for (auto& entryWeightMap : maintenanceGroup_) { @@ -98,13 +98,13 @@ void OptimizedThermalGenerator::saveScenarioResults(int fromCol, int toCol, Data::ThermalCluster& cluster) { - // daily results are in maintenanceData.availableDailyPower + // daily results are in par.clusterData.availableDailyPower // convert to hourly values and store in cluster ts // we assume that vector availableDailyPower has: // scenarioLength_ * DAYS_PER_YEAR element // that we need to store inside columns from-to - auto& availability = maintenanceData[&cluster].dynamicResults.availableDailyPower; + auto& availability = par.clusterData[&cluster].dynamicResults.availableDailyPower; assert((toCol - fromCol) * DAYS_PER_YEAR == availability.size()); int vctCol = 0; @@ -123,10 +123,10 @@ void OptimizedThermalGenerator::resetResultStorage() // clear units result structure scenarioResults.clear(); // clear cluster result structure - // do not clear whole maintenanceData + // do not clear whole par.clusterData // we store input data here as well - for (auto& cluster : maintenanceData) + for (auto& cluster : par.clusterData) { cluster.second.dynamicResults.availableDailyPower.clear(); } @@ -140,7 +140,7 @@ void OptimizedThermalGenerator::reSetDaysSinceLastMnt() // we have messed up our values // we need to reset - for (auto& cluster : maintenanceData) + for (auto& cluster : par.clusterData) { cluster.second.dynamicInputs.daysSinceLastMaintenance = cluster.first->originalRandomlyGeneratedDaysSinceLastMaintenance; @@ -155,7 +155,7 @@ void OptimizedThermalGenerator::reSetNumberOfMaintenances() // we have messed up our values // we need to reset - for (auto& cluster : maintenanceData) + for (auto& cluster : par.clusterData) { cluster.second.dynamicInputs.numberOfMaintenances = cluster.second.staticInputs.numberOfMaintenancesFirstStep; @@ -170,7 +170,7 @@ void OptimizedThermalGenerator::writeTsResults() { // we need to loop through all the clusters // and write the results - // it would be much easier to loop using maintenanceData + // it would be much easier to loop using par.clusterData // inside of it we already excluded all the non-important clusters // however it is const Data::ThermalCluster* // so we cannot modify cluster values diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp index dd246e0f29..122893d8c3 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp @@ -57,7 +57,7 @@ void OptimizedThermalGenerator::appendTimeStepResults(const OptProblemSettings& // only one maintenance can happen in the timeStep_ // TODO CR27: in phase-II we may change this and looping will be necessary { - int localMaintenanceStart = readResultUnit.maintenances[0].startDay(timeStep_); + int localMaintenanceStart = readResultUnit.maintenances[0].startDay(par.timeStep_); if (localMaintenanceStart == -1) continue; @@ -66,8 +66,8 @@ void OptimizedThermalGenerator::appendTimeStepResults(const OptProblemSettings& int PODOfTheDay = (int)cluster.prepro->data[Data::PreproThermal::poDuration][dayInTheYearStart]; - double app = maintenanceData[&cluster].staticInputs.AP[dayInTheYearStart]; - double bpp = maintenanceData[&cluster].staticInputs.BP[dayInTheYearStart]; + double app = par.clusterData[&cluster].staticInputs.AP[dayInTheYearStart]; + double bpp = par.clusterData[&cluster].staticInputs.BP[dayInTheYearStart]; int maintenanceDuration = durationGenerator( cluster.plannedLaw, PODOfTheDay, cluster.plannedVolatility, app, bpp); @@ -94,7 +94,7 @@ void OptimizedThermalGenerator::reCalculateDaysSinceLastMnt(const OptProblemSett const Unit& unit) { auto& daysSinceLastMaintenance - = maintenanceData[unit.parentCluster].dynamicInputs.daysSinceLastMaintenance[unit.index]; + = par.clusterData[unit.parentCluster].dynamicInputs.daysSinceLastMaintenance[unit.index]; bool maintenanceHappened = false; if (unit.maintenanceResults.empty()) @@ -119,7 +119,7 @@ int OptimizedThermalGenerator::reCalculateDaysSinceLastMnt(const OptProblemSetti int lastMaintenanceStart, int lastMaintenanceDuration) { - int nextOptimizationFirstDay = optSett.firstDay + timeStep_; + int nextOptimizationFirstDay = optSett.firstDay + par.timeStep_; if (maintenanceHappened) return std::max( 0, nextOptimizationFirstDay - (lastMaintenanceStart + lastMaintenanceDuration)); @@ -135,7 +135,7 @@ int OptimizedThermalGenerator::reCalculateDaysSinceLastMnt(const OptProblemSetti void OptimizedThermalGenerator::reCalculateNumberOfMaintenances() { // re-calculate days since last maintenance inputs if necessary - for (auto& cluster : maintenanceData) + for (auto& cluster : par.clusterData) { cluster.second.dynamicInputs.numberOfMaintenances = calculateNumberOfMaintenances(*(cluster.first)); diff --git a/src/solver/ts-generator/optimized-thermal-generator/PrintProblemVarRes.cpp b/src/solver/ts-generator/optimized-thermal-generator/PrintProblemVarRes.cpp index c0280f2bc8..bc4046b630 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PrintProblemVarRes.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PrintProblemVarRes.cpp @@ -174,7 +174,7 @@ void OptimizedThermalGenerator::printAvailability(OptProblemSettings& optSett) for (int day = 0; day != scenarioLength_ * 365; ++day) { std::vector RED; - for (auto& cluster : maintenanceData) + for (auto& cluster : par.clusterData) { RED.push_back(cluster.second.dynamicResults.availableDailyPower[day]); } diff --git a/src/solver/ts-generator/optimized-thermal-generator/SetProblemConstraints.cpp b/src/solver/ts-generator/optimized-thermal-generator/SetProblemConstraints.cpp index aa5dcbf70a..eabd514c41 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/SetProblemConstraints.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/SetProblemConstraints.cpp @@ -16,7 +16,7 @@ void OptimizedThermalGenerator::buildProblemConstraints(const OptProblemSettings // load balance CONSTRAINTS - constraint-per-each-day[t] - we have sum through [u] inside of it void OptimizedThermalGenerator::setLoadBalanceConstraints(const OptProblemSettings& optSett) { - for (int day = 0; day < timeHorizon_; ++day) + for (int day = 0; day < par.timeHorizon_; ++day) { setLoadBalanceConstraints(optSett, day); } @@ -78,8 +78,8 @@ void OptimizedThermalGenerator::setStartEndMntLogicConstraints(const OptProblemS // loop per maintenances per unit for (int mnt = 0; mnt < unit.maintenances.size(); ++mnt) { - assert(unit.maintenances[mnt].start.size() == timeHorizon_); - assert(unit.maintenances[mnt].end.size() == timeHorizon_); + assert(unit.maintenances[mnt].start.size() == par.timeHorizon_); + assert(unit.maintenances[mnt].end.size() == par.timeHorizon_); setEndOfMaintenanceEventBasedOnAverageDurationOfMaintenanceEvent(optSett, unit, mnt); setOnceStartIsSetToOneItWillBeOneUntilEndOfOptimizationTimeHorizon(optSett, unit, mnt); } @@ -99,7 +99,7 @@ void OptimizedThermalGenerator::setEndOfMaintenanceEventBasedOnAverageDurationOf { const auto& cluster = *(unit.parentCluster); int averageMaintenanceDuration = getAverageMaintenanceDuration(cluster); - for (int day = 0; day < timeHorizon_ - averageMaintenanceDuration; ++day) + for (int day = 0; day < par.timeHorizon_ - averageMaintenanceDuration; ++day) { std::string ctName = "E[u][q][t+Mu] = S[u][q][t] -> [" + cluster.getFullName().to() + "." @@ -121,7 +121,7 @@ void OptimizedThermalGenerator:: { const auto& cluster = *(unit.parentCluster); int averageDurationBetweenMaintenances = getAverageDurationBetweenMaintenances(cluster); - for (int day = 0; day < timeHorizon_ - averageDurationBetweenMaintenances; ++day) + for (int day = 0; day < par.timeHorizon_ - averageDurationBetweenMaintenances; ++day) { std::string ctName = "S[u][q+1][t+Tu] = E[u][q][t] -> [" + cluster.getFullName().to() + "." @@ -142,7 +142,7 @@ void OptimizedThermalGenerator::setOnceStartIsSetToOneItWillBeOneUntilEndOfOptim int mnt) { const auto& cluster = *(unit.parentCluster); - for (int day = 0; day < timeHorizon_ - 1; ++day) + for (int day = 0; day < par.timeHorizon_ - 1; ++day) { std::string ctName = "S[u][q][t+1] >= S[u][q][t] -> [" + cluster.getFullName().to() + "." @@ -162,7 +162,7 @@ void OptimizedThermalGenerator::setNextMaintenanceCanNotStartBeforePreviousMaint int mnt) { const auto& cluster = *(unit.parentCluster); - for (int day = 0; day < timeHorizon_; ++day) + for (int day = 0; day < par.timeHorizon_; ++day) { std::string ctName = "S[u][q][t] >= S[u][q+1][t] -> [" + cluster.getFullName().to() + "." @@ -180,7 +180,7 @@ void OptimizedThermalGenerator::setNextMaintenanceCanNotStartBeforePreviousMaint // CONSTRAINTS per days and per units - constraint-per-each-day+unit[t][u][m-sum per m] void OptimizedThermalGenerator::setMaxUnitOutputConstraints(const OptProblemSettings& optSett) { - for (int day = 0; day < timeHorizon_; ++day) + for (int day = 0; day < par.timeHorizon_; ++day) { setMaxUnitOutputConstraints(optSett, day); } diff --git a/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp b/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp index 942adbd698..c96a5ec7b3 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp @@ -26,7 +26,7 @@ void OptimizedThermalGenerator::setProblemEnsCost(MPObjective* objective) // loop per day for (const auto& ens : vars.ens) { - objective->SetCoefficient(ens, ensCost_); + objective->SetCoefficient(ens, par.ensCost_); } return; } @@ -36,7 +36,7 @@ void OptimizedThermalGenerator::setProblemSpillCost(MPObjective* objective) // loop per day for (const auto& spill : vars.spill) { - objective->SetCoefficient(spill, spillCost_); + objective->SetCoefficient(spill, par.spillCost_); } return; } diff --git a/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp b/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp index 1f2faac1de..a44d29edb2 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp @@ -78,7 +78,7 @@ void OptimizedThermalGenerator::fixBounds(const Unit& unit, int averageMaintenan // start[u][q][T] = 1 void OptimizedThermalGenerator::fixBoundsStartSecondMnt(const Unit& unit, int mnt) { - unit.maintenances[mnt].start[timeHorizon_ - 1]->SetBounds(1.0, 1.0); + unit.maintenances[mnt].start[par.timeHorizon_ - 1]->SetBounds(1.0, 1.0); } // End of the maintenance can't happen before average maintenance duration From 926f762f2fadae8320e16404f97e29719136f270 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Thu, 30 Nov 2023 12:59:50 +0100 Subject: [PATCH 232/315] timeHorizon - is changing - initial calculation --- .../CalculateParameters.cpp | 273 +++++++++++------- .../OptimizedGenerator.h | 11 +- 2 files changed, 173 insertions(+), 111 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp index 9963451b5f..61ec62275f 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp @@ -7,94 +7,55 @@ namespace Antares::Solver::TSGenerator { -// calculate parameters methods - per maintenance group -void OptimizedThermalGenerator::setMaintenanceGroupParameters() -{ - // timeHorizon, timeStep ENS and Spillage are defined per one MaintenanceGroup - // Residual Load (or reference value) array is defined per one MaintenanceGroup - calculateResidualLoad(); - par.residualLoadDailyValues_ = calculateDailySums(maintenanceGroup_.getUsedResidualLoadTS()); - std::tie(par.ensCost_, par.spillCost_) = calculateMaintenanceGroupENSandSpillageCost(); - std::tie(par.timeStep_, par.timeHorizon_) = calculateTimeHorizonAndStep(); - setClusterData(); -} - -bool OptimizedThermalGenerator::checkMaintenanceGroupParameters() -{ - if (par.timeStep_ == 0) - { - logs.info() << "Maintenance group: " << maintenanceGroup_.name() - << ": The timeseries generation will be skiped: timeStep = 0. It is possible " - "that the maintenance group has no clusters designated for maintenance " - "planning, or at least one cluster has interPoPeriod = 0"; - return false; - } - if (par.timeHorizon_ == 0) - { - logs.info() - << "Maintenance group: " << maintenanceGroup_.name() - << ": The timeseries generation will be skiped: timeHorizon = 0. It is possible " - "that the maintenance group has no clusters designated for maintenance " - "planning, or all clusters have interPoPeriod = 0"; - return false; - } - // add some more check here if necessary! - return true; -} - -std::pair OptimizedThermalGenerator::calculateTimeHorizonAndStep() +// methods are ordered in the line of execution order +void OptimizedThermalGenerator::allocateClusterData() { - std::vector averageDurationBetweenMaintenances = {}; + // loop all areas in maintenance group for (const auto& entryWeightMap : maintenanceGroup_) { const auto& area = *(entryWeightMap.first); + // loop all thermal clusters inside the area for (const auto& clusterEntry : area.thermal.list.mapping) { const auto& cluster = *(clusterEntry.second); - if (checkClusterExist(cluster) && cluster.doWeGenerateTS(globalThermalTSgeneration_) - && cluster.optimizeMaintenance) - { - averageDurationBetweenMaintenances.push_back(cluster.interPoPeriod); - } - } - } - - // Using std::minmax_element to find min and max - auto [minIter, maxIter] = std::minmax_element(averageDurationBetweenMaintenances.begin(), - averageDurationBetweenMaintenances.end()); + if (!checkClusterExist(cluster)) + continue; - // Check if the vector is not empty - if (minIter != averageDurationBetweenMaintenances.end() - && maxIter != averageDurationBetweenMaintenances.end()) - { - return std::make_pair(*minIter, 2 * (*maxIter)); + // create struct + par.clusterData[&cluster] = ClusterData(); + } } - - return std::make_pair(0, 0); } -std::pair OptimizedThermalGenerator::calculateMaintenanceGroupENSandSpillageCost() +void OptimizedThermalGenerator::calculateNonDependantClusterData() { - std::vector ensVector = {}; - std::vector spillageVector = {}; - for (const auto& entryWeightMap : maintenanceGroup_) - { - const auto& area = *(entryWeightMap.first); - ensVector.push_back(area.thermal.unsuppliedEnergyCost); - spillageVector.push_back(area.thermal.spilledEnergyCost); - } - - // Using std::minmax_element to find min and max - auto ens = std::min_element(ensVector.begin(), ensVector.end()); - auto spill = std::min_element(spillageVector.begin(), spillageVector.end()); - - // Check if the vector is not empty - if (ens != ensVector.end() && spill != spillageVector.end()) + for (auto& clusterEntry : par.clusterData) { - return std::make_pair(*ens, *spill); + auto& data = clusterEntry.second; + const auto& cluster = *(clusterEntry.first); + + // static Inputs + // this inputs wont be changed during optimization problem + // and are important to calculate immediately + // cause their values are used for calculating other parameters + data.staticInputs.maxPower = calculateMaxUnitOutput(cluster); + data.staticInputs.avgCost = calculateAvrUnitDailyCost(cluster); + data.staticInputs.averageMaintenanceDuration = calculateAverageMaintenanceDuration(cluster); + // static inputs for random generator + prepareIndispoFromLaw(cluster.plannedLaw, + cluster.plannedVolatility, + data.staticInputs.AP, + data.staticInputs.BP, + cluster.prepro->data[Data::PreproThermal::poDuration]); + + // dynamic input + // this input will be updated during optimization steps + // and then re-sett + // important to initialize it immediately + // cause it is used for later parameter calculation + data.dynamicInputs.daysSinceLastMaintenance + = cluster.originalRandomlyGeneratedDaysSinceLastMaintenance; } - - return std::make_pair(0, 0); } void OptimizedThermalGenerator::calculateResidualLoad() @@ -136,52 +97,150 @@ void OptimizedThermalGenerator::calculateResidualLoad() maintenanceGroup_.setUsedResidualLoadTS(refValue); } -void OptimizedThermalGenerator::setClusterData() +std::pair OptimizedThermalGenerator::calculateMaintenanceGroupENSandSpillageCost() { + std::vector ensVector = {}; + std::vector spillageVector = {}; for (const auto& entryWeightMap : maintenanceGroup_) { const auto& area = *(entryWeightMap.first); - // loop per thermal clusters inside the area - fill in the structure - for (const auto& clusterEntry : area.thermal.list.mapping) + ensVector.push_back(area.thermal.unsuppliedEnergyCost); + spillageVector.push_back(area.thermal.spilledEnergyCost); + } + + // Using std::minmax_element to find min and max + auto ens = std::min_element(ensVector.begin(), ensVector.end()); + auto spill = std::min_element(spillageVector.begin(), spillageVector.end()); + + // Check if the vector is not empty + if (ens != ensVector.end() && spill != spillageVector.end()) + { + return std::make_pair(*ens, *spill); + } + + return std::make_pair(0, 0); +} + +int OptimizedThermalGenerator::calculateTimeStep() +{ + std::vector averageDurationBetweenMaintenances = {}; + for (const auto& clusterEntry : par.clusterData) + { + const auto& cluster = *(clusterEntry.first); + if (cluster.doWeGenerateTS(globalThermalTSgeneration_) && cluster.optimizeMaintenance) { - const auto& cluster = *(clusterEntry.second); + averageDurationBetweenMaintenances.push_back(cluster.interPoPeriod); + } + } - // we do not check if cluster.optimizeMaintenance = true here - // we add all the clusters Power inside maintenance group - if (!checkClusterExist(cluster)) - continue; + auto minIter = std::min_element(averageDurationBetweenMaintenances.begin(), + averageDurationBetweenMaintenances.end()); - // create struct - par.clusterData[&cluster] = ClusterData(); + // Check if the vector is not empty + if (minIter != averageDurationBetweenMaintenances.end()) + { + return *minIter; + } + + return 0; +} - // static Inputs - par.clusterData[&cluster].staticInputs.maxPower = calculateMaxUnitOutput(cluster); - par.clusterData[&cluster].staticInputs.avgCost = calculateAvrUnitDailyCost(cluster); - par.clusterData[&cluster].staticInputs.averageMaintenanceDuration - = calculateAverageMaintenanceDuration(cluster); - - // dynamic inputs -- must calculate before number of maintenance - par.clusterData[&cluster].dynamicInputs.daysSinceLastMaintenance - = cluster.originalRandomlyGeneratedDaysSinceLastMaintenance; - - // back to static input data - par.clusterData[&cluster].staticInputs.numberOfMaintenancesFirstStep - = calculateNumberOfMaintenances(cluster); - // static inputs for random generator - prepareIndispoFromLaw(cluster.plannedLaw, - cluster.plannedVolatility, - par.clusterData[&cluster].staticInputs.AP, - par.clusterData[&cluster].staticInputs.BP, - cluster.prepro->data[Data::PreproThermal::poDuration]); - - // back to dynamic inputs - par.clusterData[&cluster].dynamicInputs.numberOfMaintenances - = par.clusterData[&cluster].staticInputs.numberOfMaintenancesFirstStep; +int OptimizedThermalGenerator::calculateTimeHorizon() +{ + std::vector timeHorizonVector = {}; + for (const auto& clusterEntry : par.clusterData) + { + const auto& cluster = *(clusterEntry.first); + if (!(cluster.doWeGenerateTS(globalThermalTSgeneration_) && cluster.optimizeMaintenance)) + continue; + for (int unit = 0; unit < cluster.unitCount; ++unit) + { + int value = 2 * getAverageDurationBetweenMaintenances(cluster) + + getAverageMaintenanceDuration(cluster) + - getDaysSinceLastMaintenance(cluster, unit); + timeHorizonVector.push_back(value); } } + + auto maxIter = std::max_element(timeHorizonVector.begin(), timeHorizonVector.end()); + + // Check if the vector is not empty + if (maxIter != timeHorizonVector.end()) + { + return *maxIter; + } + + return 0; +} + +// calculate parameters methods +void OptimizedThermalGenerator::setMaintenanceGroupParameters() +{ + // it is crucial that we allocateClusterData + // and calculate NonDependantClusterData + // since later methods expect this to be filled + // and values available + allocateClusterData(); + calculateNonDependantClusterData(); + // + calculateResidualLoad(); + par.residualLoadDailyValues_ = calculateDailySums(maintenanceGroup_.getUsedResidualLoadTS()); + std::tie(par.ensCost_, par.spillCost_) = calculateMaintenanceGroupENSandSpillageCost(); + par.timeStep_ = calculateTimeStep(); + par.timeHorizon_ = calculateTimeHorizon(); + // calculateDependantClusterData + // uses timeHorizon_ so it is important we calculate timeHorizon_ first + calculateDependantClusterData(); +} + +void OptimizedThermalGenerator::calculateDependantClusterData() +{ + for (auto& clusterEntry : par.clusterData) + { + auto& data = clusterEntry.second; + const auto& cluster = *(clusterEntry.first); + + /* + calculateNumberOfMaintenances uses: + averageMaintenanceDuration + DaysSinceLastMaintenance + timeHorizon + averageDurationBetweenMaintenances - cluster.interPoPeriod - this is static always available + so all these parameters need to be calculated before calling this method + */ + + // static input - wont be changed - used to reset dynamicInputs.numberOfMaintenances + // after each scenario + data.staticInputs.numberOfMaintenancesFirstStep = calculateNumberOfMaintenances(cluster); + // dynamic inputs + data.dynamicInputs.numberOfMaintenances = data.staticInputs.numberOfMaintenancesFirstStep; + } return; } +bool OptimizedThermalGenerator::checkMaintenanceGroupParameters() +{ + if (par.timeStep_ == 0) + { + logs.info() << "Maintenance group: " << maintenanceGroup_.name() + << ": The timeseries generation will be skiped: timeStep = 0. It is possible " + "that the maintenance group has no clusters designated for maintenance " + "planning, or at least one cluster has interPoPeriod = 0"; + return false; + } + if (par.timeHorizon_ == 0) + { + logs.info() + << "Maintenance group: " << maintenanceGroup_.name() + << ": The timeseries generation will be skiped: timeHorizon = 0. It is possible " + "that the maintenance group has no clusters designated for maintenance " + "planning, or all clusters have interPoPeriod = 0"; + return false; + } + // add some more check here if necessary! + return true; +} + // Getters double OptimizedThermalGenerator::getPowerCost(const Data::ThermalCluster& cluster, int optimizationDay) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index 2ed70dd7c2..c8402956bd 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -153,12 +153,15 @@ class OptimizedThermalGenerator : public GeneratorTempData /* ===================CALCULATE-OPTIMIZATION-PARAMETERS=================== */ // Calculate parameters methods - per maintenance group + void allocateClusterData(); + void calculateNonDependantClusterData(); + void calculateResidualLoad(); + std::pair calculateMaintenanceGroupENSandSpillageCost(); + int calculateTimeStep(); + int calculateTimeHorizon(); + void calculateDependantClusterData(); void setMaintenanceGroupParameters(); bool checkMaintenanceGroupParameters(); - std::pair calculateTimeHorizonAndStep(); - std::pair calculateMaintenanceGroupENSandSpillageCost(); - void calculateResidualLoad(); - void setClusterData(); // getters double getPowerCost(const Data::ThermalCluster& cluster, int optimizationDay); From c16ac0b52e84e784f23c2bf0db07920c381341d8 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Thu, 30 Nov 2023 13:11:23 +0100 Subject: [PATCH 233/315] reCalculateTimeHorizon --- .../optimized-thermal-generator/OptimizedGenerator.h | 1 + .../PostTimeStepOptimization.cpp | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index c8402956bd..f97f285bf1 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -146,6 +146,7 @@ class OptimizedThermalGenerator : public GeneratorTempData bool maintenanceHappened, int lastMaintenanceStart, int lastMaintenanceDuration); + void reCalculateTimeHorizon(); void reCalculateNumberOfMaintenances(); /* ===================END-POST-OPTIMIZATION=================== */ diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp index 122893d8c3..dd6986fbe0 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp @@ -11,6 +11,7 @@ void OptimizedThermalGenerator::postTimeStepOptimization(OptProblemSettings& opt { appendTimeStepResults(optSett); reCalculateDaysSinceLastMnt(optSett); + reCalculateTimeHorizon(); reCalculateNumberOfMaintenances(); return; } @@ -132,6 +133,11 @@ int OptimizedThermalGenerator::reCalculateDaysSinceLastMnt(const OptProblemSetti + unit.parentCluster->originalRandomlyGeneratedDaysSinceLastMaintenance[unit.index]; } +void OptimizedThermalGenerator::reCalculateTimeHorizon() +{ + par.timeHorizon_ = calculateTimeHorizon(); +} + void OptimizedThermalGenerator::reCalculateNumberOfMaintenances() { // re-calculate days since last maintenance inputs if necessary From 6d9ad469ec6b13117ae9cefb9fcd3762dcaf6da0 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Thu, 30 Nov 2023 13:36:03 +0100 Subject: [PATCH 234/315] reSetTimeHorizon --- .../CalculateParameters.cpp | 1 + .../optimized-thermal-generator/OptimizedGenerator.h | 1 + .../PostScenarioOptimization.cpp | 11 +++++++++++ 3 files changed, 13 insertions(+) diff --git a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp index 61ec62275f..609232307c 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp @@ -188,6 +188,7 @@ void OptimizedThermalGenerator::setMaintenanceGroupParameters() std::tie(par.ensCost_, par.spillCost_) = calculateMaintenanceGroupENSandSpillageCost(); par.timeStep_ = calculateTimeStep(); par.timeHorizon_ = calculateTimeHorizon(); + par.timeHorizonFirstStep_ = par.timeHorizon_; // calculateDependantClusterData // uses timeHorizon_ so it is important we calculate timeHorizon_ first calculateDependantClusterData(); diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h index f97f285bf1..c57a98a6ae 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h @@ -134,6 +134,7 @@ class OptimizedThermalGenerator : public GeneratorTempData void resetResultStorage(); void reSetDaysSinceLastMnt(); void reSetNumberOfMaintenances(); + void reSetTimeHorizon(); void writeTsResults(); // post-timeStep optimization methods diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp index 82f45e66dc..b2177e8a6b 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp @@ -19,6 +19,7 @@ void OptimizedThermalGenerator::postScenarioOptimization(OptProblemSettings& opt printAvailability(optSett); // to be removed resetResultStorage(); reSetDaysSinceLastMnt(); + reSetTimeHorizon(); reSetNumberOfMaintenances(); return; @@ -149,6 +150,16 @@ void OptimizedThermalGenerator::reSetDaysSinceLastMnt() return; } +void OptimizedThermalGenerator::reSetTimeHorizon() +{ + // we are back in first step, but not first scenario + // we have messed up our values + // we need to reset + + par.timeHorizon_ = par.timeHorizonFirstStep_; + return; +} + void OptimizedThermalGenerator::reSetNumberOfMaintenances() { // we are back in first step, but not first scenario From a68e6a2463b3dd68a152b8a6607adda7fec544d8 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Thu, 30 Nov 2023 13:36:50 +0100 Subject: [PATCH 235/315] timeHorizon is dynamic now - calculate last day differently --- .../optimized-thermal-generator/AuxillaryStructures.h | 1 + .../optimized-thermal-generator/OptimizedGenerator.cpp | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h index 878915ad6a..e0cf5b7e35 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h +++ b/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h @@ -132,6 +132,7 @@ struct ClusterData struct OptimizationParameters { int timeHorizon_; + int timeHorizonFirstStep_; int timeStep_; double ensCost_; double spillCost_; diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp index 1e297faa48..09b7aa3630 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp @@ -22,7 +22,7 @@ void OptimizedThermalGenerator::GenerateOptimizedThermalTimeSeries() { OptProblemSettings optSett; optSett.firstDay = 0; - optSett.lastDay = par.timeHorizon_; + optSett.lastDay = optSett.firstDay + par.timeHorizon_; optSett.scenario = scenarioIndex; // loop till the end of scenario length @@ -34,7 +34,7 @@ void OptimizedThermalGenerator::GenerateOptimizedThermalTimeSeries() // Update the time values for the next iteration optSett.firstDay += par.timeStep_; - optSett.lastDay += par.timeStep_; + optSett.lastDay = optSett.firstDay + par.timeHorizon_; optSett.isFirstStep = false; } postScenarioOptimization(optSett); From 14be2aa2ec1292d6a0601e1b02c6e5da0988187d Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Thu, 30 Nov 2023 14:59:16 +0100 Subject: [PATCH 236/315] refactor --- .../CalculateParameters.cpp | 43 +++++++++---------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp index 609232307c..457d361acc 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp @@ -173,27 +173,6 @@ int OptimizedThermalGenerator::calculateTimeHorizon() return 0; } -// calculate parameters methods -void OptimizedThermalGenerator::setMaintenanceGroupParameters() -{ - // it is crucial that we allocateClusterData - // and calculate NonDependantClusterData - // since later methods expect this to be filled - // and values available - allocateClusterData(); - calculateNonDependantClusterData(); - // - calculateResidualLoad(); - par.residualLoadDailyValues_ = calculateDailySums(maintenanceGroup_.getUsedResidualLoadTS()); - std::tie(par.ensCost_, par.spillCost_) = calculateMaintenanceGroupENSandSpillageCost(); - par.timeStep_ = calculateTimeStep(); - par.timeHorizon_ = calculateTimeHorizon(); - par.timeHorizonFirstStep_ = par.timeHorizon_; - // calculateDependantClusterData - // uses timeHorizon_ so it is important we calculate timeHorizon_ first - calculateDependantClusterData(); -} - void OptimizedThermalGenerator::calculateDependantClusterData() { for (auto& clusterEntry : par.clusterData) @@ -219,6 +198,26 @@ void OptimizedThermalGenerator::calculateDependantClusterData() return; } +void OptimizedThermalGenerator::setMaintenanceGroupParameters() +{ + // it is crucial that we allocateClusterData + // and calculate NonDependantClusterData + // since later methods expect this to be filled + // and values available + allocateClusterData(); + calculateNonDependantClusterData(); + // + calculateResidualLoad(); + par.residualLoadDailyValues_ = calculateDailySums(maintenanceGroup_.getUsedResidualLoadTS()); + std::tie(par.ensCost_, par.spillCost_) = calculateMaintenanceGroupENSandSpillageCost(); + par.timeStep_ = calculateTimeStep(); + par.timeHorizon_ = calculateTimeHorizon(); + par.timeHorizonFirstStep_ = par.timeHorizon_; + // calculateDependantClusterData + // uses timeHorizon_ so it is important we calculate timeHorizon_ first + calculateDependantClusterData(); +} + bool OptimizedThermalGenerator::checkMaintenanceGroupParameters() { if (par.timeStep_ == 0) @@ -308,7 +307,7 @@ int OptimizedThermalGenerator::getDaysSinceLastMaintenance(const Data::ThermalCl return par.clusterData[&cluster].dynamicInputs.daysSinceLastMaintenance[unit]; } -// calculate parameters methods - per cluster-Unit +// calculate parameters methods - per cluster-Unit or just Cluster int OptimizedThermalGenerator::calculateUnitEarliestStartOfFirstMaintenance( const Data::ThermalCluster& cluster, uint unitIndex) From 55ad39d8c106ce005db6628653bd706c0fe45aa0 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Thu, 30 Nov 2023 15:24:43 +0100 Subject: [PATCH 237/315] refactor - pack into sub-folders --- src/solver/simulation/solver.hxx | 2 +- src/solver/ts-generator/CMakeLists.txt | 38 +++--- .../{ => Aux}/AuxillaryFreeFunctions.cpp | 4 +- .../{ => Aux}/AuxillaryFreeFunctions.h | 2 +- .../{ => Aux}/AuxillaryStructures.cpp | 0 .../{ => Aux}/AuxillaryStructures.h | 0 .../{ => Aux}/pre-scenario-builder.cpp | 4 +- .../{ => Aux}/pre-scenario-builder.h | 0 .../{ => Main}/OptimizedGenerator.cpp | 0 .../{ => Main}/OptimizedGenerator.h | 8 +- .../{ => Optimization}/CreateVariables.cpp | 2 +- .../{ => Optimization}/PrintProblemVarRes.cpp | 2 +- .../{ => Optimization}/ResetProblem.cpp | 2 +- .../SetProblemConstraints.cpp | 2 +- .../{ => Optimization}/SetProblemCost.cpp | 2 +- .../{ => Optimization}/SetVariableBounds.cpp | 2 +- .../{ => Optimization}/SolveProbem.cpp | 2 +- .../{ => Parameters}/CalculateParameters.cpp | 125 +----------------- .../CalculateParametersPerCluster.cpp | 66 +++++++++ .../Parameters/Getters.cpp | 75 +++++++++++ .../PostScenarioOptimization.cpp | 2 +- .../PostTimeStepOptimization.cpp | 2 +- src/solver/ts-generator/thermal.cpp | 2 +- 23 files changed, 182 insertions(+), 162 deletions(-) rename src/solver/ts-generator/optimized-thermal-generator/{ => Aux}/AuxillaryFreeFunctions.cpp (98%) rename src/solver/ts-generator/optimized-thermal-generator/{ => Aux}/AuxillaryFreeFunctions.h (97%) rename src/solver/ts-generator/optimized-thermal-generator/{ => Aux}/AuxillaryStructures.cpp (100%) rename src/solver/ts-generator/optimized-thermal-generator/{ => Aux}/AuxillaryStructures.h (100%) rename src/solver/ts-generator/optimized-thermal-generator/{ => Aux}/pre-scenario-builder.cpp (88%) rename src/solver/ts-generator/optimized-thermal-generator/{ => Aux}/pre-scenario-builder.h (100%) rename src/solver/ts-generator/optimized-thermal-generator/{ => Main}/OptimizedGenerator.cpp (100%) rename src/solver/ts-generator/optimized-thermal-generator/{ => Main}/OptimizedGenerator.h (97%) rename src/solver/ts-generator/optimized-thermal-generator/{ => Optimization}/CreateVariables.cpp (99%) rename src/solver/ts-generator/optimized-thermal-generator/{ => Optimization}/PrintProblemVarRes.cpp (99%) rename src/solver/ts-generator/optimized-thermal-generator/{ => Optimization}/ResetProblem.cpp (89%) rename src/solver/ts-generator/optimized-thermal-generator/{ => Optimization}/SetProblemConstraints.cpp (99%) rename src/solver/ts-generator/optimized-thermal-generator/{ => Optimization}/SetProblemCost.cpp (97%) rename src/solver/ts-generator/optimized-thermal-generator/{ => Optimization}/SetVariableBounds.cpp (98%) rename src/solver/ts-generator/optimized-thermal-generator/{ => Optimization}/SolveProbem.cpp (96%) rename src/solver/ts-generator/optimized-thermal-generator/{ => Parameters}/CalculateParameters.cpp (64%) create mode 100644 src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParametersPerCluster.cpp create mode 100644 src/solver/ts-generator/optimized-thermal-generator/Parameters/Getters.cpp rename src/solver/ts-generator/optimized-thermal-generator/{ => PostOptimization}/PostScenarioOptimization.cpp (99%) rename src/solver/ts-generator/optimized-thermal-generator/{ => PostOptimization}/PostTimeStepOptimization.cpp (99%) diff --git a/src/solver/simulation/solver.hxx b/src/solver/simulation/solver.hxx index ffb37b1871..41c72debc8 100644 --- a/src/solver/simulation/solver.hxx +++ b/src/solver/simulation/solver.hxx @@ -40,7 +40,7 @@ #include "../ts-generator/generator.h" #include "opt_time_writer.h" #include "../hydro/management.h" // Added for use of randomReservoirLevel(...) -#include "../ts-generator/optimized-thermal-generator/pre-scenario-builder.h" +#include "../ts-generator/optimized-thermal-generator/Aux/pre-scenario-builder.h" #include #include diff --git a/src/solver/ts-generator/CMakeLists.txt b/src/solver/ts-generator/CMakeLists.txt index 4795656f26..c6ad0f6483 100644 --- a/src/solver/ts-generator/CMakeLists.txt +++ b/src/solver/ts-generator/CMakeLists.txt @@ -13,24 +13,26 @@ source_group("ts-generator\\randomized-thermal-generator" FILES ${SRC_RANDOMIZED # Optimized-thermal-ts-generator # set(SRC_OPTIMIZEDGENERATORS - optimized-thermal-generator/AuxillaryStructures.h - optimized-thermal-generator/AuxillaryStructures.cpp - optimized-thermal-generator/AuxillaryFreeFunctions.h - optimized-thermal-generator/AuxillaryFreeFunctions.cpp - optimized-thermal-generator/pre-scenario-builder.h - optimized-thermal-generator/pre-scenario-builder.cpp - optimized-thermal-generator/OptimizedGenerator.h - optimized-thermal-generator/OptimizedGenerator.cpp - optimized-thermal-generator/CalculateParameters.cpp - optimized-thermal-generator/CreateVariables.cpp - optimized-thermal-generator/SetVariableBounds.cpp - optimized-thermal-generator/SetProblemConstraints.cpp - optimized-thermal-generator/SetProblemCost.cpp - optimized-thermal-generator/ResetProblem.cpp - optimized-thermal-generator/SolveProbem.cpp - optimized-thermal-generator/PrintProblemVarRes.cpp - optimized-thermal-generator/PostTimeStepOptimization.cpp - optimized-thermal-generator/PostScenarioOptimization.cpp + optimized-thermal-generator/Aux/AuxillaryStructures.h + optimized-thermal-generator/Aux/AuxillaryStructures.cpp + optimized-thermal-generator/Aux/AuxillaryFreeFunctions.h + optimized-thermal-generator/Aux/AuxillaryFreeFunctions.cpp + optimized-thermal-generator/Aux/pre-scenario-builder.h + optimized-thermal-generator/Aux/pre-scenario-builder.cpp + optimized-thermal-generator/Main/OptimizedGenerator.h + optimized-thermal-generator/Main/OptimizedGenerator.cpp + optimized-thermal-generator/Parameters/CalculateParameters.cpp + optimized-thermal-generator/Parameters/CalculateParametersPerCluster.cpp + optimized-thermal-generator/Parameters/Getters.cpp + optimized-thermal-generator/Optimization/CreateVariables.cpp + optimized-thermal-generator/Optimization/SetVariableBounds.cpp + optimized-thermal-generator/Optimization/SetProblemConstraints.cpp + optimized-thermal-generator/Optimization/SetProblemCost.cpp + optimized-thermal-generator/Optimization/ResetProblem.cpp + optimized-thermal-generator/Optimization/SolveProbem.cpp + optimized-thermal-generator/Optimization/PrintProblemVarRes.cpp + optimized-thermal-generator/PostOptimization/PostTimeStepOptimization.cpp + optimized-thermal-generator/PostOptimization/PostScenarioOptimization.cpp ) source_group("ts-generator\\optimized-thermal-generator" FILES ${SRC_OPTIMIZEDGENERATORS}) diff --git a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.cpp b/src/solver/ts-generator/optimized-thermal-generator/Aux/AuxillaryFreeFunctions.cpp similarity index 98% rename from src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.cpp rename to src/solver/ts-generator/optimized-thermal-generator/Aux/AuxillaryFreeFunctions.cpp index 8a6d61072b..48eb9c3009 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/Aux/AuxillaryFreeFunctions.cpp @@ -4,8 +4,8 @@ #include #include #include -#include "OptimizedGenerator.h" -#include "AuxillaryFreeFunctions.h" +#include "../Main/OptimizedGenerator.h" +#include "../Aux/AuxillaryFreeFunctions.h" namespace Antares::Solver::TSGenerator { diff --git a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.h b/src/solver/ts-generator/optimized-thermal-generator/Aux/AuxillaryFreeFunctions.h similarity index 97% rename from src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.h rename to src/solver/ts-generator/optimized-thermal-generator/Aux/AuxillaryFreeFunctions.h index b4d727a8f5..eb09bd0180 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryFreeFunctions.h +++ b/src/solver/ts-generator/optimized-thermal-generator/Aux/AuxillaryFreeFunctions.h @@ -4,7 +4,7 @@ #pragma once -#include "OptimizedGenerator.h" +#include "../Main/OptimizedGenerator.h" namespace Antares::Solver::TSGenerator { diff --git a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.cpp b/src/solver/ts-generator/optimized-thermal-generator/Aux/AuxillaryStructures.cpp similarity index 100% rename from src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.cpp rename to src/solver/ts-generator/optimized-thermal-generator/Aux/AuxillaryStructures.cpp diff --git a/src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h b/src/solver/ts-generator/optimized-thermal-generator/Aux/AuxillaryStructures.h similarity index 100% rename from src/solver/ts-generator/optimized-thermal-generator/AuxillaryStructures.h rename to src/solver/ts-generator/optimized-thermal-generator/Aux/AuxillaryStructures.h diff --git a/src/solver/ts-generator/optimized-thermal-generator/pre-scenario-builder.cpp b/src/solver/ts-generator/optimized-thermal-generator/Aux/pre-scenario-builder.cpp similarity index 88% rename from src/solver/ts-generator/optimized-thermal-generator/pre-scenario-builder.cpp rename to src/solver/ts-generator/optimized-thermal-generator/Aux/pre-scenario-builder.cpp index afa1345bb8..f1f1cdef4d 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/pre-scenario-builder.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/Aux/pre-scenario-builder.cpp @@ -4,8 +4,8 @@ #include #include "pre-scenario-builder.h" -#include "../../simulation/apply-scenario.h" -#include "../../simulation/timeseries-numbers.h" +#include "../../../simulation/apply-scenario.h" +#include "../../../simulation/timeseries-numbers.h" namespace Antares::Solver { diff --git a/src/solver/ts-generator/optimized-thermal-generator/pre-scenario-builder.h b/src/solver/ts-generator/optimized-thermal-generator/Aux/pre-scenario-builder.h similarity index 100% rename from src/solver/ts-generator/optimized-thermal-generator/pre-scenario-builder.h rename to src/solver/ts-generator/optimized-thermal-generator/Aux/pre-scenario-builder.h diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.cpp similarity index 100% rename from src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.cpp rename to src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.cpp diff --git a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.h similarity index 97% rename from src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h rename to src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.h index c57a98a6ae..d67dd56ad9 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.h @@ -5,10 +5,10 @@ #pragma once #include "ortools/linear_solver/linear_solver.h" -#include "../randomized-thermal-generator/RandomizedGenerator.h" -#include "../../../libs/antares/study/maintenance_planning/MaintenanceGroup.h" -#include "AuxillaryStructures.h" -#include "AuxillaryFreeFunctions.h" +#include "../../randomized-thermal-generator/RandomizedGenerator.h" +#include "../../../../libs/antares/study/maintenance_planning/MaintenanceGroup.h" +#include "../Aux/AuxillaryStructures.h" +#include "../Aux/AuxillaryFreeFunctions.h" #include // static const std::string mntPlSolverName = "cbc"; diff --git a/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp b/src/solver/ts-generator/optimized-thermal-generator/Optimization/CreateVariables.cpp similarity index 99% rename from src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp rename to src/solver/ts-generator/optimized-thermal-generator/Optimization/CreateVariables.cpp index 60ffb2e014..56f15d6669 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CreateVariables.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/Optimization/CreateVariables.cpp @@ -2,7 +2,7 @@ // Created by milos on 14/11/23. // -#include "OptimizedGenerator.h" +#include "../Main/OptimizedGenerator.h" namespace Antares::Solver::TSGenerator { diff --git a/src/solver/ts-generator/optimized-thermal-generator/PrintProblemVarRes.cpp b/src/solver/ts-generator/optimized-thermal-generator/Optimization/PrintProblemVarRes.cpp similarity index 99% rename from src/solver/ts-generator/optimized-thermal-generator/PrintProblemVarRes.cpp rename to src/solver/ts-generator/optimized-thermal-generator/Optimization/PrintProblemVarRes.cpp index bc4046b630..03a1f87112 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PrintProblemVarRes.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/Optimization/PrintProblemVarRes.cpp @@ -8,7 +8,7 @@ #include #include -#include "OptimizedGenerator.h" +#include "../Main/OptimizedGenerator.h" namespace Antares::Solver::TSGenerator { diff --git a/src/solver/ts-generator/optimized-thermal-generator/ResetProblem.cpp b/src/solver/ts-generator/optimized-thermal-generator/Optimization/ResetProblem.cpp similarity index 89% rename from src/solver/ts-generator/optimized-thermal-generator/ResetProblem.cpp rename to src/solver/ts-generator/optimized-thermal-generator/Optimization/ResetProblem.cpp index 9815acb01e..2e71b8c2aa 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/ResetProblem.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/Optimization/ResetProblem.cpp @@ -2,7 +2,7 @@ // Created by milos on 14/11/23. // -#include "OptimizedGenerator.h" +#include "../Main/OptimizedGenerator.h" namespace Antares::Solver::TSGenerator { diff --git a/src/solver/ts-generator/optimized-thermal-generator/SetProblemConstraints.cpp b/src/solver/ts-generator/optimized-thermal-generator/Optimization/SetProblemConstraints.cpp similarity index 99% rename from src/solver/ts-generator/optimized-thermal-generator/SetProblemConstraints.cpp rename to src/solver/ts-generator/optimized-thermal-generator/Optimization/SetProblemConstraints.cpp index eabd514c41..a6e123aace 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/SetProblemConstraints.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/Optimization/SetProblemConstraints.cpp @@ -2,7 +2,7 @@ // Created by milos on 14/11/23. // -#include "OptimizedGenerator.h" +#include "../Main/OptimizedGenerator.h" namespace Antares::Solver::TSGenerator { diff --git a/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp b/src/solver/ts-generator/optimized-thermal-generator/Optimization/SetProblemCost.cpp similarity index 97% rename from src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp rename to src/solver/ts-generator/optimized-thermal-generator/Optimization/SetProblemCost.cpp index c96a5ec7b3..6c7f3af35b 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/SetProblemCost.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/Optimization/SetProblemCost.cpp @@ -2,7 +2,7 @@ // Created by milos on 14/11/23. // -#include "OptimizedGenerator.h" +#include "../Main/OptimizedGenerator.h" namespace Antares::Solver::TSGenerator { diff --git a/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp b/src/solver/ts-generator/optimized-thermal-generator/Optimization/SetVariableBounds.cpp similarity index 98% rename from src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp rename to src/solver/ts-generator/optimized-thermal-generator/Optimization/SetVariableBounds.cpp index a44d29edb2..89c673292d 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/SetVariableBounds.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/Optimization/SetVariableBounds.cpp @@ -2,7 +2,7 @@ // Created by milos on 14/11/23. // -#include "OptimizedGenerator.h" +#include "../Main/OptimizedGenerator.h" namespace Antares::Solver::TSGenerator { diff --git a/src/solver/ts-generator/optimized-thermal-generator/SolveProbem.cpp b/src/solver/ts-generator/optimized-thermal-generator/Optimization/SolveProbem.cpp similarity index 96% rename from src/solver/ts-generator/optimized-thermal-generator/SolveProbem.cpp rename to src/solver/ts-generator/optimized-thermal-generator/Optimization/SolveProbem.cpp index 78c6afa07f..a82d2c7c05 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/SolveProbem.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/Optimization/SolveProbem.cpp @@ -2,7 +2,7 @@ // Created by milos on 14/11/23. // -#include "OptimizedGenerator.h" +#include "../Main/OptimizedGenerator.h" namespace Antares::Solver::TSGenerator { diff --git a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp b/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParameters.cpp similarity index 64% rename from src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp rename to src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParameters.cpp index 457d361acc..ecfdd43c5e 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/CalculateParameters.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParameters.cpp @@ -2,7 +2,7 @@ // Created by milos on 14/11/23. // -#include "OptimizedGenerator.h" +#include "../Main/OptimizedGenerator.h" namespace Antares::Solver::TSGenerator { @@ -241,127 +241,4 @@ bool OptimizedThermalGenerator::checkMaintenanceGroupParameters() return true; } -// Getters -double OptimizedThermalGenerator::getPowerCost(const Data::ThermalCluster& cluster, - int optimizationDay) -{ - /* - ** Unit cost can be directly set, - ** Or calculated using Fuel Cost, Co2 cost, Fuel Eff and V&O Cost. - - ** In second case we also need information which year it is (to choose proper TS number, and - also what hour it is) - ** we need price per day (so averaging the hourly values) - ** this is NOT calculated prior to the simulation - so if we only want to run ts-gen, we cannot - get this info just yet - ** using: - ** getMarginalCost(uint serieIndex, uint hourInTheYear) or - ** getMarketBidCost(uint hourInTheYear, uint year) - ** TODO CR27: maybe for phase-II - ** for now just disable this option but take into account the thermalModulationCost!! - */ - - if (cluster.costgeneration == Data::useCostTimeseries) - { - logs.warning() - << "Cluster: " << cluster.getFullName() - << " has Cost generation set to: Use cost timeseries. Option not suported yet. " - "Cost set to zero."; - return 0.; - } - - return par.clusterData[&cluster].staticInputs.avgCost[dayOfTheYear(optimizationDay)]; -} - -double OptimizedThermalGenerator::getPowerOutput(const Data::ThermalCluster& cluster, - int optimizationDay) -{ - return par.clusterData[&cluster].staticInputs.maxPower[dayOfTheYear(optimizationDay)]; -} - -double OptimizedThermalGenerator::getResidualLoad(int optimizationDay) -{ - return par.residualLoadDailyValues_[dayOfTheYear(optimizationDay)]; -} - -int OptimizedThermalGenerator::getNumberOfMaintenances(const Data::ThermalCluster& cluster, - int unit) -{ - return par.clusterData[&cluster].dynamicInputs.numberOfMaintenances[unit]; -} - -int OptimizedThermalGenerator::getAverageMaintenanceDuration(const Data::ThermalCluster& cluster) -{ - return par.clusterData[&cluster].staticInputs.averageMaintenanceDuration; -} - -int OptimizedThermalGenerator::getAverageDurationBetweenMaintenances( - const Data::ThermalCluster& cluster) -{ - return cluster.interPoPeriod; -} - -int OptimizedThermalGenerator::getDaysSinceLastMaintenance(const Data::ThermalCluster& cluster, - int unit) -{ - return par.clusterData[&cluster].dynamicInputs.daysSinceLastMaintenance[unit]; -} - -// calculate parameters methods - per cluster-Unit or just Cluster -int OptimizedThermalGenerator::calculateUnitEarliestStartOfFirstMaintenance( - const Data::ThermalCluster& cluster, - uint unitIndex) -{ - // earliest start of the first maintenance of unit u (beginning of the window, can be negative): - // let it return negative value - if it returns negative value we wont implement constraint: - // s[u][0][tauLower-1] = 0 - - return (getAverageDurationBetweenMaintenances(cluster) - - getDaysSinceLastMaintenance(cluster, unitIndex) - cluster.poWindows); -} - -int OptimizedThermalGenerator::calculateUnitLatestStartOfFirstMaintenance( - const Data::ThermalCluster& cluster, - uint unitIndex) -{ - // latest start of the first maintenance of unit u, must be positive - - // FIRST STEP ONLY! - - // cannot be negative: FIRST STEP ONLY - // cluster.interPoPeriod - - // cluster.originalRandomlyGeneratedDaysSinceLastMaintenance[unitIndex] - is always positive - // or zero - // cluster.poWindows is positive or zero - // however we will make sure it does not surpass timeHorizon_ - 1 value - // AFTER FIRST STEP it can go to negative value - so we will floor it to zero - - return std::min( - std::max(0, - getAverageDurationBetweenMaintenances(cluster) - - getDaysSinceLastMaintenance(cluster, unitIndex) + cluster.poWindows), - par.timeHorizon_ - 1); -} - -std::vector OptimizedThermalGenerator::calculateNumberOfMaintenances( - const Data::ThermalCluster& cluster) -{ - // getAverageMaintenanceDuration must be at least 1 - // so we do not need to check if div / 0 - - std::vector numberOfMaintenances; - numberOfMaintenances.resize(cluster.unitCount); - - for (int unit = 0; unit != cluster.unitCount; ++unit) - { - int div = (par.timeHorizon_ + getDaysSinceLastMaintenance(cluster, unit) - - getAverageDurationBetweenMaintenances(cluster)) - / (getAverageDurationBetweenMaintenances(cluster) - + getAverageMaintenanceDuration(cluster)); - numberOfMaintenances[unit] = std::max( - 1 + div, minNumberOfMaintenances); // TODO CR27: keep here min=2 did not see it in python - } - - return numberOfMaintenances; -} - } // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParametersPerCluster.cpp b/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParametersPerCluster.cpp new file mode 100644 index 0000000000..bf583d7192 --- /dev/null +++ b/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParametersPerCluster.cpp @@ -0,0 +1,66 @@ +// +// Created by milos on 14/11/23. +// + +#include "../Main/OptimizedGenerator.h" + +namespace Antares::Solver::TSGenerator +{ + +int OptimizedThermalGenerator::calculateUnitEarliestStartOfFirstMaintenance( + const Data::ThermalCluster& cluster, + uint unitIndex) +{ + // earliest start of the first maintenance of unit u (beginning of the window, can be negative): + // let it return negative value - if it returns negative value we wont implement constraint: + // s[u][0][tauLower-1] = 0 + + return (getAverageDurationBetweenMaintenances(cluster) + - getDaysSinceLastMaintenance(cluster, unitIndex) - cluster.poWindows); +} + +int OptimizedThermalGenerator::calculateUnitLatestStartOfFirstMaintenance( + const Data::ThermalCluster& cluster, + uint unitIndex) +{ + // latest start of the first maintenance of unit u, must be positive - + // FIRST STEP ONLY! + + // cannot be negative: FIRST STEP ONLY + // cluster.interPoPeriod - + // cluster.originalRandomlyGeneratedDaysSinceLastMaintenance[unitIndex] - is always positive + // or zero + // cluster.poWindows is positive or zero + // however we will make sure it does not surpass timeHorizon_ - 1 value + // AFTER FIRST STEP it can go to negative value - so we will floor it to zero + + return std::min( + std::max(0, + getAverageDurationBetweenMaintenances(cluster) + - getDaysSinceLastMaintenance(cluster, unitIndex) + cluster.poWindows), + par.timeHorizon_ - 1); +} + +std::vector OptimizedThermalGenerator::calculateNumberOfMaintenances( + const Data::ThermalCluster& cluster) +{ + // getAverageMaintenanceDuration must be at least 1 + // so we do not need to check if div / 0 + + std::vector numberOfMaintenances; + numberOfMaintenances.resize(cluster.unitCount); + + for (int unit = 0; unit != cluster.unitCount; ++unit) + { + int div = (par.timeHorizon_ + getDaysSinceLastMaintenance(cluster, unit) + - getAverageDurationBetweenMaintenances(cluster)) + / (getAverageDurationBetweenMaintenances(cluster) + + getAverageMaintenanceDuration(cluster)); + numberOfMaintenances[unit] = std::max( + 1 + div, minNumberOfMaintenances); // TODO CR27: keep here min=2 did not see it in python + } + + return numberOfMaintenances; +} + +} // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/Parameters/Getters.cpp b/src/solver/ts-generator/optimized-thermal-generator/Parameters/Getters.cpp new file mode 100644 index 0000000000..4f4d2d2698 --- /dev/null +++ b/src/solver/ts-generator/optimized-thermal-generator/Parameters/Getters.cpp @@ -0,0 +1,75 @@ +// +// Created by milos on 14/11/23. +// + +#include "../Main/OptimizedGenerator.h" + +namespace Antares::Solver::TSGenerator +{ +// Getters +double OptimizedThermalGenerator::getPowerCost(const Data::ThermalCluster& cluster, + int optimizationDay) +{ + /* + ** Unit cost can be directly set, + ** Or calculated using Fuel Cost, Co2 cost, Fuel Eff and V&O Cost. + + ** In second case we also need information which year it is (to choose proper TS number, and + also what hour it is) + ** we need price per day (so averaging the hourly values) + ** this is NOT calculated prior to the simulation - so if we only want to run ts-gen, we cannot + get this info just yet + ** using: + ** getMarginalCost(uint serieIndex, uint hourInTheYear) or + ** getMarketBidCost(uint hourInTheYear, uint year) + ** TODO CR27: maybe for phase-II + ** for now just disable this option but take into account the thermalModulationCost!! + */ + + if (cluster.costgeneration == Data::useCostTimeseries) + { + logs.warning() + << "Cluster: " << cluster.getFullName() + << " has Cost generation set to: Use cost timeseries. Option not suported yet. " + "Cost set to zero."; + return 0.; + } + + return par.clusterData[&cluster].staticInputs.avgCost[dayOfTheYear(optimizationDay)]; +} + +double OptimizedThermalGenerator::getPowerOutput(const Data::ThermalCluster& cluster, + int optimizationDay) +{ + return par.clusterData[&cluster].staticInputs.maxPower[dayOfTheYear(optimizationDay)]; +} + +double OptimizedThermalGenerator::getResidualLoad(int optimizationDay) +{ + return par.residualLoadDailyValues_[dayOfTheYear(optimizationDay)]; +} + +int OptimizedThermalGenerator::getNumberOfMaintenances(const Data::ThermalCluster& cluster, + int unit) +{ + return par.clusterData[&cluster].dynamicInputs.numberOfMaintenances[unit]; +} + +int OptimizedThermalGenerator::getAverageMaintenanceDuration(const Data::ThermalCluster& cluster) +{ + return par.clusterData[&cluster].staticInputs.averageMaintenanceDuration; +} + +int OptimizedThermalGenerator::getAverageDurationBetweenMaintenances( + const Data::ThermalCluster& cluster) +{ + return cluster.interPoPeriod; +} + +int OptimizedThermalGenerator::getDaysSinceLastMaintenance(const Data::ThermalCluster& cluster, + int unit) +{ + return par.clusterData[&cluster].dynamicInputs.daysSinceLastMaintenance[unit]; +} + +} // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostScenarioOptimization.cpp similarity index 99% rename from src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp rename to src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostScenarioOptimization.cpp index b2177e8a6b..be474275aa 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostScenarioOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostScenarioOptimization.cpp @@ -2,7 +2,7 @@ // Created by milos on 14/11/23. // -#include "OptimizedGenerator.h" +#include "../Main/OptimizedGenerator.h" namespace Antares::Solver::TSGenerator { diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostTimeStepOptimization.cpp similarity index 99% rename from src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp rename to src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostTimeStepOptimization.cpp index dd6986fbe0..8604f294ff 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostTimeStepOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostTimeStepOptimization.cpp @@ -2,7 +2,7 @@ // Created by milos on 14/11/23. // -#include "OptimizedGenerator.h" +#include "../Main/OptimizedGenerator.h" namespace Antares::Solver::TSGenerator { diff --git a/src/solver/ts-generator/thermal.cpp b/src/solver/ts-generator/thermal.cpp index 8259d8e77e..413b3d62c1 100644 --- a/src/solver/ts-generator/thermal.cpp +++ b/src/solver/ts-generator/thermal.cpp @@ -27,7 +27,7 @@ #include "../simulation/sim_extern_variables_globales.h" #include "randomized-thermal-generator/RandomizedGenerator.h" -#include "optimized-thermal-generator/OptimizedGenerator.h" +#include "optimized-thermal-generator/Main/OptimizedGenerator.h" namespace Antares::Solver::TSGenerator { From 9c37f189ad9cb424ea062e11b321bd145084d1fd Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Fri, 1 Dec 2023 01:21:42 +0100 Subject: [PATCH 238/315] move parameters into class --- src/solver/ts-generator/CMakeLists.txt | 1 + .../Aux/AuxillaryStructures.h | 59 --------- .../Main/OptimizedGenerator.cpp | 4 +- .../Main/OptimizedGenerator.h | 32 +---- .../Optimization/CreateVariables.cpp | 2 +- .../Optimization/SetProblemConstraints.cpp | 8 +- .../Optimization/SetProblemCost.cpp | 2 +- .../Optimization/SetVariableBounds.cpp | 6 +- .../Parameters/CalculateParameters.cpp | 44 +++---- .../CalculateParametersPerCluster.cpp | 10 +- .../Parameters/Getters.cpp | 33 +++-- .../Parameters/OptimizationParameters.h | 117 ++++++++++++++++++ .../PostTimeStepOptimization.cpp | 4 +- .../RandomizedGenerator.h | 1 + 14 files changed, 178 insertions(+), 145 deletions(-) create mode 100644 src/solver/ts-generator/optimized-thermal-generator/Parameters/OptimizationParameters.h diff --git a/src/solver/ts-generator/CMakeLists.txt b/src/solver/ts-generator/CMakeLists.txt index c6ad0f6483..8f745b797c 100644 --- a/src/solver/ts-generator/CMakeLists.txt +++ b/src/solver/ts-generator/CMakeLists.txt @@ -21,6 +21,7 @@ set(SRC_OPTIMIZEDGENERATORS optimized-thermal-generator/Aux/pre-scenario-builder.cpp optimized-thermal-generator/Main/OptimizedGenerator.h optimized-thermal-generator/Main/OptimizedGenerator.cpp + optimized-thermal-generator/Parameters/OptimizationParameters.h optimized-thermal-generator/Parameters/CalculateParameters.cpp optimized-thermal-generator/Parameters/CalculateParametersPerCluster.cpp optimized-thermal-generator/Parameters/Getters.cpp diff --git a/src/solver/ts-generator/optimized-thermal-generator/Aux/AuxillaryStructures.h b/src/solver/ts-generator/optimized-thermal-generator/Aux/AuxillaryStructures.h index e0cf5b7e35..e190dffc19 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Aux/AuxillaryStructures.h +++ b/src/solver/ts-generator/optimized-thermal-generator/Aux/AuxillaryStructures.h @@ -82,63 +82,4 @@ struct OptimizationVariables std::vector spill; // pointers to Spill[t] variables }; -// it is better to immediately calculate and populate structure -// that will store information about clusters -// so inside optimization problem we just retrieve these data with getters -// not re-calculate them over and over again - -// this structure stores cluster input data (optimization parameters) -// that stays the same during optimizationS -// also temporary stores cluster output/results for one scenario - -struct StaticInputs -{ - // static input data - // calculated once before all loops - std::array maxPower; - std::array avgCost; - std::vector numberOfMaintenancesFirstStep; - int averageMaintenanceDuration; - - // for random generator - double AP[366]; - double BP[366]; -}; - -struct DynamicInputs -{ - // dynamic input data - // re-calculated after each optimization time-step - std::vector daysSinceLastMaintenance; - std::vector numberOfMaintenances; -}; - -struct DynamicResults -{ - // scenario results - // temporary store scenario results - // before writing them to output - // reset after each scenario - std::vector availableDailyPower; -}; - -struct ClusterData -{ - StaticInputs staticInputs; - DynamicInputs dynamicInputs; - DynamicResults dynamicResults; -}; - -struct OptimizationParameters -{ - int timeHorizon_; - int timeHorizonFirstStep_; - int timeStep_; - double ensCost_; - double spillCost_; - std::array residualLoadDailyValues_; - - std::map clusterData; -}; - } // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.cpp index 09b7aa3630..cf1e989fa9 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.cpp @@ -13,8 +13,8 @@ namespace Antares::Solver::TSGenerator void OptimizedThermalGenerator::GenerateOptimizedThermalTimeSeries() { allocateWhereToWriteTs(); - setMaintenanceGroupParameters(); - if (!checkMaintenanceGroupParameters()) + par.setMaintenanceGroupParameters(); + if (!par.checkMaintenanceGroupParameters()) return; // loop through all scenarios diff --git a/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.h index d67dd56ad9..101688334d 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.h @@ -9,6 +9,7 @@ #include "../../../../libs/antares/study/maintenance_planning/MaintenanceGroup.h" #include "../Aux/AuxillaryStructures.h" #include "../Aux/AuxillaryFreeFunctions.h" +#include "../Parameters/OptimizationParameters.h" #include // static const std::string mntPlSolverName = "cbc"; @@ -152,35 +153,7 @@ class OptimizedThermalGenerator : public GeneratorTempData /* ===================END-POST-OPTIMIZATION=================== */ - /* ===================CALCULATE-OPTIMIZATION-PARAMETERS=================== */ - - // Calculate parameters methods - per maintenance group - void allocateClusterData(); - void calculateNonDependantClusterData(); - void calculateResidualLoad(); - std::pair calculateMaintenanceGroupENSandSpillageCost(); - int calculateTimeStep(); - int calculateTimeHorizon(); - void calculateDependantClusterData(); - void setMaintenanceGroupParameters(); - bool checkMaintenanceGroupParameters(); - - // getters - double getPowerCost(const Data::ThermalCluster& cluster, int optimizationDay); - double getPowerOutput(const Data::ThermalCluster& cluster, int optimizationDay); - double getResidualLoad(int optimizationDay); - int getAverageMaintenanceDuration(const Data::ThermalCluster& cluster); - int getAverageDurationBetweenMaintenances(const Data::ThermalCluster& cluster); - int getNumberOfMaintenances(const Data::ThermalCluster& cluster, int unit); - int getDaysSinceLastMaintenance(const Data::ThermalCluster& cluster, int unit); - // re-calculate parameters methods - per cluster-Unit - int calculateUnitEarliestStartOfFirstMaintenance(const Data::ThermalCluster& cluster, - uint unitIndex); - int calculateUnitLatestStartOfFirstMaintenance(const Data::ThermalCluster& cluster, - uint unitIndex); - std::vector calculateNumberOfMaintenances(const Data::ThermalCluster& cluster); - - /* ===================END-CALCULATE-OPTIMIZATION-PARAMETERS=================== */ + /* ===================CLASS-VARIABLES=================== */ @@ -209,6 +182,7 @@ class OptimizedThermalGenerator : public GeneratorTempData IResultWriter& writer) : GeneratorTempData(study, progr, writer), maintenanceGroup_(maintenanceGroup), + par(study, maintenanceGroup, globalThermalTSgeneration, progr, writer), solver(MPSolver("MaintenancePlanning", MPSolver::CBC_MIXED_INTEGER_PROGRAMMING)) { currentYear = year; diff --git a/src/solver/ts-generator/optimized-thermal-generator/Optimization/CreateVariables.cpp b/src/solver/ts-generator/optimized-thermal-generator/Optimization/CreateVariables.cpp index 56f15d6669..6620dcce34 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Optimization/CreateVariables.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/Optimization/CreateVariables.cpp @@ -105,7 +105,7 @@ void OptimizedThermalGenerator::buildStartEndMntVariables(const OptProblemSettin int unit, Unit& unitRef) { - int totalMntNumber = getNumberOfMaintenances(cluster, unit); + int totalMntNumber = par.getNumberOfMaintenances(cluster, unit); // loop per maintenances per unit for (int mnt = 0; mnt < totalMntNumber; ++mnt) { diff --git a/src/solver/ts-generator/optimized-thermal-generator/Optimization/SetProblemConstraints.cpp b/src/solver/ts-generator/optimized-thermal-generator/Optimization/SetProblemConstraints.cpp index a6e123aace..3e9bcb6a89 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Optimization/SetProblemConstraints.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/Optimization/SetProblemConstraints.cpp @@ -28,7 +28,7 @@ void OptimizedThermalGenerator::setLoadBalanceConstraints(const OptProblemSettin { int optimizationDay = day + optSett.firstDay; std::string ctName = "LoadBalanceConstraint[" + std::to_string(optimizationDay) + "]"; - double residualLoad = getResidualLoad(optimizationDay); + double residualLoad = par.getResidualLoad(optimizationDay); MPConstraint* ct = solver.MakeRowConstraint(residualLoad, residualLoad, ctName); insertPowerVars(ct, day); @@ -98,7 +98,7 @@ void OptimizedThermalGenerator::setEndOfMaintenanceEventBasedOnAverageDurationOf int mnt) { const auto& cluster = *(unit.parentCluster); - int averageMaintenanceDuration = getAverageMaintenanceDuration(cluster); + int averageMaintenanceDuration = par.getAverageMaintenanceDuration(cluster); for (int day = 0; day < par.timeHorizon_ - averageMaintenanceDuration; ++day) { std::string ctName = "E[u][q][t+Mu] = S[u][q][t] -> [" @@ -120,7 +120,7 @@ void OptimizedThermalGenerator:: int mnt) { const auto& cluster = *(unit.parentCluster); - int averageDurationBetweenMaintenances = getAverageDurationBetweenMaintenances(cluster); + int averageDurationBetweenMaintenances = par.getAverageDurationBetweenMaintenances(cluster); for (int day = 0; day < par.timeHorizon_ - averageDurationBetweenMaintenances; ++day) { std::string ctName = "S[u][q+1][t+Tu] = E[u][q][t] -> [" @@ -202,7 +202,7 @@ void OptimizedThermalGenerator::setMaxUnitOutputConstraints(const OptProblemSett { const auto& cluster = *(unit.parentCluster); int optimizationDay = day + optSett.firstDay; - double maxPower = getPowerOutput(cluster, optimizationDay); + double maxPower = par.getPowerOutput(cluster, optimizationDay); std::string ctName = "MaxPowerOutputConstraint[" + cluster.getFullName().to() + "." + std::to_string(unit.index) + "][" + std::to_string(optimizationDay) diff --git a/src/solver/ts-generator/optimized-thermal-generator/Optimization/SetProblemCost.cpp b/src/solver/ts-generator/optimized-thermal-generator/Optimization/SetProblemCost.cpp index 6c7f3af35b..12c3b15f65 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Optimization/SetProblemCost.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/Optimization/SetProblemCost.cpp @@ -59,7 +59,7 @@ void OptimizedThermalGenerator::setProblemPowerCost(const OptProblemSettings& op // loop per day for (int day = 0; day < unit.P.size(); ++day) { - double unitPowerCost = getPowerCost(*(unit.parentCluster), day + optSett.firstDay); + double unitPowerCost = par.getPowerCost(*(unit.parentCluster), day + optSett.firstDay); objective->SetCoefficient(unit.P[day], unitPowerCost); } diff --git a/src/solver/ts-generator/optimized-thermal-generator/Optimization/SetVariableBounds.cpp b/src/solver/ts-generator/optimized-thermal-generator/Optimization/SetVariableBounds.cpp index 89c673292d..9f5a6253cf 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Optimization/SetVariableBounds.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/Optimization/SetVariableBounds.cpp @@ -27,7 +27,7 @@ void OptimizedThermalGenerator::fixBounds(const Unit& unit) if (!unit.createStartEndVariables) return; - int averageMaintenanceDuration = getAverageMaintenanceDuration(*(unit.parentCluster)); + int averageMaintenanceDuration = par.getAverageMaintenanceDuration(*(unit.parentCluster)); fixBoundsFirstMnt(unit); fixBounds(unit, averageMaintenanceDuration); @@ -40,9 +40,9 @@ void OptimizedThermalGenerator::fixBounds(const Unit& unit) void OptimizedThermalGenerator::fixBoundsFirstMnt(const Unit& unit) { int earliestStartOfFirstMaintenance - = calculateUnitEarliestStartOfFirstMaintenance(*(unit.parentCluster), unit.index); + = par.calculateUnitEarliestStartOfFirstMaintenance(*(unit.parentCluster), unit.index); int latestStartOfFirstMaintenance - = calculateUnitLatestStartOfFirstMaintenance(*(unit.parentCluster), unit.index); + = par.calculateUnitLatestStartOfFirstMaintenance(*(unit.parentCluster), unit.index); // // We assume here that vector "maintenance" has member [0] diff --git a/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParameters.cpp b/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParameters.cpp index ecfdd43c5e..a0f58aa7f5 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParameters.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParameters.cpp @@ -8,7 +8,7 @@ namespace Antares::Solver::TSGenerator { // methods are ordered in the line of execution order -void OptimizedThermalGenerator::allocateClusterData() +void OptimizationParameters::allocateClusterData() { // loop all areas in maintenance group for (const auto& entryWeightMap : maintenanceGroup_) @@ -22,14 +22,14 @@ void OptimizedThermalGenerator::allocateClusterData() continue; // create struct - par.clusterData[&cluster] = ClusterData(); + clusterData[&cluster] = ClusterData(); } } } -void OptimizedThermalGenerator::calculateNonDependantClusterData() +void OptimizationParameters::calculateNonDependantClusterData() { - for (auto& clusterEntry : par.clusterData) + for (auto& clusterEntry : clusterData) { auto& data = clusterEntry.second; const auto& cluster = *(clusterEntry.first); @@ -58,7 +58,7 @@ void OptimizedThermalGenerator::calculateNonDependantClusterData() } } -void OptimizedThermalGenerator::calculateResidualLoad() +void OptimizationParameters::calculateResidualLoad() { // create reference value arrays std::array refValueLoad = {}; @@ -81,7 +81,7 @@ void OptimizedThermalGenerator::calculateResidualLoad() auto tmpLoad = calculateAverageLoadTs(area); auto tmpRor = calculateAverageRorTs(area); - auto tmpRenewable = calculateAverageRenewableTs(study.parameters.renewableGeneration, area); + auto tmpRenewable = calculateAverageRenewableTs(modelingType_, area); for (std::size_t row = 0; row < HOURS_PER_YEAR; ++row) { @@ -97,7 +97,7 @@ void OptimizedThermalGenerator::calculateResidualLoad() maintenanceGroup_.setUsedResidualLoadTS(refValue); } -std::pair OptimizedThermalGenerator::calculateMaintenanceGroupENSandSpillageCost() +std::pair OptimizationParameters::calculateMaintenanceGroupENSandSpillageCost() { std::vector ensVector = {}; std::vector spillageVector = {}; @@ -121,10 +121,10 @@ std::pair OptimizedThermalGenerator::calculateMaintenanceGroupEN return std::make_pair(0, 0); } -int OptimizedThermalGenerator::calculateTimeStep() +int OptimizationParameters::calculateTimeStep() { std::vector averageDurationBetweenMaintenances = {}; - for (const auto& clusterEntry : par.clusterData) + for (const auto& clusterEntry : clusterData) { const auto& cluster = *(clusterEntry.first); if (cluster.doWeGenerateTS(globalThermalTSgeneration_) && cluster.optimizeMaintenance) @@ -145,10 +145,10 @@ int OptimizedThermalGenerator::calculateTimeStep() return 0; } -int OptimizedThermalGenerator::calculateTimeHorizon() +int OptimizationParameters::calculateTimeHorizon() { std::vector timeHorizonVector = {}; - for (const auto& clusterEntry : par.clusterData) + for (const auto& clusterEntry : clusterData) { const auto& cluster = *(clusterEntry.first); if (!(cluster.doWeGenerateTS(globalThermalTSgeneration_) && cluster.optimizeMaintenance)) @@ -173,9 +173,9 @@ int OptimizedThermalGenerator::calculateTimeHorizon() return 0; } -void OptimizedThermalGenerator::calculateDependantClusterData() +void OptimizationParameters::calculateDependantClusterData() { - for (auto& clusterEntry : par.clusterData) + for (auto& clusterEntry : clusterData) { auto& data = clusterEntry.second; const auto& cluster = *(clusterEntry.first); @@ -198,7 +198,7 @@ void OptimizedThermalGenerator::calculateDependantClusterData() return; } -void OptimizedThermalGenerator::setMaintenanceGroupParameters() +void OptimizationParameters::setMaintenanceGroupParameters() { // it is crucial that we allocateClusterData // and calculate NonDependantClusterData @@ -208,19 +208,19 @@ void OptimizedThermalGenerator::setMaintenanceGroupParameters() calculateNonDependantClusterData(); // calculateResidualLoad(); - par.residualLoadDailyValues_ = calculateDailySums(maintenanceGroup_.getUsedResidualLoadTS()); - std::tie(par.ensCost_, par.spillCost_) = calculateMaintenanceGroupENSandSpillageCost(); - par.timeStep_ = calculateTimeStep(); - par.timeHorizon_ = calculateTimeHorizon(); - par.timeHorizonFirstStep_ = par.timeHorizon_; + residualLoadDailyValues_ = calculateDailySums(maintenanceGroup_.getUsedResidualLoadTS()); + std::tie(ensCost_, spillCost_) = calculateMaintenanceGroupENSandSpillageCost(); + timeStep_ = calculateTimeStep(); + timeHorizon_ = calculateTimeHorizon(); + timeHorizonFirstStep_ = timeHorizon_; // calculateDependantClusterData // uses timeHorizon_ so it is important we calculate timeHorizon_ first calculateDependantClusterData(); } -bool OptimizedThermalGenerator::checkMaintenanceGroupParameters() +bool OptimizationParameters::checkMaintenanceGroupParameters() { - if (par.timeStep_ == 0) + if (timeStep_ == 0) { logs.info() << "Maintenance group: " << maintenanceGroup_.name() << ": The timeseries generation will be skiped: timeStep = 0. It is possible " @@ -228,7 +228,7 @@ bool OptimizedThermalGenerator::checkMaintenanceGroupParameters() "planning, or at least one cluster has interPoPeriod = 0"; return false; } - if (par.timeHorizon_ == 0) + if (timeHorizon_ == 0) { logs.info() << "Maintenance group: " << maintenanceGroup_.name() diff --git a/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParametersPerCluster.cpp b/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParametersPerCluster.cpp index bf583d7192..1da2befe2f 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParametersPerCluster.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParametersPerCluster.cpp @@ -7,7 +7,7 @@ namespace Antares::Solver::TSGenerator { -int OptimizedThermalGenerator::calculateUnitEarliestStartOfFirstMaintenance( +int OptimizationParameters::calculateUnitEarliestStartOfFirstMaintenance( const Data::ThermalCluster& cluster, uint unitIndex) { @@ -19,7 +19,7 @@ int OptimizedThermalGenerator::calculateUnitEarliestStartOfFirstMaintenance( - getDaysSinceLastMaintenance(cluster, unitIndex) - cluster.poWindows); } -int OptimizedThermalGenerator::calculateUnitLatestStartOfFirstMaintenance( +int OptimizationParameters::calculateUnitLatestStartOfFirstMaintenance( const Data::ThermalCluster& cluster, uint unitIndex) { @@ -38,10 +38,10 @@ int OptimizedThermalGenerator::calculateUnitLatestStartOfFirstMaintenance( std::max(0, getAverageDurationBetweenMaintenances(cluster) - getDaysSinceLastMaintenance(cluster, unitIndex) + cluster.poWindows), - par.timeHorizon_ - 1); + timeHorizon_ - 1); } -std::vector OptimizedThermalGenerator::calculateNumberOfMaintenances( +std::vector OptimizationParameters::calculateNumberOfMaintenances( const Data::ThermalCluster& cluster) { // getAverageMaintenanceDuration must be at least 1 @@ -52,7 +52,7 @@ std::vector OptimizedThermalGenerator::calculateNumberOfMaintenances( for (int unit = 0; unit != cluster.unitCount; ++unit) { - int div = (par.timeHorizon_ + getDaysSinceLastMaintenance(cluster, unit) + int div = (timeHorizon_ + getDaysSinceLastMaintenance(cluster, unit) - getAverageDurationBetweenMaintenances(cluster)) / (getAverageDurationBetweenMaintenances(cluster) + getAverageMaintenanceDuration(cluster)); diff --git a/src/solver/ts-generator/optimized-thermal-generator/Parameters/Getters.cpp b/src/solver/ts-generator/optimized-thermal-generator/Parameters/Getters.cpp index 4f4d2d2698..9815b421f4 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Parameters/Getters.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/Parameters/Getters.cpp @@ -7,8 +7,8 @@ namespace Antares::Solver::TSGenerator { // Getters -double OptimizedThermalGenerator::getPowerCost(const Data::ThermalCluster& cluster, - int optimizationDay) +double OptimizationParameters::getPowerCost(const Data::ThermalCluster& cluster, + int optimizationDay) { /* ** Unit cost can be directly set, @@ -35,41 +35,40 @@ double OptimizedThermalGenerator::getPowerCost(const Data::ThermalCluster& clust return 0.; } - return par.clusterData[&cluster].staticInputs.avgCost[dayOfTheYear(optimizationDay)]; + return clusterData[&cluster].staticInputs.avgCost[dayOfTheYear(optimizationDay)]; } -double OptimizedThermalGenerator::getPowerOutput(const Data::ThermalCluster& cluster, - int optimizationDay) +double OptimizationParameters::getPowerOutput(const Data::ThermalCluster& cluster, + int optimizationDay) { - return par.clusterData[&cluster].staticInputs.maxPower[dayOfTheYear(optimizationDay)]; + return clusterData[&cluster].staticInputs.maxPower[dayOfTheYear(optimizationDay)]; } -double OptimizedThermalGenerator::getResidualLoad(int optimizationDay) +double OptimizationParameters::getResidualLoad(int optimizationDay) { - return par.residualLoadDailyValues_[dayOfTheYear(optimizationDay)]; + return residualLoadDailyValues_[dayOfTheYear(optimizationDay)]; } -int OptimizedThermalGenerator::getNumberOfMaintenances(const Data::ThermalCluster& cluster, - int unit) +int OptimizationParameters::getNumberOfMaintenances(const Data::ThermalCluster& cluster, int unit) { - return par.clusterData[&cluster].dynamicInputs.numberOfMaintenances[unit]; + return clusterData[&cluster].dynamicInputs.numberOfMaintenances[unit]; } -int OptimizedThermalGenerator::getAverageMaintenanceDuration(const Data::ThermalCluster& cluster) +int OptimizationParameters::getAverageMaintenanceDuration(const Data::ThermalCluster& cluster) { - return par.clusterData[&cluster].staticInputs.averageMaintenanceDuration; + return clusterData[&cluster].staticInputs.averageMaintenanceDuration; } -int OptimizedThermalGenerator::getAverageDurationBetweenMaintenances( +int OptimizationParameters::getAverageDurationBetweenMaintenances( const Data::ThermalCluster& cluster) { return cluster.interPoPeriod; } -int OptimizedThermalGenerator::getDaysSinceLastMaintenance(const Data::ThermalCluster& cluster, - int unit) +int OptimizationParameters::getDaysSinceLastMaintenance(const Data::ThermalCluster& cluster, + int unit) { - return par.clusterData[&cluster].dynamicInputs.daysSinceLastMaintenance[unit]; + return clusterData[&cluster].dynamicInputs.daysSinceLastMaintenance[unit]; } } // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/Parameters/OptimizationParameters.h b/src/solver/ts-generator/optimized-thermal-generator/Parameters/OptimizationParameters.h new file mode 100644 index 0000000000..c61a9b0d2d --- /dev/null +++ b/src/solver/ts-generator/optimized-thermal-generator/Parameters/OptimizationParameters.h @@ -0,0 +1,117 @@ +// +// Created by milos on 14/11/23. +// + +#pragma once + +#include "../../randomized-thermal-generator/RandomizedGenerator.h" +#include "../Main/OptimizedGenerator.h" + +namespace Antares::Solver::TSGenerator +{ + +// it is better to immediately calculate and populate structure +// that will store information about clusters +// so inside optimization problem we just retrieve these data with getters +// not re-calculate them over and over again + +// this structure stores cluster input data (optimization parameters) +// that stays the same during optimizationS +// also temporary stores cluster output/results for one scenario + +struct StaticInputs +{ + // static input data + // calculated once before all loops + std::array maxPower; + std::array avgCost; + std::vector numberOfMaintenancesFirstStep; + int averageMaintenanceDuration; + + // for random generator + double AP[366]; + double BP[366]; +}; + +struct DynamicInputs +{ + // dynamic input data + // re-calculated after each optimization time-step + std::vector daysSinceLastMaintenance; + std::vector numberOfMaintenances; +}; + +struct DynamicResults +{ + // scenario results + // temporary store scenario results + // before writing them to output + // reset after each scenario + std::vector availableDailyPower; +}; + +struct ClusterData +{ + StaticInputs staticInputs; + DynamicInputs dynamicInputs; + DynamicResults dynamicResults; +}; + +class OptimizationParameters : public GeneratorTempData +{ +public: + explicit OptimizationParameters(Data::Study& study, + Data::MaintenanceGroup& maintenanceGroup, + bool globalThermalTSgeneration, + Solver::Progression::Task& progr, + IResultWriter& writer) : + GeneratorTempData(study, progr, writer), + maintenanceGroup_(maintenanceGroup), + modelingType_(study.parameters.renewableGeneration) + { + globalThermalTSgeneration_ = globalThermalTSgeneration; + } + +private: + Data::MaintenanceGroup& maintenanceGroup_; + Data::Parameters::RenewableGeneration& modelingType_; + bool globalThermalTSgeneration_; + +public: + int timeHorizon_; + int timeHorizonFirstStep_; + int timeStep_; + double ensCost_; + double spillCost_; + std::array residualLoadDailyValues_; + + std::map clusterData; + + // Calculate parameters methods - per maintenance group + void allocateClusterData(); + void calculateNonDependantClusterData(); + void calculateResidualLoad(); + std::pair calculateMaintenanceGroupENSandSpillageCost(); + int calculateTimeStep(); + int calculateTimeHorizon(); + void calculateDependantClusterData(); + void setMaintenanceGroupParameters(); + bool checkMaintenanceGroupParameters(); + + // getters + double getPowerCost(const Data::ThermalCluster& cluster, int optimizationDay); + double getPowerOutput(const Data::ThermalCluster& cluster, int optimizationDay); + double getResidualLoad(int optimizationDay); + int getAverageMaintenanceDuration(const Data::ThermalCluster& cluster); + int getAverageDurationBetweenMaintenances(const Data::ThermalCluster& cluster); + int getNumberOfMaintenances(const Data::ThermalCluster& cluster, int unit); + int getDaysSinceLastMaintenance(const Data::ThermalCluster& cluster, int unit); + // re-calculate parameters methods - per cluster-Unit + int calculateUnitEarliestStartOfFirstMaintenance(const Data::ThermalCluster& cluster, + uint unitIndex); + int calculateUnitLatestStartOfFirstMaintenance(const Data::ThermalCluster& cluster, + uint unitIndex); + std::vector calculateNumberOfMaintenances(const Data::ThermalCluster& cluster); +}; + +} // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostTimeStepOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostTimeStepOptimization.cpp index 8604f294ff..fc9025bac7 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostTimeStepOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostTimeStepOptimization.cpp @@ -135,7 +135,7 @@ int OptimizedThermalGenerator::reCalculateDaysSinceLastMnt(const OptProblemSetti void OptimizedThermalGenerator::reCalculateTimeHorizon() { - par.timeHorizon_ = calculateTimeHorizon(); + par.timeHorizon_ = par.calculateTimeHorizon(); } void OptimizedThermalGenerator::reCalculateNumberOfMaintenances() @@ -144,7 +144,7 @@ void OptimizedThermalGenerator::reCalculateNumberOfMaintenances() for (auto& cluster : par.clusterData) { cluster.second.dynamicInputs.numberOfMaintenances - = calculateNumberOfMaintenances(*(cluster.first)); + = par.calculateNumberOfMaintenances(*(cluster.first)); } } diff --git a/src/solver/ts-generator/randomized-thermal-generator/RandomizedGenerator.h b/src/solver/ts-generator/randomized-thermal-generator/RandomizedGenerator.h index 11c00a3941..9d20d672d5 100644 --- a/src/solver/ts-generator/randomized-thermal-generator/RandomizedGenerator.h +++ b/src/solver/ts-generator/randomized-thermal-generator/RandomizedGenerator.h @@ -16,6 +16,7 @@ namespace Antares::Solver::TSGenerator class GeneratorTempData { + friend class OptimizationParameters; friend class OptimizedThermalGenerator; public: From f89b216f91f41690b97d0d287b8fd47f31ff05ca Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Fri, 1 Dec 2023 02:15:18 +0100 Subject: [PATCH 239/315] move post-optimization to class --- .../Main/OptimizedGenerator.cpp | 6 ++- .../Main/OptimizedGenerator.h | 31 +---------- .../Optimization/SolveProbem.cpp | 2 +- .../Parameters/OptimizationParameters.h | 36 +++++++++++++ .../PostScenarioOptimization.cpp | 46 ++++++++-------- .../PostTimeStepOptimization.cpp | 53 ++++++++++--------- 6 files changed, 93 insertions(+), 81 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.cpp index cf1e989fa9..4303a56ae1 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.cpp @@ -37,9 +37,11 @@ void OptimizedThermalGenerator::GenerateOptimizedThermalTimeSeries() optSett.lastDay = optSett.firstDay + par.timeHorizon_; optSett.isFirstStep = false; } - postScenarioOptimization(optSett); + par.postScenarioOptimization(optSett, scenarioResults); + printMaintenances(optSett); // to be removed + printAvailability(optSett); // to be removed } - writeTsResults(); + par.writeTsResults(); } void OptimizedThermalGenerator::allocateWhereToWriteTs() diff --git a/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.h index 101688334d..33e08186f6 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.h @@ -125,36 +125,6 @@ class OptimizedThermalGenerator : public GeneratorTempData /* ===================END-MAIN=================== */ - /* ===================POST-OPTIMIZATION=================== */ - - // post-scenario optimization methods - void postScenarioOptimization(OptProblemSettings& optSett); - void calculateScenarioResults(); - void saveScenarioResults(const OptProblemSettings& optSett); - void saveScenarioResults(int fromCol, int toCol, Data::ThermalCluster& cluster); - void resetResultStorage(); - void reSetDaysSinceLastMnt(); - void reSetNumberOfMaintenances(); - void reSetTimeHorizon(); - void writeTsResults(); - - // post-timeStep optimization methods - void postTimeStepOptimization(OptProblemSettings& optSett); - void appendTimeStepResults(const OptProblemSettings& optSett); - void reCalculateDaysSinceLastMnt(const OptProblemSettings& optSett); - void reCalculateDaysSinceLastMnt(const OptProblemSettings& optSett, const Unit& unit); - int reCalculateDaysSinceLastMnt(const OptProblemSettings& optSett, - const Unit& unit, - bool maintenanceHappened, - int lastMaintenanceStart, - int lastMaintenanceDuration); - void reCalculateTimeHorizon(); - void reCalculateNumberOfMaintenances(); - - /* ===================END-POST-OPTIMIZATION=================== */ - - - /* ===================CLASS-VARIABLES=================== */ // variables @@ -190,6 +160,7 @@ class OptimizedThermalGenerator : public GeneratorTempData scenarioLength_ = study.parameters.maintenancePlanning.getScenarioLength(); scenarioNumber_ = study.parameters.maintenancePlanning.getScenarioNumber(); nbThermalTimeseries = scenarioLength_ * scenarioNumber_; + par.scenarioLength_ = scenarioLength_; // Solver Settings // MP solver parameters / TODD CR27: do we change this - diff --git a/src/solver/ts-generator/optimized-thermal-generator/Optimization/SolveProbem.cpp b/src/solver/ts-generator/optimized-thermal-generator/Optimization/SolveProbem.cpp index a82d2c7c05..84f5886b77 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Optimization/SolveProbem.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/Optimization/SolveProbem.cpp @@ -17,7 +17,7 @@ bool OptimizedThermalGenerator::runOptimizationProblem(OptProblemSettings& optSe if (!solveProblem(optSett)) return false; printProblemVarAndResults(optSett); - postTimeStepOptimization(optSett); + par.postTimeStepOptimization(optSett, vars, scenarioResults); return true; } diff --git a/src/solver/ts-generator/optimized-thermal-generator/Parameters/OptimizationParameters.h b/src/solver/ts-generator/optimized-thermal-generator/Parameters/OptimizationParameters.h index c61a9b0d2d..ee0661cd46 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Parameters/OptimizationParameters.h +++ b/src/solver/ts-generator/optimized-thermal-generator/Parameters/OptimizationParameters.h @@ -59,6 +59,8 @@ struct ClusterData class OptimizationParameters : public GeneratorTempData { + using OptimizationResults = std::vector; + public: explicit OptimizationParameters(Data::Study& study, Data::MaintenanceGroup& maintenanceGroup, @@ -78,6 +80,7 @@ class OptimizationParameters : public GeneratorTempData bool globalThermalTSgeneration_; public: + int scenarioLength_; int timeHorizon_; int timeHorizonFirstStep_; int timeStep_; @@ -112,6 +115,39 @@ class OptimizationParameters : public GeneratorTempData int calculateUnitLatestStartOfFirstMaintenance(const Data::ThermalCluster& cluster, uint unitIndex); std::vector calculateNumberOfMaintenances(const Data::ThermalCluster& cluster); + + /* ===================POST-OPTIMIZATION=================== */ + + // post-scenario optimization methods + void postScenarioOptimization(OptProblemSettings& optSett, OptimizationResults& scenarioResults); + void calculateScenarioResults(OptimizationResults& scenarioResults); + void saveScenarioResults(const OptProblemSettings& optSett); + void saveScenarioResults(int fromCol, int toCol, Data::ThermalCluster& cluster); + void resetResultStorage(OptimizationResults& scenarioResults); + void reSetDaysSinceLastMnt(); + void reSetNumberOfMaintenances(); + void reSetTimeHorizon(); + void writeTsResults(); + + // post-timeStep optimization methods + void postTimeStepOptimization(OptProblemSettings& optSett, + const OptimizationVariables& readResultsFrom, + OptimizationResults& scenarioResults); + void appendTimeStepResults(const OptProblemSettings& optSett, + const OptimizationVariables& readResultsFrom, + OptimizationResults& scenarioResults); + void reCalculateDaysSinceLastMnt(const OptProblemSettings& optSett, + OptimizationResults& scenarioResults); + void reCalculateDaysSinceLastMnt(const OptProblemSettings& optSett, const Unit& unit); + int reCalculateDaysSinceLastMnt(const OptProblemSettings& optSett, + const Unit& unit, + bool maintenanceHappened, + int lastMaintenanceStart, + int lastMaintenanceDuration); + void reCalculateTimeHorizon(); + void reCalculateNumberOfMaintenances(); + + /* ===================END-POST-OPTIMIZATION=================== */ }; } // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostScenarioOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostScenarioOptimization.cpp index be474275aa..a94f688792 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostScenarioOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostScenarioOptimization.cpp @@ -7,17 +7,15 @@ namespace Antares::Solver::TSGenerator { -void OptimizedThermalGenerator::postScenarioOptimization(OptProblemSettings& optSett) +void OptimizationParameters::postScenarioOptimization(OptProblemSettings& optSett, OptimizationResults& scenarioResults) { // do not save if optimization failed at some step if (!optSett.solved) return; - calculateScenarioResults(); + calculateScenarioResults(scenarioResults); saveScenarioResults(optSett); - printMaintenances(optSett); // to be removed - printAvailability(optSett); // to be removed - resetResultStorage(); + resetResultStorage(scenarioResults); reSetDaysSinceLastMnt(); reSetTimeHorizon(); reSetNumberOfMaintenances(); @@ -25,7 +23,7 @@ void OptimizedThermalGenerator::postScenarioOptimization(OptProblemSettings& opt return; } -void OptimizedThermalGenerator::calculateScenarioResults() +void OptimizationParameters::calculateScenarioResults(OptimizationResults& scenarioResults) { // for each unit we have now scenarioResults // which contains std::pairs of all [maintenanceStart, maintenanceDuration] @@ -40,7 +38,7 @@ void OptimizedThermalGenerator::calculateScenarioResults() // now lets get CLUSTER availability by summing up UNIT availability // fill in with zeros - for (auto& cluster : par.clusterData) + for (auto& cluster : clusterData) { cluster.second.dynamicResults.availableDailyPower.resize(scenarioLength_ * DAYS_PER_YEAR); } @@ -49,7 +47,7 @@ void OptimizedThermalGenerator::calculateScenarioResults() for (auto& unit : scenarioResults) { auto& availableDailyPower - = par.clusterData[unit.parentCluster].dynamicResults.availableDailyPower; + = clusterData[unit.parentCluster].dynamicResults.availableDailyPower; std::transform(availableDailyPower.begin(), availableDailyPower.end(), @@ -65,7 +63,7 @@ void OptimizedThermalGenerator::calculateScenarioResults() return; } -void OptimizedThermalGenerator::saveScenarioResults(const OptProblemSettings& optSett) +void OptimizationParameters::saveScenarioResults(const OptProblemSettings& optSett) { // loop through all clusters and write results // for one scenario into designated columns @@ -74,7 +72,7 @@ void OptimizedThermalGenerator::saveScenarioResults(const OptProblemSettings& op int colSaveTo = colSaveFrom + scenarioLength_; // using on purpose this double loop - // because looping through par.clusterData we cannot change cluster + // because looping through clusterData we cannot change cluster // const Data::ThermalCluster* for (auto& entryWeightMap : maintenanceGroup_) { @@ -95,17 +93,17 @@ void OptimizedThermalGenerator::saveScenarioResults(const OptProblemSettings& op return; } -void OptimizedThermalGenerator::saveScenarioResults(int fromCol, +void OptimizationParameters::saveScenarioResults(int fromCol, int toCol, Data::ThermalCluster& cluster) { - // daily results are in par.clusterData.availableDailyPower + // daily results are in clusterData.availableDailyPower // convert to hourly values and store in cluster ts // we assume that vector availableDailyPower has: // scenarioLength_ * DAYS_PER_YEAR element // that we need to store inside columns from-to - auto& availability = par.clusterData[&cluster].dynamicResults.availableDailyPower; + auto& availability = clusterData[&cluster].dynamicResults.availableDailyPower; assert((toCol - fromCol) * DAYS_PER_YEAR == availability.size()); int vctCol = 0; @@ -119,15 +117,15 @@ void OptimizedThermalGenerator::saveScenarioResults(int fromCol, } } -void OptimizedThermalGenerator::resetResultStorage() +void OptimizationParameters::resetResultStorage(OptimizationResults& scenarioResults) { // clear units result structure scenarioResults.clear(); // clear cluster result structure - // do not clear whole par.clusterData + // do not clear whole clusterData // we store input data here as well - for (auto& cluster : par.clusterData) + for (auto& cluster : clusterData) { cluster.second.dynamicResults.availableDailyPower.clear(); } @@ -135,13 +133,13 @@ void OptimizedThermalGenerator::resetResultStorage() return; } -void OptimizedThermalGenerator::reSetDaysSinceLastMnt() +void OptimizationParameters::reSetDaysSinceLastMnt() { // we are back in first step, but not first scenario // we have messed up our values // we need to reset - for (auto& cluster : par.clusterData) + for (auto& cluster : clusterData) { cluster.second.dynamicInputs.daysSinceLastMaintenance = cluster.first->originalRandomlyGeneratedDaysSinceLastMaintenance; @@ -150,23 +148,23 @@ void OptimizedThermalGenerator::reSetDaysSinceLastMnt() return; } -void OptimizedThermalGenerator::reSetTimeHorizon() +void OptimizationParameters::reSetTimeHorizon() { // we are back in first step, but not first scenario // we have messed up our values // we need to reset - par.timeHorizon_ = par.timeHorizonFirstStep_; + timeHorizon_ = timeHorizonFirstStep_; return; } -void OptimizedThermalGenerator::reSetNumberOfMaintenances() +void OptimizationParameters::reSetNumberOfMaintenances() { // we are back in first step, but not first scenario // we have messed up our values // we need to reset - for (auto& cluster : par.clusterData) + for (auto& cluster : clusterData) { cluster.second.dynamicInputs.numberOfMaintenances = cluster.second.staticInputs.numberOfMaintenancesFirstStep; @@ -177,11 +175,11 @@ void OptimizedThermalGenerator::reSetNumberOfMaintenances() // this method is called at the very end // after all time-steps and scenarios -void OptimizedThermalGenerator::writeTsResults() +void OptimizationParameters::writeTsResults() { // we need to loop through all the clusters // and write the results - // it would be much easier to loop using par.clusterData + // it would be much easier to loop using clusterData // inside of it we already excluded all the non-important clusters // however it is const Data::ThermalCluster* // so we cannot modify cluster values diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostTimeStepOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostTimeStepOptimization.cpp index fc9025bac7..f57b843beb 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostTimeStepOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostTimeStepOptimization.cpp @@ -7,17 +7,21 @@ namespace Antares::Solver::TSGenerator { -void OptimizedThermalGenerator::postTimeStepOptimization(OptProblemSettings& optSett) +void OptimizationParameters::postTimeStepOptimization(OptProblemSettings& optSett, + const OptimizationVariables& readResultsFrom, + OptimizationResults& scenarioResults) { - appendTimeStepResults(optSett); - reCalculateDaysSinceLastMnt(optSett); + appendTimeStepResults(optSett, readResultsFrom, scenarioResults); + reCalculateDaysSinceLastMnt(optSett, scenarioResults); reCalculateTimeHorizon(); reCalculateNumberOfMaintenances(); return; } // save/append optimization results form range 0-timeStep -void OptimizedThermalGenerator::appendTimeStepResults(const OptProblemSettings& optSett) +void OptimizationParameters::appendTimeStepResults(const OptProblemSettings& optSett, + const OptimizationVariables& readResultsFrom, + OptimizationResults& scenarioResults) { // we have vectors of start (zeros and ones) // lets convert that into maintenance start day vector @@ -25,7 +29,7 @@ void OptimizedThermalGenerator::appendTimeStepResults(const OptProblemSettings& // and create std::pairs - of start_day + mnt_duration // loop per units - for (std::size_t unitIndexTotal = 0; unitIndexTotal < vars.clusterUnits.size(); + for (std::size_t unitIndexTotal = 0; unitIndexTotal < readResultsFrom.clusterUnits.size(); ++unitIndexTotal) { // Unit-unitIndexTotal - is index in a vector of all the units (area * cluster * units) @@ -39,7 +43,7 @@ void OptimizedThermalGenerator::appendTimeStepResults(const OptProblemSettings& // and just loop // assert parentCluster and index - const auto& readResultUnit = vars.clusterUnits[unitIndexTotal]; + const auto& readResultUnit = readResultsFrom.clusterUnits[unitIndexTotal]; auto& storeResultUnit = scenarioResults[unitIndexTotal]; assert(readResultUnit.parentCluster == storeResultUnit.parentCluster @@ -58,7 +62,7 @@ void OptimizedThermalGenerator::appendTimeStepResults(const OptProblemSettings& // only one maintenance can happen in the timeStep_ // TODO CR27: in phase-II we may change this and looping will be necessary { - int localMaintenanceStart = readResultUnit.maintenances[0].startDay(par.timeStep_); + int localMaintenanceStart = readResultUnit.maintenances[0].startDay(timeStep_); if (localMaintenanceStart == -1) continue; @@ -67,8 +71,8 @@ void OptimizedThermalGenerator::appendTimeStepResults(const OptProblemSettings& int PODOfTheDay = (int)cluster.prepro->data[Data::PreproThermal::poDuration][dayInTheYearStart]; - double app = par.clusterData[&cluster].staticInputs.AP[dayInTheYearStart]; - double bpp = par.clusterData[&cluster].staticInputs.BP[dayInTheYearStart]; + double app = clusterData[&cluster].staticInputs.AP[dayInTheYearStart]; + double bpp = clusterData[&cluster].staticInputs.BP[dayInTheYearStart]; int maintenanceDuration = durationGenerator( cluster.plannedLaw, PODOfTheDay, cluster.plannedVolatility, app, bpp); @@ -82,7 +86,8 @@ void OptimizedThermalGenerator::appendTimeStepResults(const OptProblemSettings& // re-calculate parameters -void OptimizedThermalGenerator::reCalculateDaysSinceLastMnt(const OptProblemSettings& optSett) +void OptimizationParameters::reCalculateDaysSinceLastMnt(const OptProblemSettings& optSett, + OptimizationResults& scenarioResults) { // re-calculate days since last maintenance inputs if necessary for (const auto& unit : scenarioResults) @@ -91,11 +96,11 @@ void OptimizedThermalGenerator::reCalculateDaysSinceLastMnt(const OptProblemSett } } -void OptimizedThermalGenerator::reCalculateDaysSinceLastMnt(const OptProblemSettings& optSett, - const Unit& unit) +void OptimizationParameters::reCalculateDaysSinceLastMnt(const OptProblemSettings& optSett, + const Unit& unit) { auto& daysSinceLastMaintenance - = par.clusterData[unit.parentCluster].dynamicInputs.daysSinceLastMaintenance[unit.index]; + = clusterData[unit.parentCluster].dynamicInputs.daysSinceLastMaintenance[unit.index]; bool maintenanceHappened = false; if (unit.maintenanceResults.empty()) @@ -114,13 +119,13 @@ void OptimizedThermalGenerator::reCalculateDaysSinceLastMnt(const OptProblemSett return; } -int OptimizedThermalGenerator::reCalculateDaysSinceLastMnt(const OptProblemSettings& optSett, - const Unit& unit, - bool maintenanceHappened, - int lastMaintenanceStart, - int lastMaintenanceDuration) +int OptimizationParameters::reCalculateDaysSinceLastMnt(const OptProblemSettings& optSett, + const Unit& unit, + bool maintenanceHappened, + int lastMaintenanceStart, + int lastMaintenanceDuration) { - int nextOptimizationFirstDay = optSett.firstDay + par.timeStep_; + int nextOptimizationFirstDay = optSett.firstDay + timeStep_; if (maintenanceHappened) return std::max( 0, nextOptimizationFirstDay - (lastMaintenanceStart + lastMaintenanceDuration)); @@ -133,18 +138,18 @@ int OptimizedThermalGenerator::reCalculateDaysSinceLastMnt(const OptProblemSetti + unit.parentCluster->originalRandomlyGeneratedDaysSinceLastMaintenance[unit.index]; } -void OptimizedThermalGenerator::reCalculateTimeHorizon() +void OptimizationParameters::reCalculateTimeHorizon() { - par.timeHorizon_ = par.calculateTimeHorizon(); + timeHorizon_ = calculateTimeHorizon(); } -void OptimizedThermalGenerator::reCalculateNumberOfMaintenances() +void OptimizationParameters::reCalculateNumberOfMaintenances() { // re-calculate days since last maintenance inputs if necessary - for (auto& cluster : par.clusterData) + for (auto& cluster : clusterData) { cluster.second.dynamicInputs.numberOfMaintenances - = par.calculateNumberOfMaintenances(*(cluster.first)); + = calculateNumberOfMaintenances(*(cluster.first)); } } From c6fddd75e7a4c888e2eb470631d5d957a21abda0 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Fri, 1 Dec 2023 02:45:07 +0100 Subject: [PATCH 240/315] re-name --- .../Parameters/OptimizationParameters.h | 55 +++++++++++-------- .../PostScenarioOptimization.cpp | 7 ++- .../PostTimeStepOptimization.cpp | 10 ++-- 3 files changed, 41 insertions(+), 31 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/Parameters/OptimizationParameters.h b/src/solver/ts-generator/optimized-thermal-generator/Parameters/OptimizationParameters.h index ee0661cd46..7845b1cdb0 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Parameters/OptimizationParameters.h +++ b/src/solver/ts-generator/optimized-thermal-generator/Parameters/OptimizationParameters.h @@ -16,8 +16,10 @@ namespace Antares::Solver::TSGenerator // not re-calculate them over and over again // this structure stores cluster input data (optimization parameters) -// that stays the same during optimizationS -// also temporary stores cluster output/results for one scenario +// that stays the same during optimization - static inputs +// that are updated after each optimization - dynamic inputs +// the structure also temporary stores scenario results +// output/results for one scenario struct StaticInputs { @@ -90,7 +92,8 @@ class OptimizationParameters : public GeneratorTempData std::map clusterData; - // Calculate parameters methods - per maintenance group + /* ===================CALCULATE-PARAMETERS-MAIN=================== */ + void allocateClusterData(); void calculateNonDependantClusterData(); void calculateResidualLoad(); @@ -101,7 +104,16 @@ class OptimizationParameters : public GeneratorTempData void setMaintenanceGroupParameters(); bool checkMaintenanceGroupParameters(); - // getters + /* ===================CALCULATE-PARAMETERS-PER CLUSTER/UNIT=================== */ + + int calculateUnitEarliestStartOfFirstMaintenance(const Data::ThermalCluster& cluster, + uint unitIndex); + int calculateUnitLatestStartOfFirstMaintenance(const Data::ThermalCluster& cluster, + uint unitIndex); + std::vector calculateNumberOfMaintenances(const Data::ThermalCluster& cluster); + + /* ===================GETTERS=================== */ + double getPowerCost(const Data::ThermalCluster& cluster, int optimizationDay); double getPowerOutput(const Data::ThermalCluster& cluster, int optimizationDay); double getResidualLoad(int optimizationDay); @@ -109,32 +121,16 @@ class OptimizationParameters : public GeneratorTempData int getAverageDurationBetweenMaintenances(const Data::ThermalCluster& cluster); int getNumberOfMaintenances(const Data::ThermalCluster& cluster, int unit); int getDaysSinceLastMaintenance(const Data::ThermalCluster& cluster, int unit); - // re-calculate parameters methods - per cluster-Unit - int calculateUnitEarliestStartOfFirstMaintenance(const Data::ThermalCluster& cluster, - uint unitIndex); - int calculateUnitLatestStartOfFirstMaintenance(const Data::ThermalCluster& cluster, - uint unitIndex); - std::vector calculateNumberOfMaintenances(const Data::ThermalCluster& cluster); /* ===================POST-OPTIMIZATION=================== */ - // post-scenario optimization methods - void postScenarioOptimization(OptProblemSettings& optSett, OptimizationResults& scenarioResults); - void calculateScenarioResults(OptimizationResults& scenarioResults); - void saveScenarioResults(const OptProblemSettings& optSett); - void saveScenarioResults(int fromCol, int toCol, Data::ThermalCluster& cluster); - void resetResultStorage(OptimizationResults& scenarioResults); - void reSetDaysSinceLastMnt(); - void reSetNumberOfMaintenances(); - void reSetTimeHorizon(); - void writeTsResults(); + /* ===================AFTER-EACH-TIME-STEP=================== */ - // post-timeStep optimization methods void postTimeStepOptimization(OptProblemSettings& optSett, - const OptimizationVariables& readResultsFrom, + const OptimizationVariables& stepResults, OptimizationResults& scenarioResults); void appendTimeStepResults(const OptProblemSettings& optSett, - const OptimizationVariables& readResultsFrom, + const OptimizationVariables& stepResults, OptimizationResults& scenarioResults); void reCalculateDaysSinceLastMnt(const OptProblemSettings& optSett, OptimizationResults& scenarioResults); @@ -147,6 +143,19 @@ class OptimizationParameters : public GeneratorTempData void reCalculateTimeHorizon(); void reCalculateNumberOfMaintenances(); + /* ===================AFTER-EACH-SCENARIO=================== */ + + void postScenarioOptimization(OptProblemSettings& optSett, + OptimizationResults& scenarioResults); + void calculateScenarioResults(OptimizationResults& scenarioResults); + void saveScenarioResults(const OptProblemSettings& optSett); + void saveScenarioResults(int fromCol, int toCol, Data::ThermalCluster& cluster); + void resetResultStorage(OptimizationResults& scenarioResults); + void reSetDaysSinceLastMnt(); + void reSetNumberOfMaintenances(); + void reSetTimeHorizon(); + void writeTsResults(); + /* ===================END-POST-OPTIMIZATION=================== */ }; diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostScenarioOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostScenarioOptimization.cpp index a94f688792..8244370e4c 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostScenarioOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostScenarioOptimization.cpp @@ -7,7 +7,8 @@ namespace Antares::Solver::TSGenerator { -void OptimizationParameters::postScenarioOptimization(OptProblemSettings& optSett, OptimizationResults& scenarioResults) +void OptimizationParameters::postScenarioOptimization(OptProblemSettings& optSett, + OptimizationResults& scenarioResults) { // do not save if optimization failed at some step if (!optSett.solved) @@ -94,8 +95,8 @@ void OptimizationParameters::saveScenarioResults(const OptProblemSettings& optSe } void OptimizationParameters::saveScenarioResults(int fromCol, - int toCol, - Data::ThermalCluster& cluster) + int toCol, + Data::ThermalCluster& cluster) { // daily results are in clusterData.availableDailyPower // convert to hourly values and store in cluster ts diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostTimeStepOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostTimeStepOptimization.cpp index f57b843beb..f913031cc6 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostTimeStepOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostTimeStepOptimization.cpp @@ -8,10 +8,10 @@ namespace Antares::Solver::TSGenerator { void OptimizationParameters::postTimeStepOptimization(OptProblemSettings& optSett, - const OptimizationVariables& readResultsFrom, + const OptimizationVariables& stepResults, OptimizationResults& scenarioResults) { - appendTimeStepResults(optSett, readResultsFrom, scenarioResults); + appendTimeStepResults(optSett, stepResults, scenarioResults); reCalculateDaysSinceLastMnt(optSett, scenarioResults); reCalculateTimeHorizon(); reCalculateNumberOfMaintenances(); @@ -20,7 +20,7 @@ void OptimizationParameters::postTimeStepOptimization(OptProblemSettings& optSet // save/append optimization results form range 0-timeStep void OptimizationParameters::appendTimeStepResults(const OptProblemSettings& optSett, - const OptimizationVariables& readResultsFrom, + const OptimizationVariables& stepResults, OptimizationResults& scenarioResults) { // we have vectors of start (zeros and ones) @@ -29,7 +29,7 @@ void OptimizationParameters::appendTimeStepResults(const OptProblemSettings& opt // and create std::pairs - of start_day + mnt_duration // loop per units - for (std::size_t unitIndexTotal = 0; unitIndexTotal < readResultsFrom.clusterUnits.size(); + for (std::size_t unitIndexTotal = 0; unitIndexTotal < stepResults.clusterUnits.size(); ++unitIndexTotal) { // Unit-unitIndexTotal - is index in a vector of all the units (area * cluster * units) @@ -43,7 +43,7 @@ void OptimizationParameters::appendTimeStepResults(const OptProblemSettings& opt // and just loop // assert parentCluster and index - const auto& readResultUnit = readResultsFrom.clusterUnits[unitIndexTotal]; + const auto& readResultUnit = stepResults.clusterUnits[unitIndexTotal]; auto& storeResultUnit = scenarioResults[unitIndexTotal]; assert(readResultUnit.parentCluster == storeResultUnit.parentCluster From 68981cb81a5722a292ca874e2430b51337b862df Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Fri, 1 Dec 2023 03:01:32 +0100 Subject: [PATCH 241/315] writeTsResults - back to main class --- .../optimized-thermal-generator/Main/OptimizedGenerator.cpp | 2 +- .../optimized-thermal-generator/Main/OptimizedGenerator.h | 1 + .../Parameters/OptimizationParameters.h | 1 - .../PostOptimization/PostScenarioOptimization.cpp | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.cpp index 4303a56ae1..02e85ab373 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.cpp @@ -41,7 +41,7 @@ void OptimizedThermalGenerator::GenerateOptimizedThermalTimeSeries() printMaintenances(optSett); // to be removed printAvailability(optSett); // to be removed } - par.writeTsResults(); + writeTsResults(); } void OptimizedThermalGenerator::allocateWhereToWriteTs() diff --git a/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.h index 33e08186f6..c8cb202b6e 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.h @@ -122,6 +122,7 @@ class OptimizedThermalGenerator : public GeneratorTempData // Functions called in main method: void allocateWhereToWriteTs(); bool runOptimizationProblem(OptProblemSettings& optSett); + void writeTsResults(); /* ===================END-MAIN=================== */ diff --git a/src/solver/ts-generator/optimized-thermal-generator/Parameters/OptimizationParameters.h b/src/solver/ts-generator/optimized-thermal-generator/Parameters/OptimizationParameters.h index 7845b1cdb0..222784e85f 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Parameters/OptimizationParameters.h +++ b/src/solver/ts-generator/optimized-thermal-generator/Parameters/OptimizationParameters.h @@ -154,7 +154,6 @@ class OptimizationParameters : public GeneratorTempData void reSetDaysSinceLastMnt(); void reSetNumberOfMaintenances(); void reSetTimeHorizon(); - void writeTsResults(); /* ===================END-POST-OPTIMIZATION=================== */ }; diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostScenarioOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostScenarioOptimization.cpp index 8244370e4c..73efe4a18a 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostScenarioOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostScenarioOptimization.cpp @@ -176,7 +176,7 @@ void OptimizationParameters::reSetNumberOfMaintenances() // this method is called at the very end // after all time-steps and scenarios -void OptimizationParameters::writeTsResults() +void OptimizedThermalGenerator::writeTsResults() { // we need to loop through all the clusters // and write the results From 4c02b81254076348c0c4db3d4e1c7b3849957fbe Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Fri, 1 Dec 2023 09:00:30 +0100 Subject: [PATCH 242/315] make var & sceRes available to OptimizationParameter class --- .../Main/OptimizedGenerator.cpp | 2 +- .../Main/OptimizedGenerator.h | 2 +- .../Optimization/SolveProbem.cpp | 2 +- .../Parameters/OptimizationParameters.h | 32 +++++++++---------- .../PostScenarioOptimization.cpp | 19 ++++++----- .../PostTimeStepOptimization.cpp | 23 ++++++------- 6 files changed, 37 insertions(+), 43 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.cpp index 02e85ab373..bdb0069c6e 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.cpp @@ -37,7 +37,7 @@ void OptimizedThermalGenerator::GenerateOptimizedThermalTimeSeries() optSett.lastDay = optSett.firstDay + par.timeHorizon_; optSett.isFirstStep = false; } - par.postScenarioOptimization(optSett, scenarioResults); + par.postScenarioOptimization(optSett); printMaintenances(optSett); // to be removed printAvailability(optSett); // to be removed } diff --git a/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.h index c8cb202b6e..79149bddf1 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.h @@ -153,7 +153,7 @@ class OptimizedThermalGenerator : public GeneratorTempData IResultWriter& writer) : GeneratorTempData(study, progr, writer), maintenanceGroup_(maintenanceGroup), - par(study, maintenanceGroup, globalThermalTSgeneration, progr, writer), + par(study, maintenanceGroup, globalThermalTSgeneration, vars, scenarioResults, progr, writer), solver(MPSolver("MaintenancePlanning", MPSolver::CBC_MIXED_INTEGER_PROGRAMMING)) { currentYear = year; diff --git a/src/solver/ts-generator/optimized-thermal-generator/Optimization/SolveProbem.cpp b/src/solver/ts-generator/optimized-thermal-generator/Optimization/SolveProbem.cpp index 84f5886b77..b7230ba986 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Optimization/SolveProbem.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/Optimization/SolveProbem.cpp @@ -17,7 +17,7 @@ bool OptimizedThermalGenerator::runOptimizationProblem(OptProblemSettings& optSe if (!solveProblem(optSett)) return false; printProblemVarAndResults(optSett); - par.postTimeStepOptimization(optSett, vars, scenarioResults); + par.postTimeStepOptimization(optSett); return true; } diff --git a/src/solver/ts-generator/optimized-thermal-generator/Parameters/OptimizationParameters.h b/src/solver/ts-generator/optimized-thermal-generator/Parameters/OptimizationParameters.h index 222784e85f..249b2af63d 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Parameters/OptimizationParameters.h +++ b/src/solver/ts-generator/optimized-thermal-generator/Parameters/OptimizationParameters.h @@ -67,19 +67,25 @@ class OptimizationParameters : public GeneratorTempData explicit OptimizationParameters(Data::Study& study, Data::MaintenanceGroup& maintenanceGroup, bool globalThermalTSgeneration, + OptimizationVariables& vars, + OptimizationResults& scenarioResults, Solver::Progression::Task& progr, IResultWriter& writer) : GeneratorTempData(study, progr, writer), maintenanceGroup_(maintenanceGroup), - modelingType_(study.parameters.renewableGeneration) + globalThermalTSgeneration_(globalThermalTSgeneration), + modelingType_(study.parameters.renewableGeneration), + vars_(vars), + scenarioResults_(scenarioResults) { - globalThermalTSgeneration_ = globalThermalTSgeneration; } private: Data::MaintenanceGroup& maintenanceGroup_; - Data::Parameters::RenewableGeneration& modelingType_; - bool globalThermalTSgeneration_; + const Data::Parameters::RenewableGeneration& modelingType_; + const bool globalThermalTSgeneration_; + const OptimizationVariables& vars_; + OptimizationResults& scenarioResults_; public: int scenarioLength_; @@ -126,14 +132,9 @@ class OptimizationParameters : public GeneratorTempData /* ===================AFTER-EACH-TIME-STEP=================== */ - void postTimeStepOptimization(OptProblemSettings& optSett, - const OptimizationVariables& stepResults, - OptimizationResults& scenarioResults); - void appendTimeStepResults(const OptProblemSettings& optSett, - const OptimizationVariables& stepResults, - OptimizationResults& scenarioResults); - void reCalculateDaysSinceLastMnt(const OptProblemSettings& optSett, - OptimizationResults& scenarioResults); + void postTimeStepOptimization(OptProblemSettings& optSett); + void appendTimeStepResults(const OptProblemSettings& optSett); + void reCalculateDaysSinceLastMnt(const OptProblemSettings& optSett); void reCalculateDaysSinceLastMnt(const OptProblemSettings& optSett, const Unit& unit); int reCalculateDaysSinceLastMnt(const OptProblemSettings& optSett, const Unit& unit, @@ -145,12 +146,11 @@ class OptimizationParameters : public GeneratorTempData /* ===================AFTER-EACH-SCENARIO=================== */ - void postScenarioOptimization(OptProblemSettings& optSett, - OptimizationResults& scenarioResults); - void calculateScenarioResults(OptimizationResults& scenarioResults); + void postScenarioOptimization(OptProblemSettings& optSett); + void calculateScenarioResults(); void saveScenarioResults(const OptProblemSettings& optSett); void saveScenarioResults(int fromCol, int toCol, Data::ThermalCluster& cluster); - void resetResultStorage(OptimizationResults& scenarioResults); + void resetResultStorage(); void reSetDaysSinceLastMnt(); void reSetNumberOfMaintenances(); void reSetTimeHorizon(); diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostScenarioOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostScenarioOptimization.cpp index 73efe4a18a..230017ea35 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostScenarioOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostScenarioOptimization.cpp @@ -7,16 +7,15 @@ namespace Antares::Solver::TSGenerator { -void OptimizationParameters::postScenarioOptimization(OptProblemSettings& optSett, - OptimizationResults& scenarioResults) +void OptimizationParameters::postScenarioOptimization(OptProblemSettings& optSett) { // do not save if optimization failed at some step if (!optSett.solved) return; - calculateScenarioResults(scenarioResults); + calculateScenarioResults(); saveScenarioResults(optSett); - resetResultStorage(scenarioResults); + resetResultStorage(); reSetDaysSinceLastMnt(); reSetTimeHorizon(); reSetNumberOfMaintenances(); @@ -24,14 +23,14 @@ void OptimizationParameters::postScenarioOptimization(OptProblemSettings& optSet return; } -void OptimizationParameters::calculateScenarioResults(OptimizationResults& scenarioResults) +void OptimizationParameters::calculateScenarioResults() { - // for each unit we have now scenarioResults + // for each unit we have now scenarioResults_ // which contains std::pairs of all [maintenanceStart, maintenanceDuration] // lets transfer that into vectors of UNIT availability // loop per units - for (auto& unit : scenarioResults) + for (auto& unit : scenarioResults_) { unit.calculateAvailableDailyPower(scenarioLength_); } @@ -45,7 +44,7 @@ void OptimizationParameters::calculateScenarioResults(OptimizationResults& scena } // add one by one unit availability - for (auto& unit : scenarioResults) + for (auto& unit : scenarioResults_) { auto& availableDailyPower = clusterData[unit.parentCluster].dynamicResults.availableDailyPower; @@ -118,10 +117,10 @@ void OptimizationParameters::saveScenarioResults(int fromCol, } } -void OptimizationParameters::resetResultStorage(OptimizationResults& scenarioResults) +void OptimizationParameters::resetResultStorage() { // clear units result structure - scenarioResults.clear(); + scenarioResults_.clear(); // clear cluster result structure // do not clear whole clusterData // we store input data here as well diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostTimeStepOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostTimeStepOptimization.cpp index f913031cc6..25e681b126 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostTimeStepOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostTimeStepOptimization.cpp @@ -7,21 +7,17 @@ namespace Antares::Solver::TSGenerator { -void OptimizationParameters::postTimeStepOptimization(OptProblemSettings& optSett, - const OptimizationVariables& stepResults, - OptimizationResults& scenarioResults) +void OptimizationParameters::postTimeStepOptimization(OptProblemSettings& optSett) { - appendTimeStepResults(optSett, stepResults, scenarioResults); - reCalculateDaysSinceLastMnt(optSett, scenarioResults); + appendTimeStepResults(optSett); + reCalculateDaysSinceLastMnt(optSett); reCalculateTimeHorizon(); reCalculateNumberOfMaintenances(); return; } // save/append optimization results form range 0-timeStep -void OptimizationParameters::appendTimeStepResults(const OptProblemSettings& optSett, - const OptimizationVariables& stepResults, - OptimizationResults& scenarioResults) +void OptimizationParameters::appendTimeStepResults(const OptProblemSettings& optSett) { // we have vectors of start (zeros and ones) // lets convert that into maintenance start day vector @@ -29,7 +25,7 @@ void OptimizationParameters::appendTimeStepResults(const OptProblemSettings& opt // and create std::pairs - of start_day + mnt_duration // loop per units - for (std::size_t unitIndexTotal = 0; unitIndexTotal < stepResults.clusterUnits.size(); + for (std::size_t unitIndexTotal = 0; unitIndexTotal < vars_.clusterUnits.size(); ++unitIndexTotal) { // Unit-unitIndexTotal - is index in a vector of all the units (area * cluster * units) @@ -43,8 +39,8 @@ void OptimizationParameters::appendTimeStepResults(const OptProblemSettings& opt // and just loop // assert parentCluster and index - const auto& readResultUnit = stepResults.clusterUnits[unitIndexTotal]; - auto& storeResultUnit = scenarioResults[unitIndexTotal]; + const auto& readResultUnit = vars_.clusterUnits[unitIndexTotal]; + auto& storeResultUnit = scenarioResults_[unitIndexTotal]; assert(readResultUnit.parentCluster == storeResultUnit.parentCluster && "Read and Store Units do not point to the same parent cluster."); @@ -86,11 +82,10 @@ void OptimizationParameters::appendTimeStepResults(const OptProblemSettings& opt // re-calculate parameters -void OptimizationParameters::reCalculateDaysSinceLastMnt(const OptProblemSettings& optSett, - OptimizationResults& scenarioResults) +void OptimizationParameters::reCalculateDaysSinceLastMnt(const OptProblemSettings& optSett) { // re-calculate days since last maintenance inputs if necessary - for (const auto& unit : scenarioResults) + for (const auto& unit : scenarioResults_) { reCalculateDaysSinceLastMnt(optSett, unit); } From 9d45059d57b9ff4fcca3d8c1b322ccf79ba603de Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Fri, 1 Dec 2023 09:07:24 +0100 Subject: [PATCH 243/315] move write results to separate file --- src/solver/ts-generator/CMakeLists.txt | 1 + .../PostOptimization/WriteResults.cpp | 45 +++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 src/solver/ts-generator/optimized-thermal-generator/PostOptimization/WriteResults.cpp diff --git a/src/solver/ts-generator/CMakeLists.txt b/src/solver/ts-generator/CMakeLists.txt index 8f745b797c..ab64a18d3f 100644 --- a/src/solver/ts-generator/CMakeLists.txt +++ b/src/solver/ts-generator/CMakeLists.txt @@ -34,6 +34,7 @@ set(SRC_OPTIMIZEDGENERATORS optimized-thermal-generator/Optimization/PrintProblemVarRes.cpp optimized-thermal-generator/PostOptimization/PostTimeStepOptimization.cpp optimized-thermal-generator/PostOptimization/PostScenarioOptimization.cpp + optimized-thermal-generator/PostOptimization/WriteResults.cpp ) source_group("ts-generator\\optimized-thermal-generator" FILES ${SRC_OPTIMIZEDGENERATORS}) diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/WriteResults.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/WriteResults.cpp new file mode 100644 index 0000000000..69254e0237 --- /dev/null +++ b/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/WriteResults.cpp @@ -0,0 +1,45 @@ +// +// Created by milos on 14/11/23. +// + +#include "../Main/OptimizedGenerator.h" + +namespace Antares::Solver::TSGenerator +{ + +// this method is called at the very end +// after all time-steps and scenarios +void OptimizedThermalGenerator::writeTsResults() +{ + // we need to loop through all the clusters + // and write the results + // it would be much easier to loop using clusterData + // inside of it we already excluded all the non-important clusters + // however it is const Data::ThermalCluster* + // so we cannot modify cluster values + + for (auto& entryWeightMap : maintenanceGroup_) + { + auto& area = *(entryWeightMap.first); + + for (auto& clusterEntry : area.thermal.list.mapping) + { + auto& cluster = *(clusterEntry.second); + + if (!(checkClusterExist(cluster) && cluster.doWeGenerateTS(globalThermalTSgeneration_) + && cluster.optimizeMaintenance)) + continue; + + if (derated) + cluster.series.timeSeries.averageTimeseries(); + + if (archive) + writeResultsToDisk(area, cluster); + + cluster.calculationOfSpinning(); + } + } + return; +} + +} // namespace Antares::Solver::TSGenerator From f1c0df2c2c026ab5643f182bdaba40e0d439d1a1 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Fri, 1 Dec 2023 09:13:38 +0100 Subject: [PATCH 244/315] progression++ --- .../optimized-thermal-generator/Main/OptimizedGenerator.cpp | 1 + .../optimized-thermal-generator/Main/OptimizedGenerator.h | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.cpp index bdb0069c6e..340fde64da 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.cpp @@ -38,6 +38,7 @@ void OptimizedThermalGenerator::GenerateOptimizedThermalTimeSeries() optSett.isFirstStep = false; } par.postScenarioOptimization(optSett); + ++progression_; printMaintenances(optSett); // to be removed printAvailability(optSett); // to be removed } diff --git a/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.h index 79149bddf1..9a1ba878b8 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.h @@ -141,7 +141,7 @@ class OptimizedThermalGenerator : public GeneratorTempData // MPSolver instance MPSolver solver; double solverInfinity; - + Solver::Progression::Task& progression_; /* ===================END-CLASS-VARIABLES=================== */ public: @@ -153,6 +153,7 @@ class OptimizedThermalGenerator : public GeneratorTempData IResultWriter& writer) : GeneratorTempData(study, progr, writer), maintenanceGroup_(maintenanceGroup), + progression_(progr), par(study, maintenanceGroup, globalThermalTSgeneration, vars, scenarioResults, progr, writer), solver(MPSolver("MaintenancePlanning", MPSolver::CBC_MIXED_INTEGER_PROGRAMMING)) { From 257ca6a50c049c25ea7efed9e372176b1eefbc10 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Fri, 1 Dec 2023 09:32:20 +0100 Subject: [PATCH 245/315] move print results to OptPar --- .../Main/OptimizedGenerator.cpp | 2 -- .../Main/OptimizedGenerator.h | 9 ----- .../Optimization/PrintProblemVarRes.cpp | 34 +++++++++---------- .../Optimization/SolveProbem.cpp | 2 +- .../Parameters/OptimizationParameters.h | 9 +++++ .../PostScenarioOptimization.cpp | 2 ++ 6 files changed, 29 insertions(+), 29 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.cpp index 340fde64da..c2177c9b26 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.cpp @@ -39,8 +39,6 @@ void OptimizedThermalGenerator::GenerateOptimizedThermalTimeSeries() } par.postScenarioOptimization(optSett); ++progression_; - printMaintenances(optSett); // to be removed - printAvailability(optSett); // to be removed } writeTsResults(); } diff --git a/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.h index 9a1ba878b8..7c3af5f5f4 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.h @@ -106,15 +106,6 @@ class OptimizedThermalGenerator : public GeneratorTempData // reset problem and variable structure void resetProblem(); - // print functions for debugging - void printAllVariables(); - void printObjectiveFunction(MPObjective* objective); - void printConstraints(); - void printResults(OptProblemSettings& optSett); - void printProblemVarAndResults(OptProblemSettings& optSett); - void printMaintenances(OptProblemSettings& optSett); - void printAvailability(OptProblemSettings& optSett); - /* ===================END-OPTIMIZATION=================== */ /* ===================MAIN=================== */ diff --git a/src/solver/ts-generator/optimized-thermal-generator/Optimization/PrintProblemVarRes.cpp b/src/solver/ts-generator/optimized-thermal-generator/Optimization/PrintProblemVarRes.cpp index 03a1f87112..f93a05e16b 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Optimization/PrintProblemVarRes.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/Optimization/PrintProblemVarRes.cpp @@ -12,15 +12,15 @@ namespace Antares::Solver::TSGenerator { -void OptimizedThermalGenerator::printProblemVarAndResults(OptProblemSettings& optSett) +void OptimizationParameters::printProblemVarAndResults(OptProblemSettings& optSett, MPSolver& solver) { - printAllVariables(); - printConstraints(); - printObjectiveFunction(solver.MutableObjective()); - printResults(optSett); + printAllVariables(solver); + printConstraints(solver); + printObjectiveFunction(solver.MutableObjective(), solver); + printResults(optSett, solver); } -void OptimizedThermalGenerator::printAllVariables() +void OptimizationParameters::printAllVariables(MPSolver& solver) { std::vector> dataToPrint; @@ -42,7 +42,7 @@ void OptimizedThermalGenerator::printAllVariables() return; } -void OptimizedThermalGenerator::printConstraints() +void OptimizationParameters::printConstraints(MPSolver& solver) { const int num_constraints = solver.NumConstraints(); std::vector> dataToPrint; @@ -82,7 +82,7 @@ void OptimizedThermalGenerator::printConstraints() "/home/milos/Documents/RTEi/01-Antares/04-TestModels/REFACTOR-CR27-Constraints.csv"); } -void OptimizedThermalGenerator::printObjectiveFunction(MPObjective* objective) +void OptimizationParameters::printObjectiveFunction(MPObjective* objective, MPSolver& solver) { std::vector> dataToPrint; for (MPVariable* variable : solver.variables()) @@ -100,22 +100,22 @@ void OptimizedThermalGenerator::printObjectiveFunction(MPObjective* objective) return; } -void OptimizedThermalGenerator::printResults(OptProblemSettings& optSett) +void OptimizationParameters::printResults(OptProblemSettings& optSett, MPSolver& solver) { std::vector> dataToPrint; // loop per day - for (auto day = 0; day != vars.ens.size(); ++day) + for (auto day = 0; day != vars_.ens.size(); ++day) { // row vector std::vector RED; // ens and spill - RED.push_back(vars.ens[day]->solution_value()); - RED.push_back(vars.spill[day]->solution_value()); + RED.push_back(vars_.ens[day]->solution_value()); + RED.push_back(vars_.spill[day]->solution_value()); // powers + start/end - for (const auto& unit : vars.clusterUnits) + for (const auto& unit : vars_.clusterUnits) { // powers if (unit.P[day] != nullptr) @@ -143,10 +143,10 @@ void OptimizedThermalGenerator::printResults(OptProblemSettings& optSett) return; } -void OptimizedThermalGenerator::printMaintenances(OptProblemSettings& optSett) +void OptimizationParameters::printMaintenances(OptProblemSettings& optSett) { std::vector> dataToPrint; - for (auto& unit : scenarioResults) + for (auto& unit : scenarioResults_) { std::vector RED; RED.push_back(9999); @@ -167,14 +167,14 @@ void OptimizedThermalGenerator::printMaintenances(OptProblemSettings& optSett) printColumnToFile(dataToPrint, fileName); } -void OptimizedThermalGenerator::printAvailability(OptProblemSettings& optSett) +void OptimizationParameters::printAvailability(OptProblemSettings& optSett) { std::vector> dataToPrint; for (int day = 0; day != scenarioLength_ * 365; ++day) { std::vector RED; - for (auto& cluster : par.clusterData) + for (auto& cluster : clusterData) { RED.push_back(cluster.second.dynamicResults.availableDailyPower[day]); } diff --git a/src/solver/ts-generator/optimized-thermal-generator/Optimization/SolveProbem.cpp b/src/solver/ts-generator/optimized-thermal-generator/Optimization/SolveProbem.cpp index b7230ba986..f1a1f15d99 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Optimization/SolveProbem.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/Optimization/SolveProbem.cpp @@ -16,7 +16,7 @@ bool OptimizedThermalGenerator::runOptimizationProblem(OptProblemSettings& optSe setProblemCost(optSett); if (!solveProblem(optSett)) return false; - printProblemVarAndResults(optSett); + par.printProblemVarAndResults(optSett, solver); // to be removed par.postTimeStepOptimization(optSett); return true; } diff --git a/src/solver/ts-generator/optimized-thermal-generator/Parameters/OptimizationParameters.h b/src/solver/ts-generator/optimized-thermal-generator/Parameters/OptimizationParameters.h index 249b2af63d..d6a361c0f1 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Parameters/OptimizationParameters.h +++ b/src/solver/ts-generator/optimized-thermal-generator/Parameters/OptimizationParameters.h @@ -156,6 +156,15 @@ class OptimizationParameters : public GeneratorTempData void reSetTimeHorizon(); /* ===================END-POST-OPTIMIZATION=================== */ + + /* ===================PRINT-DEBUG-ONLY-TO-BE-REMOVED=================== */ + void printAllVariables(MPSolver& solver); + void printObjectiveFunction(MPObjective* objective, MPSolver& solver); + void printConstraints(MPSolver& solver); + void printResults(OptProblemSettings& optSett,MPSolver& solver); + void printProblemVarAndResults(OptProblemSettings& optSett, MPSolver& solver); + void printMaintenances(OptProblemSettings& optSett); + void printAvailability(OptProblemSettings& optSett); }; } // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostScenarioOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostScenarioOptimization.cpp index 230017ea35..b4b6c8d961 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostScenarioOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostScenarioOptimization.cpp @@ -15,6 +15,8 @@ void OptimizationParameters::postScenarioOptimization(OptProblemSettings& optSet calculateScenarioResults(); saveScenarioResults(optSett); + printMaintenances(optSett); // to be removed + printAvailability(optSett); // to be removed resetResultStorage(); reSetDaysSinceLastMnt(); reSetTimeHorizon(); From 26f83f6f6376deb077ce0d96179a3f8e49703a20 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Fri, 1 Dec 2023 09:34:37 +0100 Subject: [PATCH 246/315] clang --- .../Parameters/OptimizationParameters.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/Parameters/OptimizationParameters.h b/src/solver/ts-generator/optimized-thermal-generator/Parameters/OptimizationParameters.h index d6a361c0f1..2170f13d1b 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Parameters/OptimizationParameters.h +++ b/src/solver/ts-generator/optimized-thermal-generator/Parameters/OptimizationParameters.h @@ -161,7 +161,7 @@ class OptimizationParameters : public GeneratorTempData void printAllVariables(MPSolver& solver); void printObjectiveFunction(MPObjective* objective, MPSolver& solver); void printConstraints(MPSolver& solver); - void printResults(OptProblemSettings& optSett,MPSolver& solver); + void printResults(OptProblemSettings& optSett, MPSolver& solver); void printProblemVarAndResults(OptProblemSettings& optSett, MPSolver& solver); void printMaintenances(OptProblemSettings& optSett); void printAvailability(OptProblemSettings& optSett); From 15f7c09d4949f19bba9e4413a34961216fe8143a Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Fri, 1 Dec 2023 09:43:03 +0100 Subject: [PATCH 247/315] refactor - simplify Unit::startDay method --- .../Aux/AuxillaryStructures.cpp | 23 ++++--------------- .../Aux/AuxillaryStructures.h | 1 - 2 files changed, 5 insertions(+), 19 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/Aux/AuxillaryStructures.cpp b/src/solver/ts-generator/optimized-thermal-generator/Aux/AuxillaryStructures.cpp index 78a482dcf4..22496a2130 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Aux/AuxillaryStructures.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/Aux/AuxillaryStructures.cpp @@ -13,15 +13,14 @@ int Maintenances::startDay(int limit) const // if no 1, return -1 // because 0 is a valid output - maintenance starts on first day - auto vector = getStartSolutionValues(); - - for (int i = 0; i < vector.size(); ++i) + for (int day = 0; day < start.size(); ++day) { - if (vector[i] == 1) + int value = static_cast(start[day]->solution_value()); + if (value == 1) { - if (i < limit) + if (day < limit) { - return i; + return day; } else { @@ -32,18 +31,6 @@ int Maintenances::startDay(int limit) const return -1; } -std::vector Maintenances::getStartSolutionValues() const -{ - std::vector solutionValues; - - for (const auto& variable : start) - { - solutionValues.push_back(static_cast(variable->solution_value())); - } - - return solutionValues; -} - void Unit::calculateAvailableDailyPower(int tsCount) { int totalDays = tsCount * DAYS_PER_YEAR; diff --git a/src/solver/ts-generator/optimized-thermal-generator/Aux/AuxillaryStructures.h b/src/solver/ts-generator/optimized-thermal-generator/Aux/AuxillaryStructures.h index e190dffc19..599180d7b7 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Aux/AuxillaryStructures.h +++ b/src/solver/ts-generator/optimized-thermal-generator/Aux/AuxillaryStructures.h @@ -34,7 +34,6 @@ struct Maintenances // methods int startDay(int limit) const; - std::vector getStartSolutionValues() const; }; struct Unit From 6dcb6bb9378b9a9894b219416554ec53eebc1999 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Fri, 1 Dec 2023 09:58:47 +0100 Subject: [PATCH 248/315] refactor in order of call --- .../Parameters/OptimizationParameters.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/Parameters/OptimizationParameters.h b/src/solver/ts-generator/optimized-thermal-generator/Parameters/OptimizationParameters.h index 2170f13d1b..f30c0d376e 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Parameters/OptimizationParameters.h +++ b/src/solver/ts-generator/optimized-thermal-generator/Parameters/OptimizationParameters.h @@ -152,8 +152,8 @@ class OptimizationParameters : public GeneratorTempData void saveScenarioResults(int fromCol, int toCol, Data::ThermalCluster& cluster); void resetResultStorage(); void reSetDaysSinceLastMnt(); - void reSetNumberOfMaintenances(); void reSetTimeHorizon(); + void reSetNumberOfMaintenances(); /* ===================END-POST-OPTIMIZATION=================== */ From 42422566c1a3b450b8e4e59567dafa34fe70f2b9 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Fri, 1 Dec 2023 12:20:05 +0100 Subject: [PATCH 249/315] fix crash when optimize-maintenance = false do not calculate and recalculate start/end parameters --- .../Parameters/CalculateParameters.cpp | 11 +++++++++++ .../Parameters/CalculateParametersPerCluster.cpp | 3 +++ .../Parameters/OptimizationParameters.h | 1 + .../PostOptimization/PostTimeStepOptimization.cpp | 3 +++ 4 files changed, 18 insertions(+) diff --git a/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParameters.cpp b/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParameters.cpp index a0f58aa7f5..64ae4441f6 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParameters.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParameters.cpp @@ -23,6 +23,11 @@ void OptimizationParameters::allocateClusterData() // create struct clusterData[&cluster] = ClusterData(); + clusterData[&cluster].maintenanceEnabled + = (cluster.doWeGenerateTS(globalThermalTSgeneration_) && cluster.optimizeMaintenance); + clusterData[&cluster].staticInputs = StaticInputs(); + clusterData[&cluster].dynamicInputs = DynamicInputs(); + clusterData[&cluster].dynamicResults = DynamicResults(); } } } @@ -40,6 +45,10 @@ void OptimizationParameters::calculateNonDependantClusterData() // cause their values are used for calculating other parameters data.staticInputs.maxPower = calculateMaxUnitOutput(cluster); data.staticInputs.avgCost = calculateAvrUnitDailyCost(cluster); + + if (!data.maintenanceEnabled) + continue; + data.staticInputs.averageMaintenanceDuration = calculateAverageMaintenanceDuration(cluster); // static inputs for random generator prepareIndispoFromLaw(cluster.plannedLaw, @@ -180,6 +189,8 @@ void OptimizationParameters::calculateDependantClusterData() auto& data = clusterEntry.second; const auto& cluster = *(clusterEntry.first); + if (!data.maintenanceEnabled) + continue; /* calculateNumberOfMaintenances uses: averageMaintenanceDuration diff --git a/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParametersPerCluster.cpp b/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParametersPerCluster.cpp index 1da2befe2f..70b8baf952 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParametersPerCluster.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParametersPerCluster.cpp @@ -50,6 +50,9 @@ std::vector OptimizationParameters::calculateNumberOfMaintenances( std::vector numberOfMaintenances; numberOfMaintenances.resize(cluster.unitCount); + if (!(cluster.doWeGenerateTS(globalThermalTSgeneration_) && cluster.optimizeMaintenance)) + return numberOfMaintenances; + for (int unit = 0; unit != cluster.unitCount; ++unit) { int div = (timeHorizon_ + getDaysSinceLastMaintenance(cluster, unit) diff --git a/src/solver/ts-generator/optimized-thermal-generator/Parameters/OptimizationParameters.h b/src/solver/ts-generator/optimized-thermal-generator/Parameters/OptimizationParameters.h index f30c0d376e..735170128c 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Parameters/OptimizationParameters.h +++ b/src/solver/ts-generator/optimized-thermal-generator/Parameters/OptimizationParameters.h @@ -54,6 +54,7 @@ struct DynamicResults struct ClusterData { + bool maintenanceEnabled; StaticInputs staticInputs; DynamicInputs dynamicInputs; DynamicResults dynamicResults; diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostTimeStepOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostTimeStepOptimization.cpp index 25e681b126..a1c0c6448d 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostTimeStepOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostTimeStepOptimization.cpp @@ -94,6 +94,9 @@ void OptimizationParameters::reCalculateDaysSinceLastMnt(const OptProblemSetting void OptimizationParameters::reCalculateDaysSinceLastMnt(const OptProblemSettings& optSett, const Unit& unit) { + if (!unit.createStartEndVariables) + return; + auto& daysSinceLastMaintenance = clusterData[unit.parentCluster].dynamicInputs.daysSinceLastMaintenance[unit.index]; bool maintenanceHappened = false; From 781f75b139ee4a86aef1d56c40f1dc23c044c3ae Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Fri, 1 Dec 2023 12:59:43 +0100 Subject: [PATCH 250/315] remove duplicate function definition --- .../PostScenarioOptimization.cpp | 35 ------------------- 1 file changed, 35 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostScenarioOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostScenarioOptimization.cpp index b4b6c8d961..dadd9a917b 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostScenarioOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostScenarioOptimization.cpp @@ -175,39 +175,4 @@ void OptimizationParameters::reSetNumberOfMaintenances() return; } -// this method is called at the very end -// after all time-steps and scenarios -void OptimizedThermalGenerator::writeTsResults() -{ - // we need to loop through all the clusters - // and write the results - // it would be much easier to loop using clusterData - // inside of it we already excluded all the non-important clusters - // however it is const Data::ThermalCluster* - // so we cannot modify cluster values - - for (auto& entryWeightMap : maintenanceGroup_) - { - auto& area = *(entryWeightMap.first); - - for (auto& clusterEntry : area.thermal.list.mapping) - { - auto& cluster = *(clusterEntry.second); - - if (!(checkClusterExist(cluster) && cluster.doWeGenerateTS(globalThermalTSgeneration_) - && cluster.optimizeMaintenance)) - continue; - - if (derated) - cluster.series.timeSeries.averageTimeseries(); - - if (archive) - writeResultsToDisk(area, cluster); - - cluster.calculationOfSpinning(); - } - } - return; -} - } // namespace Antares::Solver::TSGenerator From f26136c6c9d69dbb650640411485c4cc79e2d8c0 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Thu, 7 Dec 2023 11:50:59 +0100 Subject: [PATCH 251/315] add limitations --- .../Parameters/CalculateParameters.cpp | 4 ++-- .../Parameters/CalculateParametersPerCluster.cpp | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParameters.cpp b/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParameters.cpp index 64ae4441f6..b8eadd436f 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParameters.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParameters.cpp @@ -231,7 +231,7 @@ void OptimizationParameters::setMaintenanceGroupParameters() bool OptimizationParameters::checkMaintenanceGroupParameters() { - if (timeStep_ == 0) + if (timeStep_ <= 0) { logs.info() << "Maintenance group: " << maintenanceGroup_.name() << ": The timeseries generation will be skiped: timeStep = 0. It is possible " @@ -239,7 +239,7 @@ bool OptimizationParameters::checkMaintenanceGroupParameters() "planning, or at least one cluster has interPoPeriod = 0"; return false; } - if (timeHorizon_ == 0) + if (timeHorizon_ <= 0) { logs.info() << "Maintenance group: " << maintenanceGroup_.name() diff --git a/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParametersPerCluster.cpp b/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParametersPerCluster.cpp index 70b8baf952..4d3d43d3d1 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParametersPerCluster.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParametersPerCluster.cpp @@ -15,8 +15,9 @@ int OptimizationParameters::calculateUnitEarliestStartOfFirstMaintenance( // let it return negative value - if it returns negative value we wont implement constraint: // s[u][0][tauLower-1] = 0 - return (getAverageDurationBetweenMaintenances(cluster) - - getDaysSinceLastMaintenance(cluster, unitIndex) - cluster.poWindows); + return std::min(getAverageDurationBetweenMaintenances(cluster) + - getDaysSinceLastMaintenance(cluster, unitIndex) - cluster.poWindows, + timeHorizon_ - 1); } int OptimizationParameters::calculateUnitLatestStartOfFirstMaintenance( @@ -59,8 +60,7 @@ std::vector OptimizationParameters::calculateNumberOfMaintenances( - getAverageDurationBetweenMaintenances(cluster)) / (getAverageDurationBetweenMaintenances(cluster) + getAverageMaintenanceDuration(cluster)); - numberOfMaintenances[unit] = std::max( - 1 + div, minNumberOfMaintenances); // TODO CR27: keep here min=2 did not see it in python + numberOfMaintenances[unit] = std::max(1 + div, minNumberOfMaintenances); } return numberOfMaintenances; From 0e91a6ae6a6bcbc8382867a3a219323041f9cdd1 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Thu, 7 Dec 2023 12:09:25 +0100 Subject: [PATCH 252/315] check timeHorizon after each step --- .../Optimization/SolveProbem.cpp | 2 +- .../Parameters/CalculateParameters.cpp | 20 ++++++++++++++----- .../Parameters/OptimizationParameters.h | 1 + 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/Optimization/SolveProbem.cpp b/src/solver/ts-generator/optimized-thermal-generator/Optimization/SolveProbem.cpp index f1a1f15d99..4abf71bbd2 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Optimization/SolveProbem.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/Optimization/SolveProbem.cpp @@ -18,7 +18,7 @@ bool OptimizedThermalGenerator::runOptimizationProblem(OptProblemSettings& optSe return false; par.printProblemVarAndResults(optSett, solver); // to be removed par.postTimeStepOptimization(optSett); - return true; + return par.checkTimeHorizon(optSett); } // retrieve and check the results if optimization was successful diff --git a/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParameters.cpp b/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParameters.cpp index b8eadd436f..37c2345ffd 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParameters.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParameters.cpp @@ -241,15 +241,25 @@ bool OptimizationParameters::checkMaintenanceGroupParameters() } if (timeHorizon_ <= 0) { - logs.info() - << "Maintenance group: " << maintenanceGroup_.name() - << ": The timeseries generation will be skiped: timeHorizon = 0. It is possible " - "that the maintenance group has no clusters designated for maintenance " - "planning, or all clusters have interPoPeriod = 0"; + logs.info() << "Maintenance group: " << maintenanceGroup_.name() + << ": The timeseries generation will be skiped: timeHorizon <= 0"; return false; } // add some more check here if necessary! return true; } +bool OptimizationParameters::checkTimeHorizon(OptProblemSettings& optSett) +{ + if (timeHorizon_ <= 0) + { + logs.info() << "Maintenance group: " << maintenanceGroup_.name() + << ": The timeseries generation will be skiped: timeHorizon <= 0"; + optSett.solved = false; + return false; + } + + return true; +} + } // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/Parameters/OptimizationParameters.h b/src/solver/ts-generator/optimized-thermal-generator/Parameters/OptimizationParameters.h index 735170128c..c0e14ee4ba 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Parameters/OptimizationParameters.h +++ b/src/solver/ts-generator/optimized-thermal-generator/Parameters/OptimizationParameters.h @@ -144,6 +144,7 @@ class OptimizationParameters : public GeneratorTempData int lastMaintenanceDuration); void reCalculateTimeHorizon(); void reCalculateNumberOfMaintenances(); + bool checkTimeHorizon(OptProblemSettings& optSett); /* ===================AFTER-EACH-SCENARIO=================== */ From 5fe09e1e0f72216e723c404539fbeafdf09a61c3 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Thu, 7 Dec 2023 14:15:32 +0100 Subject: [PATCH 253/315] let daysSinceLast maintenance goes into negative value --- .../PostOptimization/PostTimeStepOptimization.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostTimeStepOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostTimeStepOptimization.cpp index a1c0c6448d..765264b6a5 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostTimeStepOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostTimeStepOptimization.cpp @@ -125,12 +125,10 @@ int OptimizationParameters::reCalculateDaysSinceLastMnt(const OptProblemSettings { int nextOptimizationFirstDay = optSett.firstDay + timeStep_; if (maintenanceHappened) - return std::max( - 0, nextOptimizationFirstDay - (lastMaintenanceStart + lastMaintenanceDuration)); + return (nextOptimizationFirstDay - (lastMaintenanceStart + lastMaintenanceDuration)); // we let this go into negative value // it will only move the maintenance in the next optimization // further away from start - // TODO CR27: no we don't! It broke the solver - we keep std::max for now! else return nextOptimizationFirstDay + unit.parentCluster->originalRandomlyGeneratedDaysSinceLastMaintenance[unit.index]; From 6ed802e1b65af449349cab07749a7d7ea04ee147 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Thu, 7 Dec 2023 14:35:39 +0100 Subject: [PATCH 254/315] make wrong parameters warning - improve log --- .../Parameters/CalculateParameters.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParameters.cpp b/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParameters.cpp index 37c2345ffd..f50b1730ba 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParameters.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParameters.cpp @@ -233,7 +233,7 @@ bool OptimizationParameters::checkMaintenanceGroupParameters() { if (timeStep_ <= 0) { - logs.info() << "Maintenance group: " << maintenanceGroup_.name() + logs.warning() << "Maintenance group: " << maintenanceGroup_.name() << ": The timeseries generation will be skiped: timeStep = 0. It is possible " "that the maintenance group has no clusters designated for maintenance " "planning, or at least one cluster has interPoPeriod = 0"; @@ -241,7 +241,7 @@ bool OptimizationParameters::checkMaintenanceGroupParameters() } if (timeHorizon_ <= 0) { - logs.info() << "Maintenance group: " << maintenanceGroup_.name() + logs.warning() << "Maintenance group: " << maintenanceGroup_.name() << ": The timeseries generation will be skiped: timeHorizon <= 0"; return false; } @@ -253,8 +253,10 @@ bool OptimizationParameters::checkTimeHorizon(OptProblemSettings& optSett) { if (timeHorizon_ <= 0) { - logs.info() << "Maintenance group: " << maintenanceGroup_.name() - << ": The timeseries generation will be skiped: timeHorizon <= 0"; + logs.warning() << "Maintenance group: " << maintenanceGroup_.name() + << ". Scenario Num: " << optSett.scenario + << ". Optimization stopped in step: " << optSett.firstDay << ".Day - " + << optSett.lastDay << ".Day. TimeHorizon <= 0 "; optSett.solved = false; return false; } From ae4337245f1563e7f1e8223c0e8917d0963e90b7 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Thu, 7 Dec 2023 14:48:45 +0100 Subject: [PATCH 255/315] improve logs --- .../Parameters/CalculateParameters.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParameters.cpp b/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParameters.cpp index f50b1730ba..4d7986da6f 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParameters.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParameters.cpp @@ -256,7 +256,8 @@ bool OptimizationParameters::checkTimeHorizon(OptProblemSettings& optSett) logs.warning() << "Maintenance group: " << maintenanceGroup_.name() << ". Scenario Num: " << optSett.scenario << ". Optimization stopped in step: " << optSett.firstDay << ".Day - " - << optSett.lastDay << ".Day. TimeHorizon <= 0 "; + << optSett.lastDay + << ".Day. TimeHorizon <= 0. This scenario wont have generated timeseries"; optSett.solved = false; return false; } From 457f5b8d1a2ec4495adb85602db9c6ad51c0d8b1 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Thu, 7 Dec 2023 16:14:47 +0100 Subject: [PATCH 256/315] bounds-> ct (better solver behavior) --- .../Optimization/SetVariableBounds.cpp | 37 ++++++++++++++++--- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/Optimization/SetVariableBounds.cpp b/src/solver/ts-generator/optimized-thermal-generator/Optimization/SetVariableBounds.cpp index 9f5a6253cf..3825cbe538 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Optimization/SetVariableBounds.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/Optimization/SetVariableBounds.cpp @@ -43,21 +43,36 @@ void OptimizedThermalGenerator::fixBoundsFirstMnt(const Unit& unit) = par.calculateUnitEarliestStartOfFirstMaintenance(*(unit.parentCluster), unit.index); int latestStartOfFirstMaintenance = par.calculateUnitLatestStartOfFirstMaintenance(*(unit.parentCluster), unit.index); - + const auto& cluster = *(unit.parentCluster); + std::string ctName; // // We assume here that vector "maintenance" has member [0] // meaning: for each unit we assume we have at least one maintenance // this assumption is ok - since method calculateNumberOfMaintenances() // will never return number bellow 2 + // we will fix the bounds using new constrains + // I tried to avoid adding new constraints to the problem + // by fixing variables bounds ->SetBounds + // but it worked fine for some cases and for some other crashed the solver + // so safer option is with new constraints + if (earliestStartOfFirstMaintenance >= 1) { // start[u][0][tauLower-1] = 0 - unit.maintenances[0].start[earliestStartOfFirstMaintenance - 1]->SetBounds(0.0, 0.0); + // unit.maintenances[0].start[earliestStartOfFirstMaintenance - 1]->SetBounds(0.0, 0.0); + ctName = "start[u][0][tauLower-1] = 0 -> [" + cluster.getFullName().to() + "." + + std::to_string(unit.index) + "]"; + MPConstraint* ct = solver.MakeRowConstraint(0., 0., ctName); + ct->SetCoefficient(unit.maintenances[0].start[earliestStartOfFirstMaintenance - 1], 1.0); } // start[u][0][tauUpper] = 1 - unit.maintenances[0].start[latestStartOfFirstMaintenance]->SetBounds(1.0, 1.0); + // unit.maintenances[0].start[latestStartOfFirstMaintenance]->SetBounds(1.0, 1.0); + ctName = "start[u][0][tauUpper] = 1 -> [" + cluster.getFullName().to() + "." + + std::to_string(unit.index) + "]"; + MPConstraint* ct = solver.MakeRowConstraint(1.0, 1.0, ctName); + ct->SetCoefficient(unit.maintenances[0].start[latestStartOfFirstMaintenance], 1.0); return; } @@ -78,7 +93,12 @@ void OptimizedThermalGenerator::fixBounds(const Unit& unit, int averageMaintenan // start[u][q][T] = 1 void OptimizedThermalGenerator::fixBoundsStartSecondMnt(const Unit& unit, int mnt) { - unit.maintenances[mnt].start[par.timeHorizon_ - 1]->SetBounds(1.0, 1.0); + // unit.maintenances[mnt].start[par.timeHorizon_ - 1]->SetBounds(1.0, 1.0); + const auto& cluster = *(unit.parentCluster); + std::string ctName = "start[u][q][T] = 1 -> [" + cluster.getFullName().to() + "." + + std::to_string(unit.index) + "][" + std::to_string(mnt) + "][T]"; + MPConstraint* ct = solver.MakeRowConstraint(1.0, 1.0, ctName); + ct->SetCoefficient(unit.maintenances[mnt].start[par.timeHorizon_ - 1], 1.0); } // End of the maintenance can't happen before average maintenance duration @@ -87,9 +107,16 @@ void OptimizedThermalGenerator::fixBoundsMntEnd(const Unit& unit, int mnt, int averageMaintenanceDuration) { + const auto& cluster = *(unit.parentCluster); + std::string ctName; for (int day = 0; day < averageMaintenanceDuration; ++day) { - unit.maintenances[mnt].end[day]->SetBounds(0.0, 0.0); + // unit.maintenances[mnt].end[day]->SetBounds(0.0, 0.0); + ctName = "end[u][q][T = [0-average_maintenance_duration_per_unit]] = 0 -> [" + + cluster.getFullName().to() + "." + std::to_string(unit.index) + "][" + + std::to_string(mnt) + "][" + std::to_string(day) + "]"; + MPConstraint* ct = solver.MakeRowConstraint(0.0, 0.0, ctName); + ct->SetCoefficient(unit.maintenances[mnt].end[day], 1.0); } } From bd5171e330367eeb96493cccfe6f995639b48430 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Thu, 7 Dec 2023 17:13:23 +0100 Subject: [PATCH 257/315] fix - postScenarioOptimization after crash --- .../PostOptimization/PostScenarioOptimization.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostScenarioOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostScenarioOptimization.cpp index dadd9a917b..3d0e1aa789 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostScenarioOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostScenarioOptimization.cpp @@ -10,13 +10,14 @@ namespace Antares::Solver::TSGenerator void OptimizationParameters::postScenarioOptimization(OptProblemSettings& optSett) { // do not save if optimization failed at some step - if (!optSett.solved) - return; + if (optSett.solved) + { + calculateScenarioResults(); + saveScenarioResults(optSett); + printMaintenances(optSett); // to be removed + printAvailability(optSett); // to be removed + } - calculateScenarioResults(); - saveScenarioResults(optSett); - printMaintenances(optSett); // to be removed - printAvailability(optSett); // to be removed resetResultStorage(); reSetDaysSinceLastMnt(); reSetTimeHorizon(); From 7e65e89ed80bcfd431184844db3def6673a06830 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Fri, 8 Dec 2023 00:19:23 +0100 Subject: [PATCH 258/315] fix - calc number of maintenances - exclude edge case --- .../Parameters/CalculateParametersPerCluster.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParametersPerCluster.cpp b/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParametersPerCluster.cpp index 4d3d43d3d1..2a90726289 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParametersPerCluster.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParametersPerCluster.cpp @@ -61,6 +61,19 @@ std::vector OptimizationParameters::calculateNumberOfMaintenances( / (getAverageDurationBetweenMaintenances(cluster) + getAverageMaintenanceDuration(cluster)); numberOfMaintenances[unit] = std::max(1 + div, minNumberOfMaintenances); + + // Exclude Edge case: + // first maintenance starts in day 0 + last maintenance starts last day of Horizon + // and breaks the solver - can only happen for number of maintenances > 2 + int earliestStart + = std::max(0, calculateUnitEarliestStartOfFirstMaintenance(cluster, unit)); + int lastMaintenanceStart = earliestStart + + (numberOfMaintenances[unit] - 1) + * (getAverageDurationBetweenMaintenances(cluster) + + getAverageMaintenanceDuration(cluster)); + + if (lastMaintenanceStart >= timeHorizon_) + numberOfMaintenances[unit]--; } return numberOfMaintenances; From 66a0b39f4259071aaeb1310469ae20ecd1966d75 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Fri, 8 Dec 2023 00:24:18 +0100 Subject: [PATCH 259/315] Revert "let daysSinceLast maintenance goes into negative value" This reverts commit 5fe09e1e0f72216e723c404539fbeafdf09a61c3. --- .../PostOptimization/PostTimeStepOptimization.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostTimeStepOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostTimeStepOptimization.cpp index 765264b6a5..a1c0c6448d 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostTimeStepOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostTimeStepOptimization.cpp @@ -125,10 +125,12 @@ int OptimizationParameters::reCalculateDaysSinceLastMnt(const OptProblemSettings { int nextOptimizationFirstDay = optSett.firstDay + timeStep_; if (maintenanceHappened) - return (nextOptimizationFirstDay - (lastMaintenanceStart + lastMaintenanceDuration)); + return std::max( + 0, nextOptimizationFirstDay - (lastMaintenanceStart + lastMaintenanceDuration)); // we let this go into negative value // it will only move the maintenance in the next optimization // further away from start + // TODO CR27: no we don't! It broke the solver - we keep std::max for now! else return nextOptimizationFirstDay + unit.parentCluster->originalRandomlyGeneratedDaysSinceLastMaintenance[unit.index]; From 9788ccb0d11f5d3f12c31c0ef23dfc63007acd34 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Mon, 11 Dec 2023 10:28:25 +0100 Subject: [PATCH 260/315] fix - std::min(averageDurationBetweenMaintenances - 1, daysSinceLastMaintenance) --- .../Parameters/CalculateParameters.cpp | 3 ++- .../Parameters/CalculateParametersPerCluster.cpp | 10 ++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParameters.cpp b/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParameters.cpp index 4d7986da6f..b7fef9dad3 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParameters.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParameters.cpp @@ -166,7 +166,8 @@ int OptimizationParameters::calculateTimeHorizon() { int value = 2 * getAverageDurationBetweenMaintenances(cluster) + getAverageMaintenanceDuration(cluster) - - getDaysSinceLastMaintenance(cluster, unit); + - std::min(getAverageDurationBetweenMaintenances(cluster) - 1, + getDaysSinceLastMaintenance(cluster, unit)); timeHorizonVector.push_back(value); } } diff --git a/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParametersPerCluster.cpp b/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParametersPerCluster.cpp index 2a90726289..2d868aae3b 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParametersPerCluster.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParametersPerCluster.cpp @@ -56,15 +56,17 @@ std::vector OptimizationParameters::calculateNumberOfMaintenances( for (int unit = 0; unit != cluster.unitCount; ++unit) { - int div = (timeHorizon_ + getDaysSinceLastMaintenance(cluster, unit) + int div = (timeHorizon_ + + std::min(getAverageDurationBetweenMaintenances(cluster) - 1, + getDaysSinceLastMaintenance(cluster, unit)) - getAverageDurationBetweenMaintenances(cluster)) / (getAverageDurationBetweenMaintenances(cluster) + getAverageMaintenanceDuration(cluster)); numberOfMaintenances[unit] = std::max(1 + div, minNumberOfMaintenances); - // Exclude Edge case: - // first maintenance starts in day 0 + last maintenance starts last day of Horizon - // and breaks the solver - can only happen for number of maintenances > 2 + // Exclude Edge cases: + // the above fix should take care of this + // but leave it for now till I am 100% sure! int earliestStart = std::max(0, calculateUnitEarliestStartOfFirstMaintenance(cluster, unit)); int lastMaintenanceStart = earliestStart From baa72c48e069721b8229c8983c6bc779d31172f5 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Mon, 11 Dec 2023 23:41:14 +0100 Subject: [PATCH 261/315] add pre-check - ts num in simulation must equal sc.len*sc.num --- .../antares/checks/antares/checks/checkLoadedInputData.h | 1 + src/libs/antares/checks/checkLoadedInputData.cpp | 8 ++++++++ src/libs/antares/exception/LoadingError.cpp | 6 ++++++ .../antares/exception/antares/exception/LoadingError.hpp | 6 ++++++ src/solver/application.cpp | 1 + 5 files changed, 22 insertions(+) diff --git a/src/libs/antares/checks/antares/checks/checkLoadedInputData.h b/src/libs/antares/checks/antares/checks/checkLoadedInputData.h index f1950db360..781ab7d56e 100644 --- a/src/libs/antares/checks/antares/checks/checkLoadedInputData.h +++ b/src/libs/antares/checks/antares/checks/checkLoadedInputData.h @@ -47,5 +47,6 @@ void checkFuelCostColumnNumber(const Antares::Data::AreaList& areas); void checkCO2CostColumnNumber(const Antares::Data::AreaList& areas); void checkMaintenancePlanningSettings(const Antares::Data::Parameters* parameters); +void checkMaintenancePlanningTsNum(const Antares::Data::Parameters* parameters); } // namespace Antares::Check diff --git a/src/libs/antares/checks/checkLoadedInputData.cpp b/src/libs/antares/checks/checkLoadedInputData.cpp index 53c0e15208..70fe67dac6 100644 --- a/src/libs/antares/checks/checkLoadedInputData.cpp +++ b/src/libs/antares/checks/checkLoadedInputData.cpp @@ -219,4 +219,12 @@ void checkMaintenancePlanningSettings(const Antares::Data::Parameters* parameter throw Error::IncompatibleMaintenancePlanningUsage(); } +void checkMaintenancePlanningTsNum(const Antares::Data::Parameters* parameters) +{ + if (parameters->maintenancePlanning.getScenarioLength() + * parameters->maintenancePlanning.getScenarioNumber() + != parameters->nbTimeSeriesThermal) + throw Error::IncompatibleMaintenancePlanningTsNum(); +} + } // namespace Antares::Check diff --git a/src/libs/antares/exception/LoadingError.cpp b/src/libs/antares/exception/LoadingError.cpp index 99f38ec8f5..f9534b83d1 100644 --- a/src/libs/antares/exception/LoadingError.cpp +++ b/src/libs/antares/exception/LoadingError.cpp @@ -172,5 +172,11 @@ IncompatibleMaintenancePlanningUsage::IncompatibleMaintenancePlanningUsage() : { } +IncompatibleMaintenancePlanningTsNum::IncompatibleMaintenancePlanningTsNum() : + LoadingError("When generating thermal time series using Maintenance Planning, scenario length " + "* scenario number must be equal to number of thermal ts in Stochastic TS") +{ +} + } // namespace Error } // namespace Antares diff --git a/src/libs/antares/exception/antares/exception/LoadingError.hpp b/src/libs/antares/exception/antares/exception/LoadingError.hpp index 322602d9dc..87925d64cd 100644 --- a/src/libs/antares/exception/antares/exception/LoadingError.hpp +++ b/src/libs/antares/exception/antares/exception/LoadingError.hpp @@ -227,5 +227,11 @@ class IncompatibleMaintenancePlanningUsage : public LoadingError IncompatibleMaintenancePlanningUsage(); }; +class IncompatibleMaintenancePlanningTsNum : public LoadingError +{ +public: + IncompatibleMaintenancePlanningTsNum(); +}; + } // namespace Error } // namespace Antares diff --git a/src/solver/application.cpp b/src/solver/application.cpp index 467ff74c1a..2da18f031e 100644 --- a/src/solver/application.cpp +++ b/src/solver/application.cpp @@ -165,6 +165,7 @@ void Application::prepare(int argc, char* argv[]) checkCO2CostColumnNumber(pStudy->areas); checkMaintenancePlanningSettings(pParameters); + checkMaintenancePlanningTsNum(pParameters); // Start the progress meter pStudy->initializeProgressMeter(pSettings.tsGeneratorsOnly); From 04cf6d2e64edb9689c6df5752537a4d50ab0850a Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 12 Dec 2023 00:27:39 +0100 Subject: [PATCH 262/315] fix - check --- src/libs/antares/checks/checkLoadedInputData.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/libs/antares/checks/checkLoadedInputData.cpp b/src/libs/antares/checks/checkLoadedInputData.cpp index 70fe67dac6..59733f6b87 100644 --- a/src/libs/antares/checks/checkLoadedInputData.cpp +++ b/src/libs/antares/checks/checkLoadedInputData.cpp @@ -221,9 +221,14 @@ void checkMaintenancePlanningSettings(const Antares::Data::Parameters* parameter void checkMaintenancePlanningTsNum(const Antares::Data::Parameters* parameters) { - if (parameters->maintenancePlanning.getScenarioLength() - * parameters->maintenancePlanning.getScenarioNumber() - != parameters->nbTimeSeriesThermal) + bool activeThermalTSGenAndMntPlanning + = (parameters->maintenancePlanning.isOptimized() + && (parameters->timeSeriesToGenerate & Antares::Data::timeSeriesThermal)); + + if (activeThermalTSGenAndMntPlanning + && parameters->maintenancePlanning.getScenarioLength() + * parameters->maintenancePlanning.getScenarioNumber() + != parameters->nbTimeSeriesThermal) throw Error::IncompatibleMaintenancePlanningTsNum(); } From 210e6b83e3dff49c2cd4c8b48bf3675a1b9c91e5 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 12 Dec 2023 00:56:30 +0100 Subject: [PATCH 263/315] Revert "bounds-> ct (better solver behavior)" This reverts commit 457f5b8d1a2ec4495adb85602db9c6ad51c0d8b1. --- .../Optimization/SetVariableBounds.cpp | 37 +++---------------- 1 file changed, 5 insertions(+), 32 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/Optimization/SetVariableBounds.cpp b/src/solver/ts-generator/optimized-thermal-generator/Optimization/SetVariableBounds.cpp index 3825cbe538..9f5a6253cf 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Optimization/SetVariableBounds.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/Optimization/SetVariableBounds.cpp @@ -43,36 +43,21 @@ void OptimizedThermalGenerator::fixBoundsFirstMnt(const Unit& unit) = par.calculateUnitEarliestStartOfFirstMaintenance(*(unit.parentCluster), unit.index); int latestStartOfFirstMaintenance = par.calculateUnitLatestStartOfFirstMaintenance(*(unit.parentCluster), unit.index); - const auto& cluster = *(unit.parentCluster); - std::string ctName; + // // We assume here that vector "maintenance" has member [0] // meaning: for each unit we assume we have at least one maintenance // this assumption is ok - since method calculateNumberOfMaintenances() // will never return number bellow 2 - // we will fix the bounds using new constrains - // I tried to avoid adding new constraints to the problem - // by fixing variables bounds ->SetBounds - // but it worked fine for some cases and for some other crashed the solver - // so safer option is with new constraints - if (earliestStartOfFirstMaintenance >= 1) { // start[u][0][tauLower-1] = 0 - // unit.maintenances[0].start[earliestStartOfFirstMaintenance - 1]->SetBounds(0.0, 0.0); - ctName = "start[u][0][tauLower-1] = 0 -> [" + cluster.getFullName().to() + "." - + std::to_string(unit.index) + "]"; - MPConstraint* ct = solver.MakeRowConstraint(0., 0., ctName); - ct->SetCoefficient(unit.maintenances[0].start[earliestStartOfFirstMaintenance - 1], 1.0); + unit.maintenances[0].start[earliestStartOfFirstMaintenance - 1]->SetBounds(0.0, 0.0); } // start[u][0][tauUpper] = 1 - // unit.maintenances[0].start[latestStartOfFirstMaintenance]->SetBounds(1.0, 1.0); - ctName = "start[u][0][tauUpper] = 1 -> [" + cluster.getFullName().to() + "." - + std::to_string(unit.index) + "]"; - MPConstraint* ct = solver.MakeRowConstraint(1.0, 1.0, ctName); - ct->SetCoefficient(unit.maintenances[0].start[latestStartOfFirstMaintenance], 1.0); + unit.maintenances[0].start[latestStartOfFirstMaintenance]->SetBounds(1.0, 1.0); return; } @@ -93,12 +78,7 @@ void OptimizedThermalGenerator::fixBounds(const Unit& unit, int averageMaintenan // start[u][q][T] = 1 void OptimizedThermalGenerator::fixBoundsStartSecondMnt(const Unit& unit, int mnt) { - // unit.maintenances[mnt].start[par.timeHorizon_ - 1]->SetBounds(1.0, 1.0); - const auto& cluster = *(unit.parentCluster); - std::string ctName = "start[u][q][T] = 1 -> [" + cluster.getFullName().to() + "." - + std::to_string(unit.index) + "][" + std::to_string(mnt) + "][T]"; - MPConstraint* ct = solver.MakeRowConstraint(1.0, 1.0, ctName); - ct->SetCoefficient(unit.maintenances[mnt].start[par.timeHorizon_ - 1], 1.0); + unit.maintenances[mnt].start[par.timeHorizon_ - 1]->SetBounds(1.0, 1.0); } // End of the maintenance can't happen before average maintenance duration @@ -107,16 +87,9 @@ void OptimizedThermalGenerator::fixBoundsMntEnd(const Unit& unit, int mnt, int averageMaintenanceDuration) { - const auto& cluster = *(unit.parentCluster); - std::string ctName; for (int day = 0; day < averageMaintenanceDuration; ++day) { - // unit.maintenances[mnt].end[day]->SetBounds(0.0, 0.0); - ctName = "end[u][q][T = [0-average_maintenance_duration_per_unit]] = 0 -> [" - + cluster.getFullName().to() + "." + std::to_string(unit.index) + "][" - + std::to_string(mnt) + "][" + std::to_string(day) + "]"; - MPConstraint* ct = solver.MakeRowConstraint(0.0, 0.0, ctName); - ct->SetCoefficient(unit.maintenances[mnt].end[day], 1.0); + unit.maintenances[mnt].end[day]->SetBounds(0.0, 0.0); } } From 0555850cd96596acaf568cd96601b78727b4c16e Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 12 Dec 2023 19:05:34 +0100 Subject: [PATCH 264/315] clean redundant checks --- .../Parameters/CalculateParametersPerCluster.cpp | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParametersPerCluster.cpp b/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParametersPerCluster.cpp index 2d868aae3b..bd9c6663fb 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParametersPerCluster.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParametersPerCluster.cpp @@ -63,19 +63,6 @@ std::vector OptimizationParameters::calculateNumberOfMaintenances( / (getAverageDurationBetweenMaintenances(cluster) + getAverageMaintenanceDuration(cluster)); numberOfMaintenances[unit] = std::max(1 + div, minNumberOfMaintenances); - - // Exclude Edge cases: - // the above fix should take care of this - // but leave it for now till I am 100% sure! - int earliestStart - = std::max(0, calculateUnitEarliestStartOfFirstMaintenance(cluster, unit)); - int lastMaintenanceStart = earliestStart - + (numberOfMaintenances[unit] - 1) - * (getAverageDurationBetweenMaintenances(cluster) - + getAverageMaintenanceDuration(cluster)); - - if (lastMaintenanceStart >= timeHorizon_) - numberOfMaintenances[unit]--; } return numberOfMaintenances; From ff04e3d2d04138d2459ad6b15c969f7af4312b58 Mon Sep 17 00:00:00 2001 From: NikolaIlic Date: Wed, 13 Dec 2023 14:39:09 +0100 Subject: [PATCH 265/315] Update cleaner --- src/libs/antares/study/cleaner/cleaner-v20.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libs/antares/study/cleaner/cleaner-v20.cpp b/src/libs/antares/study/cleaner/cleaner-v20.cpp index a0f4dea784..eae7b0ebe7 100644 --- a/src/libs/antares/study/cleaner/cleaner-v20.cpp +++ b/src/libs/antares/study/cleaner/cleaner-v20.cpp @@ -260,6 +260,7 @@ bool listOfFilesAnDirectoriesToKeep(StudyCleaningInfos* infos) e.add("settings/constraintbuilder.ini"); e.add("settings/scenariobuilder.dat"); e.add("input/bindingconstraints/bindingconstraints.ini"); + e.add("input/maintenanceplanning/maintenancegroups.ini"); e.add("input/hydro/hydro.ini"); e.add("input/areas/list.txt"); e.add("input/areas/sets.ini"); @@ -311,6 +312,7 @@ bool listOfFilesAnDirectoriesToKeep(StudyCleaningInfos* infos) p.add("settings/resources"); p.add("settings/simulations"); p.add("input/bindingconstraints"); + p.add("input/maintenanceplanning"); // Getting all areas auto* arealist = new AreaList(*study); From 49e414395c40c08fc61c5fc99d50d37720769b97 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Thu, 14 Dec 2023 13:38:18 +0100 Subject: [PATCH 266/315] fix time horizon. Add +1 ( when po.win = 0) --- .../Parameters/CalculateParameters.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParameters.cpp b/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParameters.cpp index b7fef9dad3..e39d344d5c 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParameters.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParameters.cpp @@ -167,7 +167,7 @@ int OptimizationParameters::calculateTimeHorizon() int value = 2 * getAverageDurationBetweenMaintenances(cluster) + getAverageMaintenanceDuration(cluster) - std::min(getAverageDurationBetweenMaintenances(cluster) - 1, - getDaysSinceLastMaintenance(cluster, unit)); + getDaysSinceLastMaintenance(cluster, unit)) + 1; timeHorizonVector.push_back(value); } } From 51b483aa1e48dee1ef270c3b81e9d83daff3a282 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Thu, 14 Dec 2023 17:43:25 +0100 Subject: [PATCH 267/315] small improve cause of +1 in timeHorizon --- .../Parameters/CalculateParameters.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParameters.cpp b/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParameters.cpp index e39d344d5c..0885771e5b 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParameters.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParameters.cpp @@ -166,8 +166,9 @@ int OptimizationParameters::calculateTimeHorizon() { int value = 2 * getAverageDurationBetweenMaintenances(cluster) + getAverageMaintenanceDuration(cluster) - - std::min(getAverageDurationBetweenMaintenances(cluster) - 1, - getDaysSinceLastMaintenance(cluster, unit)) + 1; + - std::min(getAverageDurationBetweenMaintenances(cluster), + getDaysSinceLastMaintenance(cluster, unit)) + + 1; timeHorizonVector.push_back(value); } } From f55f333e60065dc3633264de6ee2d4d32d36a8ec Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 19 Dec 2023 13:02:12 +0100 Subject: [PATCH 268/315] move printColumnToFile to aux --- .../optimized-thermal-generator/Aux/AuxillaryFreeFunctions.h | 5 +++++ .../optimized-thermal-generator/Main/OptimizedGenerator.h | 5 ----- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/Aux/AuxillaryFreeFunctions.h b/src/solver/ts-generator/optimized-thermal-generator/Aux/AuxillaryFreeFunctions.h index eb09bd0180..d8760ca14c 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Aux/AuxillaryFreeFunctions.h +++ b/src/solver/ts-generator/optimized-thermal-generator/Aux/AuxillaryFreeFunctions.h @@ -31,4 +31,9 @@ int calculateAverageMaintenanceDuration(const Data::ThermalCluster& cluster); std::array calculateMaxUnitOutput(const Data::ThermalCluster& cluster); std::array calculateAvrUnitDailyCost(const Data::ThermalCluster& cluster); +// Declare the auxiliary function outside the class +// Debug & Test purpose - to be removed +template +void printColumnToFile(const std::vector>& data, const std::string& filename); + } // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.h index 7c3af5f5f4..c7f67bd860 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.h @@ -177,9 +177,4 @@ class OptimizedThermalGenerator : public GeneratorTempData void GenerateOptimizedThermalTimeSeries(); }; -// Declare the auxiliary function outside the class -// Debug & Test purpose - to be removed -template -void printColumnToFile(const std::vector>& data, const std::string& filename); - } // namespace Antares::Solver::TSGenerator \ No newline at end of file From 236fb3600b8ca5654b9be5400e6abe35cb759762 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 19 Dec 2023 13:06:43 +0100 Subject: [PATCH 269/315] remove printing --- .../optimized-thermal-generator/Optimization/SolveProbem.cpp | 1 - .../PostOptimization/PostScenarioOptimization.cpp | 2 -- 2 files changed, 3 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/Optimization/SolveProbem.cpp b/src/solver/ts-generator/optimized-thermal-generator/Optimization/SolveProbem.cpp index 4abf71bbd2..cf9685d13e 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Optimization/SolveProbem.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/Optimization/SolveProbem.cpp @@ -16,7 +16,6 @@ bool OptimizedThermalGenerator::runOptimizationProblem(OptProblemSettings& optSe setProblemCost(optSett); if (!solveProblem(optSett)) return false; - par.printProblemVarAndResults(optSett, solver); // to be removed par.postTimeStepOptimization(optSett); return par.checkTimeHorizon(optSett); } diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostScenarioOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostScenarioOptimization.cpp index 3d0e1aa789..f856de9ef6 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostScenarioOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostScenarioOptimization.cpp @@ -14,8 +14,6 @@ void OptimizationParameters::postScenarioOptimization(OptProblemSettings& optSet { calculateScenarioResults(); saveScenarioResults(optSett); - printMaintenances(optSett); // to be removed - printAvailability(optSett); // to be removed } resetResultStorage(); From e9f592d5a84b19c8c64e507dd61248ece84e10d8 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 19 Dec 2023 14:29:32 +0100 Subject: [PATCH 270/315] use lowercase for folder names --- src/solver/simulation/solver.hxx | 2 +- src/solver/ts-generator/CMakeLists.txt | 44 ++--- .../PostTimeStepOptimization.cpp | 2 +- .../{Aux => aux}/AuxillaryFreeFunctions.cpp | 4 +- .../{Aux => aux}/AuxillaryFreeFunctions.h | 2 +- .../{Aux => aux}/AuxillaryStructures.cpp | 0 .../{Aux => aux}/AuxillaryStructures.h | 0 .../{Aux => aux}/pre-scenario-builder.cpp | 0 .../{Aux => aux}/pre-scenario-builder.h | 0 .../{Main => main}/OptimizedGenerator.cpp | 0 .../{Main => main}/OptimizedGenerator.h | 6 +- .../CreateVariables.cpp | 2 +- .../PrintProblemVarRes.cpp | 2 +- .../ResetProblem.cpp | 2 +- .../SetProblemConstraints.cpp | 2 +- .../SetProblemCost.cpp | 2 +- .../SetVariableBounds.cpp | 2 +- .../SolveProbem.cpp | 2 +- .../CalculateParameters.cpp | 2 +- .../CalculateParametersPerCluster.cpp | 2 +- .../{Parameters => parameters}/Getters.cpp | 2 +- .../OptimizationParameters.h | 2 +- .../PostScenarioOptimization.cpp | 2 +- .../PostTimeStepOptimization.cpp | 154 ++++++++++++++++++ .../WriteResults.cpp | 2 +- src/solver/ts-generator/thermal.cpp | 2 +- 26 files changed, 198 insertions(+), 44 deletions(-) rename src/solver/ts-generator/optimized-thermal-generator/{Aux => aux}/AuxillaryFreeFunctions.cpp (98%) rename src/solver/ts-generator/optimized-thermal-generator/{Aux => aux}/AuxillaryFreeFunctions.h (97%) rename src/solver/ts-generator/optimized-thermal-generator/{Aux => aux}/AuxillaryStructures.cpp (100%) rename src/solver/ts-generator/optimized-thermal-generator/{Aux => aux}/AuxillaryStructures.h (100%) rename src/solver/ts-generator/optimized-thermal-generator/{Aux => aux}/pre-scenario-builder.cpp (100%) rename src/solver/ts-generator/optimized-thermal-generator/{Aux => aux}/pre-scenario-builder.h (100%) rename src/solver/ts-generator/optimized-thermal-generator/{Main => main}/OptimizedGenerator.cpp (100%) rename src/solver/ts-generator/optimized-thermal-generator/{Main => main}/OptimizedGenerator.h (98%) rename src/solver/ts-generator/optimized-thermal-generator/{Optimization => optimization}/CreateVariables.cpp (99%) rename src/solver/ts-generator/optimized-thermal-generator/{Optimization => optimization}/PrintProblemVarRes.cpp (99%) rename src/solver/ts-generator/optimized-thermal-generator/{Optimization => optimization}/ResetProblem.cpp (89%) rename src/solver/ts-generator/optimized-thermal-generator/{Optimization => optimization}/SetProblemConstraints.cpp (99%) rename src/solver/ts-generator/optimized-thermal-generator/{Optimization => optimization}/SetProblemCost.cpp (97%) rename src/solver/ts-generator/optimized-thermal-generator/{Optimization => optimization}/SetVariableBounds.cpp (98%) rename src/solver/ts-generator/optimized-thermal-generator/{Optimization => optimization}/SolveProbem.cpp (96%) rename src/solver/ts-generator/optimized-thermal-generator/{Parameters => parameters}/CalculateParameters.cpp (99%) rename src/solver/ts-generator/optimized-thermal-generator/{Parameters => parameters}/CalculateParametersPerCluster.cpp (98%) rename src/solver/ts-generator/optimized-thermal-generator/{Parameters => parameters}/Getters.cpp (98%) rename src/solver/ts-generator/optimized-thermal-generator/{Parameters => parameters}/OptimizationParameters.h (99%) rename src/solver/ts-generator/optimized-thermal-generator/{PostOptimization => postoptimization}/PostScenarioOptimization.cpp (99%) create mode 100644 src/solver/ts-generator/optimized-thermal-generator/postoptimization/PostTimeStepOptimization.cpp rename src/solver/ts-generator/optimized-thermal-generator/{PostOptimization => postoptimization}/WriteResults.cpp (96%) diff --git a/src/solver/simulation/solver.hxx b/src/solver/simulation/solver.hxx index 8e5d9d9824..56ee766b09 100644 --- a/src/solver/simulation/solver.hxx +++ b/src/solver/simulation/solver.hxx @@ -40,7 +40,7 @@ #include "../ts-generator/generator.h" #include "opt_time_writer.h" #include "../hydro/management.h" // Added for use of randomReservoirLevel(...) -#include "../ts-generator/optimized-thermal-generator/Aux/pre-scenario-builder.h" +#include "../ts-generator/optimized-thermal-generator/aux/pre-scenario-builder.h" #include #include diff --git a/src/solver/ts-generator/CMakeLists.txt b/src/solver/ts-generator/CMakeLists.txt index ab64a18d3f..c6fd46c428 100644 --- a/src/solver/ts-generator/CMakeLists.txt +++ b/src/solver/ts-generator/CMakeLists.txt @@ -13,28 +13,28 @@ source_group("ts-generator\\randomized-thermal-generator" FILES ${SRC_RANDOMIZED # Optimized-thermal-ts-generator # set(SRC_OPTIMIZEDGENERATORS - optimized-thermal-generator/Aux/AuxillaryStructures.h - optimized-thermal-generator/Aux/AuxillaryStructures.cpp - optimized-thermal-generator/Aux/AuxillaryFreeFunctions.h - optimized-thermal-generator/Aux/AuxillaryFreeFunctions.cpp - optimized-thermal-generator/Aux/pre-scenario-builder.h - optimized-thermal-generator/Aux/pre-scenario-builder.cpp - optimized-thermal-generator/Main/OptimizedGenerator.h - optimized-thermal-generator/Main/OptimizedGenerator.cpp - optimized-thermal-generator/Parameters/OptimizationParameters.h - optimized-thermal-generator/Parameters/CalculateParameters.cpp - optimized-thermal-generator/Parameters/CalculateParametersPerCluster.cpp - optimized-thermal-generator/Parameters/Getters.cpp - optimized-thermal-generator/Optimization/CreateVariables.cpp - optimized-thermal-generator/Optimization/SetVariableBounds.cpp - optimized-thermal-generator/Optimization/SetProblemConstraints.cpp - optimized-thermal-generator/Optimization/SetProblemCost.cpp - optimized-thermal-generator/Optimization/ResetProblem.cpp - optimized-thermal-generator/Optimization/SolveProbem.cpp - optimized-thermal-generator/Optimization/PrintProblemVarRes.cpp - optimized-thermal-generator/PostOptimization/PostTimeStepOptimization.cpp - optimized-thermal-generator/PostOptimization/PostScenarioOptimization.cpp - optimized-thermal-generator/PostOptimization/WriteResults.cpp + optimized-thermal-generator/aux/AuxillaryStructures.h + optimized-thermal-generator/aux/AuxillaryStructures.cpp + optimized-thermal-generator/aux/AuxillaryFreeFunctions.h + optimized-thermal-generator/aux/AuxillaryFreeFunctions.cpp + optimized-thermal-generator/aux/pre-scenario-builder.h + optimized-thermal-generator/aux/pre-scenario-builder.cpp + optimized-thermal-generator/main/OptimizedGenerator.h + optimized-thermal-generator/main/OptimizedGenerator.cpp + optimized-thermal-generator/parameters/OptimizationParameters.h + optimized-thermal-generator/parameters/CalculateParameters.cpp + optimized-thermal-generator/parameters/CalculateParametersPerCluster.cpp + optimized-thermal-generator/parameters/Getters.cpp + optimized-thermal-generator/optimization/CreateVariables.cpp + optimized-thermal-generator/optimization/SetVariableBounds.cpp + optimized-thermal-generator/optimization/SetProblemConstraints.cpp + optimized-thermal-generator/optimization/SetProblemCost.cpp + optimized-thermal-generator/optimization/ResetProblem.cpp + optimized-thermal-generator/optimization/SolveProbem.cpp + optimized-thermal-generator/optimization/PrintProblemVarRes.cpp + optimized-thermal-generator/postoptimization/PostTimeStepOptimization.cpp + optimized-thermal-generator/postoptimization/PostScenarioOptimization.cpp + optimized-thermal-generator/postoptimization/WriteResults.cpp ) source_group("ts-generator\\optimized-thermal-generator" FILES ${SRC_OPTIMIZEDGENERATORS}) diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostTimeStepOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostTimeStepOptimization.cpp index a1c0c6448d..9752b832c2 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostTimeStepOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostTimeStepOptimization.cpp @@ -2,7 +2,7 @@ // Created by milos on 14/11/23. // -#include "../Main/OptimizedGenerator.h" +#include "../main/OptimizedGenerator.h" namespace Antares::Solver::TSGenerator { diff --git a/src/solver/ts-generator/optimized-thermal-generator/Aux/AuxillaryFreeFunctions.cpp b/src/solver/ts-generator/optimized-thermal-generator/aux/AuxillaryFreeFunctions.cpp similarity index 98% rename from src/solver/ts-generator/optimized-thermal-generator/Aux/AuxillaryFreeFunctions.cpp rename to src/solver/ts-generator/optimized-thermal-generator/aux/AuxillaryFreeFunctions.cpp index 48eb9c3009..4805cb94ff 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Aux/AuxillaryFreeFunctions.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/aux/AuxillaryFreeFunctions.cpp @@ -4,8 +4,8 @@ #include #include #include -#include "../Main/OptimizedGenerator.h" -#include "../Aux/AuxillaryFreeFunctions.h" +#include "../main/OptimizedGenerator.h" +#include "../aux/AuxillaryFreeFunctions.h" namespace Antares::Solver::TSGenerator { diff --git a/src/solver/ts-generator/optimized-thermal-generator/Aux/AuxillaryFreeFunctions.h b/src/solver/ts-generator/optimized-thermal-generator/aux/AuxillaryFreeFunctions.h similarity index 97% rename from src/solver/ts-generator/optimized-thermal-generator/Aux/AuxillaryFreeFunctions.h rename to src/solver/ts-generator/optimized-thermal-generator/aux/AuxillaryFreeFunctions.h index d8760ca14c..492d0236d0 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Aux/AuxillaryFreeFunctions.h +++ b/src/solver/ts-generator/optimized-thermal-generator/aux/AuxillaryFreeFunctions.h @@ -4,7 +4,7 @@ #pragma once -#include "../Main/OptimizedGenerator.h" +#include "../main/OptimizedGenerator.h" namespace Antares::Solver::TSGenerator { diff --git a/src/solver/ts-generator/optimized-thermal-generator/Aux/AuxillaryStructures.cpp b/src/solver/ts-generator/optimized-thermal-generator/aux/AuxillaryStructures.cpp similarity index 100% rename from src/solver/ts-generator/optimized-thermal-generator/Aux/AuxillaryStructures.cpp rename to src/solver/ts-generator/optimized-thermal-generator/aux/AuxillaryStructures.cpp diff --git a/src/solver/ts-generator/optimized-thermal-generator/Aux/AuxillaryStructures.h b/src/solver/ts-generator/optimized-thermal-generator/aux/AuxillaryStructures.h similarity index 100% rename from src/solver/ts-generator/optimized-thermal-generator/Aux/AuxillaryStructures.h rename to src/solver/ts-generator/optimized-thermal-generator/aux/AuxillaryStructures.h diff --git a/src/solver/ts-generator/optimized-thermal-generator/Aux/pre-scenario-builder.cpp b/src/solver/ts-generator/optimized-thermal-generator/aux/pre-scenario-builder.cpp similarity index 100% rename from src/solver/ts-generator/optimized-thermal-generator/Aux/pre-scenario-builder.cpp rename to src/solver/ts-generator/optimized-thermal-generator/aux/pre-scenario-builder.cpp diff --git a/src/solver/ts-generator/optimized-thermal-generator/Aux/pre-scenario-builder.h b/src/solver/ts-generator/optimized-thermal-generator/aux/pre-scenario-builder.h similarity index 100% rename from src/solver/ts-generator/optimized-thermal-generator/Aux/pre-scenario-builder.h rename to src/solver/ts-generator/optimized-thermal-generator/aux/pre-scenario-builder.h diff --git a/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/main/OptimizedGenerator.cpp similarity index 100% rename from src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.cpp rename to src/solver/ts-generator/optimized-thermal-generator/main/OptimizedGenerator.cpp diff --git a/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/main/OptimizedGenerator.h similarity index 98% rename from src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.h rename to src/solver/ts-generator/optimized-thermal-generator/main/OptimizedGenerator.h index c7f67bd860..e015aa09a7 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Main/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/main/OptimizedGenerator.h @@ -7,9 +7,9 @@ #include "ortools/linear_solver/linear_solver.h" #include "../../randomized-thermal-generator/RandomizedGenerator.h" #include "../../../../libs/antares/study/maintenance_planning/MaintenanceGroup.h" -#include "../Aux/AuxillaryStructures.h" -#include "../Aux/AuxillaryFreeFunctions.h" -#include "../Parameters/OptimizationParameters.h" +#include "../aux/AuxillaryStructures.h" +#include "../aux/AuxillaryFreeFunctions.h" +#include "../parameters/OptimizationParameters.h" #include // static const std::string mntPlSolverName = "cbc"; diff --git a/src/solver/ts-generator/optimized-thermal-generator/Optimization/CreateVariables.cpp b/src/solver/ts-generator/optimized-thermal-generator/optimization/CreateVariables.cpp similarity index 99% rename from src/solver/ts-generator/optimized-thermal-generator/Optimization/CreateVariables.cpp rename to src/solver/ts-generator/optimized-thermal-generator/optimization/CreateVariables.cpp index 6620dcce34..5fb78051de 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Optimization/CreateVariables.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/optimization/CreateVariables.cpp @@ -2,7 +2,7 @@ // Created by milos on 14/11/23. // -#include "../Main/OptimizedGenerator.h" +#include "../main/OptimizedGenerator.h" namespace Antares::Solver::TSGenerator { diff --git a/src/solver/ts-generator/optimized-thermal-generator/Optimization/PrintProblemVarRes.cpp b/src/solver/ts-generator/optimized-thermal-generator/optimization/PrintProblemVarRes.cpp similarity index 99% rename from src/solver/ts-generator/optimized-thermal-generator/Optimization/PrintProblemVarRes.cpp rename to src/solver/ts-generator/optimized-thermal-generator/optimization/PrintProblemVarRes.cpp index f93a05e16b..3306fcd039 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Optimization/PrintProblemVarRes.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/optimization/PrintProblemVarRes.cpp @@ -8,7 +8,7 @@ #include #include -#include "../Main/OptimizedGenerator.h" +#include "../main/OptimizedGenerator.h" namespace Antares::Solver::TSGenerator { diff --git a/src/solver/ts-generator/optimized-thermal-generator/Optimization/ResetProblem.cpp b/src/solver/ts-generator/optimized-thermal-generator/optimization/ResetProblem.cpp similarity index 89% rename from src/solver/ts-generator/optimized-thermal-generator/Optimization/ResetProblem.cpp rename to src/solver/ts-generator/optimized-thermal-generator/optimization/ResetProblem.cpp index 2e71b8c2aa..e58f1b298b 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Optimization/ResetProblem.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/optimization/ResetProblem.cpp @@ -2,7 +2,7 @@ // Created by milos on 14/11/23. // -#include "../Main/OptimizedGenerator.h" +#include "../main/OptimizedGenerator.h" namespace Antares::Solver::TSGenerator { diff --git a/src/solver/ts-generator/optimized-thermal-generator/Optimization/SetProblemConstraints.cpp b/src/solver/ts-generator/optimized-thermal-generator/optimization/SetProblemConstraints.cpp similarity index 99% rename from src/solver/ts-generator/optimized-thermal-generator/Optimization/SetProblemConstraints.cpp rename to src/solver/ts-generator/optimized-thermal-generator/optimization/SetProblemConstraints.cpp index 3e9bcb6a89..f7dd49b83d 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Optimization/SetProblemConstraints.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/optimization/SetProblemConstraints.cpp @@ -2,7 +2,7 @@ // Created by milos on 14/11/23. // -#include "../Main/OptimizedGenerator.h" +#include "../main/OptimizedGenerator.h" namespace Antares::Solver::TSGenerator { diff --git a/src/solver/ts-generator/optimized-thermal-generator/Optimization/SetProblemCost.cpp b/src/solver/ts-generator/optimized-thermal-generator/optimization/SetProblemCost.cpp similarity index 97% rename from src/solver/ts-generator/optimized-thermal-generator/Optimization/SetProblemCost.cpp rename to src/solver/ts-generator/optimized-thermal-generator/optimization/SetProblemCost.cpp index 12c3b15f65..d42cda55e2 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Optimization/SetProblemCost.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/optimization/SetProblemCost.cpp @@ -2,7 +2,7 @@ // Created by milos on 14/11/23. // -#include "../Main/OptimizedGenerator.h" +#include "../main/OptimizedGenerator.h" namespace Antares::Solver::TSGenerator { diff --git a/src/solver/ts-generator/optimized-thermal-generator/Optimization/SetVariableBounds.cpp b/src/solver/ts-generator/optimized-thermal-generator/optimization/SetVariableBounds.cpp similarity index 98% rename from src/solver/ts-generator/optimized-thermal-generator/Optimization/SetVariableBounds.cpp rename to src/solver/ts-generator/optimized-thermal-generator/optimization/SetVariableBounds.cpp index 9f5a6253cf..9bb4d7974e 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Optimization/SetVariableBounds.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/optimization/SetVariableBounds.cpp @@ -2,7 +2,7 @@ // Created by milos on 14/11/23. // -#include "../Main/OptimizedGenerator.h" +#include "../main/OptimizedGenerator.h" namespace Antares::Solver::TSGenerator { diff --git a/src/solver/ts-generator/optimized-thermal-generator/Optimization/SolveProbem.cpp b/src/solver/ts-generator/optimized-thermal-generator/optimization/SolveProbem.cpp similarity index 96% rename from src/solver/ts-generator/optimized-thermal-generator/Optimization/SolveProbem.cpp rename to src/solver/ts-generator/optimized-thermal-generator/optimization/SolveProbem.cpp index cf9685d13e..dada198ef5 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Optimization/SolveProbem.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/optimization/SolveProbem.cpp @@ -2,7 +2,7 @@ // Created by milos on 14/11/23. // -#include "../Main/OptimizedGenerator.h" +#include "../main/OptimizedGenerator.h" namespace Antares::Solver::TSGenerator { diff --git a/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParameters.cpp b/src/solver/ts-generator/optimized-thermal-generator/parameters/CalculateParameters.cpp similarity index 99% rename from src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParameters.cpp rename to src/solver/ts-generator/optimized-thermal-generator/parameters/CalculateParameters.cpp index 0885771e5b..d6f1a2c0b2 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParameters.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/parameters/CalculateParameters.cpp @@ -2,7 +2,7 @@ // Created by milos on 14/11/23. // -#include "../Main/OptimizedGenerator.h" +#include "../main/OptimizedGenerator.h" namespace Antares::Solver::TSGenerator { diff --git a/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParametersPerCluster.cpp b/src/solver/ts-generator/optimized-thermal-generator/parameters/CalculateParametersPerCluster.cpp similarity index 98% rename from src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParametersPerCluster.cpp rename to src/solver/ts-generator/optimized-thermal-generator/parameters/CalculateParametersPerCluster.cpp index bd9c6663fb..66fc38837c 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Parameters/CalculateParametersPerCluster.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/parameters/CalculateParametersPerCluster.cpp @@ -2,7 +2,7 @@ // Created by milos on 14/11/23. // -#include "../Main/OptimizedGenerator.h" +#include "../main/OptimizedGenerator.h" namespace Antares::Solver::TSGenerator { diff --git a/src/solver/ts-generator/optimized-thermal-generator/Parameters/Getters.cpp b/src/solver/ts-generator/optimized-thermal-generator/parameters/Getters.cpp similarity index 98% rename from src/solver/ts-generator/optimized-thermal-generator/Parameters/Getters.cpp rename to src/solver/ts-generator/optimized-thermal-generator/parameters/Getters.cpp index 9815b421f4..7f9cfba5f9 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Parameters/Getters.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/parameters/Getters.cpp @@ -2,7 +2,7 @@ // Created by milos on 14/11/23. // -#include "../Main/OptimizedGenerator.h" +#include "../main/OptimizedGenerator.h" namespace Antares::Solver::TSGenerator { diff --git a/src/solver/ts-generator/optimized-thermal-generator/Parameters/OptimizationParameters.h b/src/solver/ts-generator/optimized-thermal-generator/parameters/OptimizationParameters.h similarity index 99% rename from src/solver/ts-generator/optimized-thermal-generator/Parameters/OptimizationParameters.h rename to src/solver/ts-generator/optimized-thermal-generator/parameters/OptimizationParameters.h index c0e14ee4ba..f8704cf4e8 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/Parameters/OptimizationParameters.h +++ b/src/solver/ts-generator/optimized-thermal-generator/parameters/OptimizationParameters.h @@ -5,7 +5,7 @@ #pragma once #include "../../randomized-thermal-generator/RandomizedGenerator.h" -#include "../Main/OptimizedGenerator.h" +#include "../main/OptimizedGenerator.h" namespace Antares::Solver::TSGenerator { diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostScenarioOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/postoptimization/PostScenarioOptimization.cpp similarity index 99% rename from src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostScenarioOptimization.cpp rename to src/solver/ts-generator/optimized-thermal-generator/postoptimization/PostScenarioOptimization.cpp index f856de9ef6..ec28bd0b44 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostScenarioOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/postoptimization/PostScenarioOptimization.cpp @@ -2,7 +2,7 @@ // Created by milos on 14/11/23. // -#include "../Main/OptimizedGenerator.h" +#include "../main/OptimizedGenerator.h" namespace Antares::Solver::TSGenerator { diff --git a/src/solver/ts-generator/optimized-thermal-generator/postoptimization/PostTimeStepOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/postoptimization/PostTimeStepOptimization.cpp new file mode 100644 index 0000000000..9752b832c2 --- /dev/null +++ b/src/solver/ts-generator/optimized-thermal-generator/postoptimization/PostTimeStepOptimization.cpp @@ -0,0 +1,154 @@ +// +// Created by milos on 14/11/23. +// + +#include "../main/OptimizedGenerator.h" + +namespace Antares::Solver::TSGenerator +{ + +void OptimizationParameters::postTimeStepOptimization(OptProblemSettings& optSett) +{ + appendTimeStepResults(optSett); + reCalculateDaysSinceLastMnt(optSett); + reCalculateTimeHorizon(); + reCalculateNumberOfMaintenances(); + return; +} + +// save/append optimization results form range 0-timeStep +void OptimizationParameters::appendTimeStepResults(const OptProblemSettings& optSett) +{ + // we have vectors of start (zeros and ones) + // lets convert that into maintenance start day vector + // and then randomly generate maintenance duration + // and create std::pairs - of start_day + mnt_duration + + // loop per units + for (std::size_t unitIndexTotal = 0; unitIndexTotal < vars_.clusterUnits.size(); + ++unitIndexTotal) + { + // Unit-unitIndexTotal - is index in a vector of all the units (area * cluster * units) + // not to be confused by Unit-index - index in cluster + + // variables structure: vars and result structure: scenarioResults + // are created at the same time in the same loop + // so the order of the units should be the same !!! + // so lets avoid creating some search/find method + // that will find the Unit in scenarioResults according to its parentCluster and index + // and just loop + // assert parentCluster and index + + const auto& readResultUnit = vars_.clusterUnits[unitIndexTotal]; + auto& storeResultUnit = scenarioResults_[unitIndexTotal]; + + assert(readResultUnit.parentCluster == storeResultUnit.parentCluster + && "Read and Store Units do not point to the same parent cluster."); + assert(readResultUnit.index == storeResultUnit.index + && "Read and Store Units do not point to the same unit index."); + + auto& cluster = *(readResultUnit.parentCluster); + + // if createStartEndVariables for the readResultUnit is false + // maintenances.size() is going to be zero - so in a way there is our check + if (readResultUnit.maintenances.empty()) + continue; + + // NO need to loop through maintenances + // only one maintenance can happen in the timeStep_ + // TODO CR27: in phase-II we may change this and looping will be necessary + { + int localMaintenanceStart = readResultUnit.maintenances[0].startDay(timeStep_); + if (localMaintenanceStart == -1) + continue; + + int globalMaintenanceStart = localMaintenanceStart + optSett.firstDay; + int dayInTheYearStart = dayOfTheYear(globalMaintenanceStart); + + int PODOfTheDay + = (int)cluster.prepro->data[Data::PreproThermal::poDuration][dayInTheYearStart]; + double app = clusterData[&cluster].staticInputs.AP[dayInTheYearStart]; + double bpp = clusterData[&cluster].staticInputs.BP[dayInTheYearStart]; + int maintenanceDuration = durationGenerator( + cluster.plannedLaw, PODOfTheDay, cluster.plannedVolatility, app, bpp); + + storeResultUnit.maintenanceResults.push_back( + std::make_pair(globalMaintenanceStart, maintenanceDuration)); + } + } + + return; +} + +// re-calculate parameters + +void OptimizationParameters::reCalculateDaysSinceLastMnt(const OptProblemSettings& optSett) +{ + // re-calculate days since last maintenance inputs if necessary + for (const auto& unit : scenarioResults_) + { + reCalculateDaysSinceLastMnt(optSett, unit); + } +} + +void OptimizationParameters::reCalculateDaysSinceLastMnt(const OptProblemSettings& optSett, + const Unit& unit) +{ + if (!unit.createStartEndVariables) + return; + + auto& daysSinceLastMaintenance + = clusterData[unit.parentCluster].dynamicInputs.daysSinceLastMaintenance[unit.index]; + bool maintenanceHappened = false; + + if (unit.maintenanceResults.empty()) + { + daysSinceLastMaintenance + = reCalculateDaysSinceLastMnt(optSett, unit, maintenanceHappened, 0, 0); + return; + } + + maintenanceHappened = true; + int lastMaintenanceStart = unit.maintenanceResults.back().first; + int lastMaintenanceDuration = unit.maintenanceResults.back().second; + + daysSinceLastMaintenance = reCalculateDaysSinceLastMnt( + optSett, unit, maintenanceHappened, lastMaintenanceStart, lastMaintenanceDuration); + return; +} + +int OptimizationParameters::reCalculateDaysSinceLastMnt(const OptProblemSettings& optSett, + const Unit& unit, + bool maintenanceHappened, + int lastMaintenanceStart, + int lastMaintenanceDuration) +{ + int nextOptimizationFirstDay = optSett.firstDay + timeStep_; + if (maintenanceHappened) + return std::max( + 0, nextOptimizationFirstDay - (lastMaintenanceStart + lastMaintenanceDuration)); + // we let this go into negative value + // it will only move the maintenance in the next optimization + // further away from start + // TODO CR27: no we don't! It broke the solver - we keep std::max for now! + else + return nextOptimizationFirstDay + + unit.parentCluster->originalRandomlyGeneratedDaysSinceLastMaintenance[unit.index]; +} + +void OptimizationParameters::reCalculateTimeHorizon() +{ + timeHorizon_ = calculateTimeHorizon(); +} + +void OptimizationParameters::reCalculateNumberOfMaintenances() +{ + // re-calculate days since last maintenance inputs if necessary + for (auto& cluster : clusterData) + { + cluster.second.dynamicInputs.numberOfMaintenances + = calculateNumberOfMaintenances(*(cluster.first)); + } +} + +} // namespace Antares::Solver::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/WriteResults.cpp b/src/solver/ts-generator/optimized-thermal-generator/postoptimization/WriteResults.cpp similarity index 96% rename from src/solver/ts-generator/optimized-thermal-generator/PostOptimization/WriteResults.cpp rename to src/solver/ts-generator/optimized-thermal-generator/postoptimization/WriteResults.cpp index 69254e0237..95e5c61893 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/WriteResults.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/postoptimization/WriteResults.cpp @@ -2,7 +2,7 @@ // Created by milos on 14/11/23. // -#include "../Main/OptimizedGenerator.h" +#include "../main/OptimizedGenerator.h" namespace Antares::Solver::TSGenerator { diff --git a/src/solver/ts-generator/thermal.cpp b/src/solver/ts-generator/thermal.cpp index 413b3d62c1..074a2a0101 100644 --- a/src/solver/ts-generator/thermal.cpp +++ b/src/solver/ts-generator/thermal.cpp @@ -27,7 +27,7 @@ #include "../simulation/sim_extern_variables_globales.h" #include "randomized-thermal-generator/RandomizedGenerator.h" -#include "optimized-thermal-generator/Main/OptimizedGenerator.h" +#include "optimized-thermal-generator/main/OptimizedGenerator.h" namespace Antares::Solver::TSGenerator { From 130dc13527abba274f4f27b6ff9ddaf50294d806 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 19 Dec 2023 15:31:04 +0100 Subject: [PATCH 271/315] try fix - window build fail --- src/solver/ts-generator/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/solver/ts-generator/CMakeLists.txt b/src/solver/ts-generator/CMakeLists.txt index 0cbfe95ab7..3786890cd1 100644 --- a/src/solver/ts-generator/CMakeLists.txt +++ b/src/solver/ts-generator/CMakeLists.txt @@ -7,7 +7,7 @@ set(SRC_RANDOMIZEDGENERATORS randomized-thermal-generator/RandomizedGenerator.h randomized-thermal-generator/RandomizedGenerator.cpp ) -source_group("ts-generator\\randomized-thermal-generator" FILES ${SRC_RANDOMIZEDGENERATORS}) +source_group("ts-generator\\Randomized-thermal-generator" FILES ${SRC_RANDOMIZEDGENERATORS}) # # Optimized-thermal-ts-generator @@ -37,7 +37,7 @@ set(SRC_OPTIMIZEDGENERATORS optimized-thermal-generator/postoptimization/WriteResults.cpp ) -source_group("ts-generator\\optimized-thermal-generator" FILES ${SRC_OPTIMIZEDGENERATORS}) +source_group("ts-generator\\Optimized-thermal-generator" FILES ${SRC_OPTIMIZEDGENERATORS}) # # Time-Series Generators From 8fdbfc7e3b5bdc3ac3881ff069bb15cc88d0da41 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 19 Dec 2023 15:38:37 +0100 Subject: [PATCH 272/315] try fix - shorter name --- src/solver/ts-generator/CMakeLists.txt | 4 ++-- .../aux/{AuxillaryFreeFunctions.cpp => AuxFreeFun.cpp} | 2 +- .../aux/{AuxillaryFreeFunctions.h => AuxFreeFun.h} | 0 .../optimized-thermal-generator/main/OptimizedGenerator.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) rename src/solver/ts-generator/optimized-thermal-generator/aux/{AuxillaryFreeFunctions.cpp => AuxFreeFun.cpp} (99%) rename src/solver/ts-generator/optimized-thermal-generator/aux/{AuxillaryFreeFunctions.h => AuxFreeFun.h} (100%) diff --git a/src/solver/ts-generator/CMakeLists.txt b/src/solver/ts-generator/CMakeLists.txt index 3786890cd1..209159019a 100644 --- a/src/solver/ts-generator/CMakeLists.txt +++ b/src/solver/ts-generator/CMakeLists.txt @@ -15,8 +15,8 @@ source_group("ts-generator\\Randomized-thermal-generator" FILES ${SRC_RANDOMIZED set(SRC_OPTIMIZEDGENERATORS optimized-thermal-generator/aux/AuxillaryStructures.h optimized-thermal-generator/aux/AuxillaryStructures.cpp - optimized-thermal-generator/aux/AuxillaryFreeFunctions.h - optimized-thermal-generator/aux/AuxillaryFreeFunctions.cpp + optimized-thermal-generator/aux/AuxFreeFun.h + optimized-thermal-generator/aux/AuxFreeFun.cpp optimized-thermal-generator/aux/pre-scenario-builder.h optimized-thermal-generator/aux/pre-scenario-builder.cpp optimized-thermal-generator/main/OptimizedGenerator.h diff --git a/src/solver/ts-generator/optimized-thermal-generator/aux/AuxillaryFreeFunctions.cpp b/src/solver/ts-generator/optimized-thermal-generator/aux/AuxFreeFun.cpp similarity index 99% rename from src/solver/ts-generator/optimized-thermal-generator/aux/AuxillaryFreeFunctions.cpp rename to src/solver/ts-generator/optimized-thermal-generator/aux/AuxFreeFun.cpp index 4805cb94ff..45b24fd604 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/aux/AuxillaryFreeFunctions.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/aux/AuxFreeFun.cpp @@ -5,7 +5,7 @@ #include #include #include "../main/OptimizedGenerator.h" -#include "../aux/AuxillaryFreeFunctions.h" +#include "../aux/AuxFreeFun.h" namespace Antares::Solver::TSGenerator { diff --git a/src/solver/ts-generator/optimized-thermal-generator/aux/AuxillaryFreeFunctions.h b/src/solver/ts-generator/optimized-thermal-generator/aux/AuxFreeFun.h similarity index 100% rename from src/solver/ts-generator/optimized-thermal-generator/aux/AuxillaryFreeFunctions.h rename to src/solver/ts-generator/optimized-thermal-generator/aux/AuxFreeFun.h diff --git a/src/solver/ts-generator/optimized-thermal-generator/main/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/main/OptimizedGenerator.h index e015aa09a7..41fe73daf7 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/main/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/main/OptimizedGenerator.h @@ -8,7 +8,7 @@ #include "../../randomized-thermal-generator/RandomizedGenerator.h" #include "../../../../libs/antares/study/maintenance_planning/MaintenanceGroup.h" #include "../aux/AuxillaryStructures.h" -#include "../aux/AuxillaryFreeFunctions.h" +#include "../aux/AuxFreeFun.h" #include "../parameters/OptimizationParameters.h" #include From c123ef7eddfff09222acebadb37b6adc6065622a Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 19 Dec 2023 16:06:33 +0100 Subject: [PATCH 273/315] fix double file --- .../PostTimeStepOptimization.cpp | 154 ------------------ 1 file changed, 154 deletions(-) delete mode 100644 src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostTimeStepOptimization.cpp diff --git a/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostTimeStepOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostTimeStepOptimization.cpp deleted file mode 100644 index 9752b832c2..0000000000 --- a/src/solver/ts-generator/optimized-thermal-generator/PostOptimization/PostTimeStepOptimization.cpp +++ /dev/null @@ -1,154 +0,0 @@ -// -// Created by milos on 14/11/23. -// - -#include "../main/OptimizedGenerator.h" - -namespace Antares::Solver::TSGenerator -{ - -void OptimizationParameters::postTimeStepOptimization(OptProblemSettings& optSett) -{ - appendTimeStepResults(optSett); - reCalculateDaysSinceLastMnt(optSett); - reCalculateTimeHorizon(); - reCalculateNumberOfMaintenances(); - return; -} - -// save/append optimization results form range 0-timeStep -void OptimizationParameters::appendTimeStepResults(const OptProblemSettings& optSett) -{ - // we have vectors of start (zeros and ones) - // lets convert that into maintenance start day vector - // and then randomly generate maintenance duration - // and create std::pairs - of start_day + mnt_duration - - // loop per units - for (std::size_t unitIndexTotal = 0; unitIndexTotal < vars_.clusterUnits.size(); - ++unitIndexTotal) - { - // Unit-unitIndexTotal - is index in a vector of all the units (area * cluster * units) - // not to be confused by Unit-index - index in cluster - - // variables structure: vars and result structure: scenarioResults - // are created at the same time in the same loop - // so the order of the units should be the same !!! - // so lets avoid creating some search/find method - // that will find the Unit in scenarioResults according to its parentCluster and index - // and just loop - // assert parentCluster and index - - const auto& readResultUnit = vars_.clusterUnits[unitIndexTotal]; - auto& storeResultUnit = scenarioResults_[unitIndexTotal]; - - assert(readResultUnit.parentCluster == storeResultUnit.parentCluster - && "Read and Store Units do not point to the same parent cluster."); - assert(readResultUnit.index == storeResultUnit.index - && "Read and Store Units do not point to the same unit index."); - - auto& cluster = *(readResultUnit.parentCluster); - - // if createStartEndVariables for the readResultUnit is false - // maintenances.size() is going to be zero - so in a way there is our check - if (readResultUnit.maintenances.empty()) - continue; - - // NO need to loop through maintenances - // only one maintenance can happen in the timeStep_ - // TODO CR27: in phase-II we may change this and looping will be necessary - { - int localMaintenanceStart = readResultUnit.maintenances[0].startDay(timeStep_); - if (localMaintenanceStart == -1) - continue; - - int globalMaintenanceStart = localMaintenanceStart + optSett.firstDay; - int dayInTheYearStart = dayOfTheYear(globalMaintenanceStart); - - int PODOfTheDay - = (int)cluster.prepro->data[Data::PreproThermal::poDuration][dayInTheYearStart]; - double app = clusterData[&cluster].staticInputs.AP[dayInTheYearStart]; - double bpp = clusterData[&cluster].staticInputs.BP[dayInTheYearStart]; - int maintenanceDuration = durationGenerator( - cluster.plannedLaw, PODOfTheDay, cluster.plannedVolatility, app, bpp); - - storeResultUnit.maintenanceResults.push_back( - std::make_pair(globalMaintenanceStart, maintenanceDuration)); - } - } - - return; -} - -// re-calculate parameters - -void OptimizationParameters::reCalculateDaysSinceLastMnt(const OptProblemSettings& optSett) -{ - // re-calculate days since last maintenance inputs if necessary - for (const auto& unit : scenarioResults_) - { - reCalculateDaysSinceLastMnt(optSett, unit); - } -} - -void OptimizationParameters::reCalculateDaysSinceLastMnt(const OptProblemSettings& optSett, - const Unit& unit) -{ - if (!unit.createStartEndVariables) - return; - - auto& daysSinceLastMaintenance - = clusterData[unit.parentCluster].dynamicInputs.daysSinceLastMaintenance[unit.index]; - bool maintenanceHappened = false; - - if (unit.maintenanceResults.empty()) - { - daysSinceLastMaintenance - = reCalculateDaysSinceLastMnt(optSett, unit, maintenanceHappened, 0, 0); - return; - } - - maintenanceHappened = true; - int lastMaintenanceStart = unit.maintenanceResults.back().first; - int lastMaintenanceDuration = unit.maintenanceResults.back().second; - - daysSinceLastMaintenance = reCalculateDaysSinceLastMnt( - optSett, unit, maintenanceHappened, lastMaintenanceStart, lastMaintenanceDuration); - return; -} - -int OptimizationParameters::reCalculateDaysSinceLastMnt(const OptProblemSettings& optSett, - const Unit& unit, - bool maintenanceHappened, - int lastMaintenanceStart, - int lastMaintenanceDuration) -{ - int nextOptimizationFirstDay = optSett.firstDay + timeStep_; - if (maintenanceHappened) - return std::max( - 0, nextOptimizationFirstDay - (lastMaintenanceStart + lastMaintenanceDuration)); - // we let this go into negative value - // it will only move the maintenance in the next optimization - // further away from start - // TODO CR27: no we don't! It broke the solver - we keep std::max for now! - else - return nextOptimizationFirstDay - + unit.parentCluster->originalRandomlyGeneratedDaysSinceLastMaintenance[unit.index]; -} - -void OptimizationParameters::reCalculateTimeHorizon() -{ - timeHorizon_ = calculateTimeHorizon(); -} - -void OptimizationParameters::reCalculateNumberOfMaintenances() -{ - // re-calculate days since last maintenance inputs if necessary - for (auto& cluster : clusterData) - { - cluster.second.dynamicInputs.numberOfMaintenances - = calculateNumberOfMaintenances(*(cluster.first)); - } -} - -} // namespace Antares::Solver::TSGenerator From d78f2e28fb6ba057bc945f220aefc1bed8e57cb4 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 19 Dec 2023 16:21:13 +0100 Subject: [PATCH 274/315] do not use aux folder name --- src/solver/simulation/solver.hxx | 2 +- src/solver/ts-generator/CMakeLists.txt | 12 ++++++------ .../{aux => auxillary}/AuxFreeFun.cpp | 2 +- .../{aux => auxillary}/AuxFreeFun.h | 0 .../{aux => auxillary}/AuxillaryStructures.cpp | 0 .../{aux => auxillary}/AuxillaryStructures.h | 0 .../{aux => auxillary}/pre-scenario-builder.cpp | 0 .../{aux => auxillary}/pre-scenario-builder.h | 0 .../main/OptimizedGenerator.h | 4 ++-- 9 files changed, 10 insertions(+), 10 deletions(-) rename src/solver/ts-generator/optimized-thermal-generator/{aux => auxillary}/AuxFreeFun.cpp (99%) rename src/solver/ts-generator/optimized-thermal-generator/{aux => auxillary}/AuxFreeFun.h (100%) rename src/solver/ts-generator/optimized-thermal-generator/{aux => auxillary}/AuxillaryStructures.cpp (100%) rename src/solver/ts-generator/optimized-thermal-generator/{aux => auxillary}/AuxillaryStructures.h (100%) rename src/solver/ts-generator/optimized-thermal-generator/{aux => auxillary}/pre-scenario-builder.cpp (100%) rename src/solver/ts-generator/optimized-thermal-generator/{aux => auxillary}/pre-scenario-builder.h (100%) diff --git a/src/solver/simulation/solver.hxx b/src/solver/simulation/solver.hxx index 54a219625e..06f906ed4f 100644 --- a/src/solver/simulation/solver.hxx +++ b/src/solver/simulation/solver.hxx @@ -40,7 +40,7 @@ #include "../ts-generator/generator.h" #include "opt_time_writer.h" #include "../hydro/management.h" // Added for use of randomReservoirLevel(...) -#include "../ts-generator/optimized-thermal-generator/aux/pre-scenario-builder.h" +#include "../ts-generator/optimized-thermal-generator/auxillary/pre-scenario-builder.h" #include #include diff --git a/src/solver/ts-generator/CMakeLists.txt b/src/solver/ts-generator/CMakeLists.txt index 209159019a..84a7e58249 100644 --- a/src/solver/ts-generator/CMakeLists.txt +++ b/src/solver/ts-generator/CMakeLists.txt @@ -13,12 +13,12 @@ source_group("ts-generator\\Randomized-thermal-generator" FILES ${SRC_RANDOMIZED # Optimized-thermal-ts-generator # set(SRC_OPTIMIZEDGENERATORS - optimized-thermal-generator/aux/AuxillaryStructures.h - optimized-thermal-generator/aux/AuxillaryStructures.cpp - optimized-thermal-generator/aux/AuxFreeFun.h - optimized-thermal-generator/aux/AuxFreeFun.cpp - optimized-thermal-generator/aux/pre-scenario-builder.h - optimized-thermal-generator/aux/pre-scenario-builder.cpp + optimized-thermal-generator/auxillary/AuxillaryStructures.h + optimized-thermal-generator/auxillary/AuxillaryStructures.cpp + optimized-thermal-generator/auxillary/AuxFreeFun.h + optimized-thermal-generator/auxillary/AuxFreeFun.cpp + optimized-thermal-generator/auxillary/pre-scenario-builder.h + optimized-thermal-generator/auxillary/pre-scenario-builder.cpp optimized-thermal-generator/main/OptimizedGenerator.h optimized-thermal-generator/main/OptimizedGenerator.cpp optimized-thermal-generator/parameters/OptimizationParameters.h diff --git a/src/solver/ts-generator/optimized-thermal-generator/aux/AuxFreeFun.cpp b/src/solver/ts-generator/optimized-thermal-generator/auxillary/AuxFreeFun.cpp similarity index 99% rename from src/solver/ts-generator/optimized-thermal-generator/aux/AuxFreeFun.cpp rename to src/solver/ts-generator/optimized-thermal-generator/auxillary/AuxFreeFun.cpp index 45b24fd604..afe5c1237c 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/aux/AuxFreeFun.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/auxillary/AuxFreeFun.cpp @@ -5,7 +5,7 @@ #include #include #include "../main/OptimizedGenerator.h" -#include "../aux/AuxFreeFun.h" +#include "../auxillary/AuxFreeFun.h" namespace Antares::Solver::TSGenerator { diff --git a/src/solver/ts-generator/optimized-thermal-generator/aux/AuxFreeFun.h b/src/solver/ts-generator/optimized-thermal-generator/auxillary/AuxFreeFun.h similarity index 100% rename from src/solver/ts-generator/optimized-thermal-generator/aux/AuxFreeFun.h rename to src/solver/ts-generator/optimized-thermal-generator/auxillary/AuxFreeFun.h diff --git a/src/solver/ts-generator/optimized-thermal-generator/aux/AuxillaryStructures.cpp b/src/solver/ts-generator/optimized-thermal-generator/auxillary/AuxillaryStructures.cpp similarity index 100% rename from src/solver/ts-generator/optimized-thermal-generator/aux/AuxillaryStructures.cpp rename to src/solver/ts-generator/optimized-thermal-generator/auxillary/AuxillaryStructures.cpp diff --git a/src/solver/ts-generator/optimized-thermal-generator/aux/AuxillaryStructures.h b/src/solver/ts-generator/optimized-thermal-generator/auxillary/AuxillaryStructures.h similarity index 100% rename from src/solver/ts-generator/optimized-thermal-generator/aux/AuxillaryStructures.h rename to src/solver/ts-generator/optimized-thermal-generator/auxillary/AuxillaryStructures.h diff --git a/src/solver/ts-generator/optimized-thermal-generator/aux/pre-scenario-builder.cpp b/src/solver/ts-generator/optimized-thermal-generator/auxillary/pre-scenario-builder.cpp similarity index 100% rename from src/solver/ts-generator/optimized-thermal-generator/aux/pre-scenario-builder.cpp rename to src/solver/ts-generator/optimized-thermal-generator/auxillary/pre-scenario-builder.cpp diff --git a/src/solver/ts-generator/optimized-thermal-generator/aux/pre-scenario-builder.h b/src/solver/ts-generator/optimized-thermal-generator/auxillary/pre-scenario-builder.h similarity index 100% rename from src/solver/ts-generator/optimized-thermal-generator/aux/pre-scenario-builder.h rename to src/solver/ts-generator/optimized-thermal-generator/auxillary/pre-scenario-builder.h diff --git a/src/solver/ts-generator/optimized-thermal-generator/main/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/main/OptimizedGenerator.h index 41fe73daf7..e5ec2e9c5c 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/main/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/main/OptimizedGenerator.h @@ -7,8 +7,8 @@ #include "ortools/linear_solver/linear_solver.h" #include "../../randomized-thermal-generator/RandomizedGenerator.h" #include "../../../../libs/antares/study/maintenance_planning/MaintenanceGroup.h" -#include "../aux/AuxillaryStructures.h" -#include "../aux/AuxFreeFun.h" +#include "../auxillary/AuxillaryStructures.h" +#include "../auxillary/AuxFreeFun.h" #include "../parameters/OptimizationParameters.h" #include From 41b6f169e6f0551666111dc45452ab27b41c05ec Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 19 Dec 2023 17:27:12 +0100 Subject: [PATCH 275/315] make it beta --- src/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index fb3cff9705..3da8b3bd5c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -6,8 +6,8 @@ set(ANTARES_VERSION_LO 8) set(ANTARES_VERSION_REVISION 0) # Beta release -set(ANTARES_BETA 0) -set(ANTARES_RC 3) +set(ANTARES_BETA 1) +set(ANTARES_RC 0) set(ANTARES_VERSION_YEAR 2023) From fb252a6f6daf2e9ff73a1004ecf2bbc7f6867290 Mon Sep 17 00:00:00 2001 From: Abdoulbari Zakir Date: Wed, 21 Feb 2024 14:49:14 +0100 Subject: [PATCH 276/315] fix --- src/solver/optimisation/opt_optimisation_lineaire.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/solver/optimisation/opt_optimisation_lineaire.cpp b/src/solver/optimisation/opt_optimisation_lineaire.cpp index 0a80822a17..d6fd877dda 100644 --- a/src/solver/optimisation/opt_optimisation_lineaire.cpp +++ b/src/solver/optimisation/opt_optimisation_lineaire.cpp @@ -163,7 +163,10 @@ bool OPT_OptimisationLineaire(const OptimizationOptions& options, ConstraintBuilder builder(builder_data); LinearProblemMatrix linearProblemMatrix(problemeHebdo, builder); linearProblemMatrix.Run(); - OPT_ExportStructures(problemeHebdo, writer); + if (problemeHebdo->ExportStructure && problemeHebdo->firstWeekOfSimulation) + { + OPT_ExportStructures(problemeHebdo, writer); + } bool ret = runWeeklyOptimization( options, problemeHebdo, adqPatchParams, writer, PREMIERE_OPTIMISATION); From aeae7ebed6b3d1d8f489ead0fe008fd7dcb5f2e5 Mon Sep 17 00:00:00 2001 From: Jason Marechal Date: Wed, 21 Feb 2024 16:15:13 +0100 Subject: [PATCH 277/315] Update to 8.8.3 --- sonar-project.properties | 23 ++++++++++++++++++++++- src/CMakeLists.txt | 2 +- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/sonar-project.properties b/sonar-project.properties index 1a30847665..703a8f0696 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -1,7 +1,28 @@ +# +# Copyright 2007-2024, RTE (https://www.rte-france.com) +# See AUTHORS.txt +# SPDX-License-Identifier: MPL-2.0 +# This file is part of Antares-Simulator, +# Adequacy and Performance assessment for interconnected energy networks. +# +# Antares_Simulator is free software: you can redistribute it and/or modify +# it under the terms of the Mozilla Public Licence 2.0 as published by +# the Mozilla Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# 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 +# Mozilla Public Licence 2.0 for more details. +# +# You should have received a copy of the Mozilla Public Licence 2.0 +# along with Antares_Simulator. If not, see . +# + sonar.projectName=Antares_Simulator sonar.projectKey=AntaresSimulatorTeam_Antares_Simulator sonar.organization=antaressimulatorteam -sonar.projectVersion=8.8.0 +sonar.projectVersion=8.8.3 # ===================================================== # Properties that will be shared amongst all modules diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9a2b334d3d..ae51c56496 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.14) # FetchContent_MakeAvailable # Version set(ANTARES_VERSION_HI 8) set(ANTARES_VERSION_LO 8) -set(ANTARES_VERSION_REVISION 2) +set(ANTARES_VERSION_REVISION 3) # Beta release set(ANTARES_BETA 0) From c1c98e3bdd22ded6818c366ebd913ab80a372fae Mon Sep 17 00:00:00 2001 From: Jason Marechal Date: Wed, 21 Feb 2024 16:38:17 +0100 Subject: [PATCH 278/315] Changelog --- docs/CHANGELOG.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 4f80b0eef7..2ed3a2b22b 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -1,10 +1,10 @@ Antares Changelog ================= -8.9.0 (Unreleased yet) +8.8.3 -------------------- -## New Features -* Solver logs can be enabled either by the command-line option (--solver-logs) or in the generaldata.ini by setting solver-logs = true under the optimization section [(#1717)](https://github.com/AntaresSimulatorTeam/Antares_Simulator/pull/1717) +## Bugfix +* Fix an issue where depending on the platform the output archive could contain several entries of the same area and inrco files 8.8.2 -------------------- From 01aa590d35005f418e2cbaff8bf6dbee0ff53971 Mon Sep 17 00:00:00 2001 From: Abdoulbari Zakir Date: Thu, 22 Feb 2024 10:42:23 +0100 Subject: [PATCH 279/315] install cmake 3.28 --- .github/workflows/install-cmake-328/action.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 .github/workflows/install-cmake-328/action.yml diff --git a/.github/workflows/install-cmake-328/action.yml b/.github/workflows/install-cmake-328/action.yml new file mode 100644 index 0000000000..a6f111746c --- /dev/null +++ b/.github/workflows/install-cmake-328/action.yml @@ -0,0 +1,17 @@ +name: "Install cmake 3.28 using devtoolset 10" +description: "Download and install system wide cmake 3.28" + +runs: + using: "composite" + steps: + - name: Build cmake + shell: bash + run: | + source /opt/rh/devtoolset-10/enable + yum -y install openssl-devel + wget https://github.com/Kitware/CMake/releases/download/v3.28.2/cmake-3.28.2.tar.gz + tar -xvf cmake-3.28.2.tar.gz + cd cmake-3.28.2 + ./bootstrap + make -j$(nproc) + make install From 8e84e3275181e1c5a0ad7eb3446d22d5ff21c3be Mon Sep 17 00:00:00 2001 From: payetvin <113102157+payetvin@users.noreply.github.com> Date: Tue, 26 Mar 2024 10:32:00 +0100 Subject: [PATCH 280/315] 8.8.4 (#1998) Backport some bugfixes #1969 #1960 #1982 --------- Co-authored-by: Florian OMNES --- docs/CHANGELOG.md | 7 ++ src/CMakeLists.txt | 2 +- .../study/parameters/adq-patch-params.cpp | 13 +--- .../study/parameters/adq-patch-params.h | 13 ++-- .../scenario-builder/ThermalTSNumberData.cpp | 8 ++- .../adq_patch_post_process_list.cpp | 54 +++++---------- .../optimisation/post_process_commands.cpp | 69 +++++++++++++------ .../optimisation/post_process_commands.h | 7 +- src/solver/ts-generator/thermal.cpp | 22 +++--- .../test-sc-builder-file-read-line.cpp | 21 ++++++ .../solver/optimisation/adequacy_patch.cpp | 8 --- 11 files changed, 125 insertions(+), 99 deletions(-) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 2ed3a2b22b..7bf8c2f52c 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -1,6 +1,13 @@ Antares Changelog ================= +8.8.4 (03/2024) +-------------------- +## Bugfix +* Adequacy patch CSR - fix DTG MRG (#1982) +* Fix ts numbers for no gen clusters (#1969) +* Remove unitcount limit for time series generation (#1960) + 8.8.3 -------------------- ## Bugfix diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ae51c56496..e39ee204e9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.14) # FetchContent_MakeAvailable # Version set(ANTARES_VERSION_HI 8) set(ANTARES_VERSION_LO 8) -set(ANTARES_VERSION_REVISION 3) +set(ANTARES_VERSION_REVISION 4) # Beta release set(ANTARES_BETA 0) diff --git a/src/libs/antares/study/parameters/adq-patch-params.cpp b/src/libs/antares/study/parameters/adq-patch-params.cpp index 2e012ff37d..b6deae7352 100644 --- a/src/libs/antares/study/parameters/adq-patch-params.cpp +++ b/src/libs/antares/study/parameters/adq-patch-params.cpp @@ -176,13 +176,13 @@ bool AdqPatchParams::checkAdqPatchParams(const SimulationMode simulationMode, checkAdqPatchSimulationModeEconomyOnly(simulationMode); checkAdqPatchContainsAdqPatchArea(areas); checkAdqPatchIncludeHurdleCost(includeHurdleCostParameters); - checkAdqPatchDisabledLocalMatching(); return true; } // Adequacy Patch can only be used with Economy Study/Simulation Mode. -void AdqPatchParams::checkAdqPatchSimulationModeEconomyOnly(const SimulationMode simulationMode) const +void AdqPatchParams::checkAdqPatchSimulationModeEconomyOnly( + const SimulationMode simulationMode) const { if (simulationMode != SimulationMode::Economy) throw Error::IncompatibleSimulationModeForAdqPatch(); @@ -205,11 +205,4 @@ void AdqPatchParams::checkAdqPatchIncludeHurdleCost(const bool includeHurdleCost if (curtailmentSharing.includeHurdleCost && !includeHurdleCostParameters) throw Error::IncompatibleHurdleCostCSR(); } - -void AdqPatchParams::checkAdqPatchDisabledLocalMatching() const -{ - if (!localMatching.enabled && curtailmentSharing.priceTakingOrder == AdqPatchPTO::isDens) - throw Error::AdqPatchDisabledLMR(); -} - -} // Antares::Data::AdequacyPatch +} // namespace Antares::Data::AdequacyPatch diff --git a/src/libs/antares/study/parameters/adq-patch-params.h b/src/libs/antares/study/parameters/adq-patch-params.h index 8362d66765..e3c56115b2 100644 --- a/src/libs/antares/study/parameters/adq-patch-params.h +++ b/src/libs/antares/study/parameters/adq-patch-params.h @@ -9,7 +9,6 @@ namespace Antares::Data::AdequacyPatch { - //! A default threshold value for initiate curtailment sharing rule const double defaultThresholdToRunCurtailmentSharing = 0.0; //! A default threshold value for display local matching rule violations @@ -58,7 +57,6 @@ enum class AdqPatchPTO }; // enum AdqPatchPTO - struct LocalMatching { bool enabled = true; @@ -71,12 +69,11 @@ struct LocalMatching //! rule. bool setToZeroOutsideOutsideLinks = true; /*! - ** \brief Reset to default values related to local matching - */ + ** \brief Reset to default values related to local matching + */ void reset(); bool updateFromKeyValue(const Yuni::String& key, const Yuni::String& value); void addProperties(IniFile::Section* section) const; - }; class CurtailmentSharing @@ -95,6 +92,8 @@ class CurtailmentSharing //! Check CSR cost function prior & after CSR optimization bool checkCsrCostFunction; + bool recomputeDTGMRG = false; + bool updateFromKeyValue(const Yuni::String& key, const Yuni::String& value); void addProperties(IniFile::Section* section) const; @@ -104,10 +103,8 @@ class CurtailmentSharing void resetThresholds(); }; - struct AdqPatchParams { - bool enabled; LocalMatching localMatching; CurtailmentSharing curtailmentSharing; @@ -120,11 +117,9 @@ struct AdqPatchParams const AreaList& areas, const bool includeHurdleCostParameters) const; - void checkAdqPatchSimulationModeEconomyOnly(const SimulationMode simulationMode) const; void checkAdqPatchContainsAdqPatchArea(const Antares::Data::AreaList& areas) const; void checkAdqPatchIncludeHurdleCost(const bool includeHurdleCost) const; - void checkAdqPatchDisabledLocalMatching() const; }; } // namespace Antares::Data::AdequacyPatch diff --git a/src/libs/antares/study/scenario-builder/ThermalTSNumberData.cpp b/src/libs/antares/study/scenario-builder/ThermalTSNumberData.cpp index b67ede4039..7de24c0f0e 100644 --- a/src/libs/antares/study/scenario-builder/ThermalTSNumberData.cpp +++ b/src/libs/antares/study/scenario-builder/ThermalTSNumberData.cpp @@ -83,8 +83,6 @@ bool thermalTSNumberData::apply(Study& study) // WARNING: We may have some thermal clusters with the `mustrun` option auto clusterCount = (uint)area.thermal.clusterCount(); - const uint tsGenCountThermal = get_tsGenCount(study); - for (uint clusterIndex = 0; clusterIndex != clusterCount; ++clusterIndex) { auto& cluster = *(area.thermal.clusters[clusterIndex]); @@ -92,9 +90,13 @@ bool thermalTSNumberData::apply(Study& study) assert(clusterIndex < pTSNumberRules.width); const auto& col = pTSNumberRules[clusterIndex]; + uint tsGenCount = cluster.tsGenBehavior == LocalTSGenerationBehavior::forceNoGen ? + cluster.series.timeSeries.width : get_tsGenCount(study); + logprefix.clear() << "Thermal: area '" << area.name << "', cluster: '" << cluster.name() << "': "; - ret = ApplyToMatrix(errors, logprefix, cluster.series, col, tsGenCountThermal) && ret; + ret = ApplyToMatrix(errors, logprefix, cluster.series, col, tsGenCount) && ret; + } return ret; } diff --git a/src/solver/optimisation/adequacy_patch_csr/adq_patch_post_process_list.cpp b/src/solver/optimisation/adequacy_patch_csr/adq_patch_post_process_list.cpp index 9bf0665d4b..d02c6ea7cd 100644 --- a/src/solver/optimisation/adequacy_patch_csr/adq_patch_post_process_list.cpp +++ b/src/solver/optimisation/adequacy_patch_csr/adq_patch_post_process_list.cpp @@ -1,57 +1,35 @@ #include "adq_patch_post_process_list.h" #include "../post_process_commands.h" - namespace Antares::Solver::Simulation { - AdqPatchPostProcessList::AdqPatchPostProcessList(const AdqPatchParams& adqPatchParams, PROBLEME_HEBDO* problemeHebdo, uint thread_number, AreaList& areas, SheddingPolicy sheddingPolicy, SimplexOptimization splxOptimization, - Calendar& calendar) - : interfacePostProcessList(problemeHebdo, thread_number) + Calendar& calendar) : + interfacePostProcessList(problemeHebdo, thread_number) { - post_process_list.push_back(std::make_unique( - problemeHebdo_, - thread_number_, - areas)); + post_process_list.push_back( + std::make_unique(problemeHebdo_, thread_number_, areas)); // Here a post process particular to adq patch post_process_list.push_back(std::make_unique( - adqPatchParams, - problemeHebdo_, - areas, - thread_number_)); - post_process_list.push_back(std::make_unique( - problemeHebdo_, - areas, - false, - false)); + adqPatchParams, problemeHebdo_, areas, thread_number_)); + post_process_list.push_back( + std::make_unique(problemeHebdo_, areas, false, false)); post_process_list.push_back(std::make_unique( - problemeHebdo_, - areas, - sheddingPolicy, - splxOptimization, - thread_number)); + problemeHebdo_, areas, sheddingPolicy, splxOptimization, thread_number)); // Here a post process particular to adq patch post_process_list.push_back(std::make_unique( - problemeHebdo_, - areas, - thread_number)); - post_process_list.push_back(std::make_unique( - problemeHebdo_, - areas, - true, - false)); - post_process_list.push_back(std::make_unique( - problemeHebdo_, - areas, - calendar)); - post_process_list.push_back(std::make_unique( - problemeHebdo_, - areas)); + adqPatchParams, problemeHebdo_, areas, thread_number)); + post_process_list.push_back( + std::make_unique(problemeHebdo_, areas, true, false)); + post_process_list.push_back( + std::make_unique(problemeHebdo_, areas, calendar)); + post_process_list.push_back( + std::make_unique(problemeHebdo_, areas)); } -} // namespace Antares::Solver::Simulation \ No newline at end of file +} // namespace Antares::Solver::Simulation diff --git a/src/solver/optimisation/post_process_commands.cpp b/src/solver/optimisation/post_process_commands.cpp index d1a367e03c..9e1bfc4c41 100644 --- a/src/solver/optimisation/post_process_commands.cpp +++ b/src/solver/optimisation/post_process_commands.cpp @@ -1,3 +1,23 @@ +/* +** Copyright 2007-2024, RTE (https://www.rte-france.com) +** See AUTHORS.txt +** SPDX-License-Identifier: MPL-2.0 +** This file is part of Antares-Simulator, +** Adequacy and Performance assessment for interconnected energy networks. +** +** Antares_Simulator is free software: you can redistribute it and/or modify +** it under the terms of the Mozilla Public Licence 2.0 as published by +** the Mozilla Foundation, either version 2 of the License, or +** (at your option) any later version. +** +** 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 +** Mozilla Public Licence 2.0 for more details. +** +** You should have received a copy of the Mozilla Public Licence 2.0 +** along with Antares_Simulator. If not, see . +*/ #include "post_process_commands.h" #include "../simulation/common-eco-adq.h" @@ -97,10 +117,14 @@ void RemixHydroPostProcessCmd::execute(const optRuntimeData& opt_runtime_data) using namespace Antares::Data::AdequacyPatch; DTGmarginForAdqPatchPostProcessCmd::DTGmarginForAdqPatchPostProcessCmd( + const AdqPatchParams& adqPatchParams, PROBLEME_HEBDO* problemeHebdo, AreaList& areas, unsigned int thread_number) : - basePostProcessCommand(problemeHebdo), area_list_(areas), thread_number_(thread_number) + basePostProcessCommand(problemeHebdo), + adqPatchParams_(adqPatchParams), + area_list_(areas), + thread_number_(thread_number) { } @@ -128,8 +152,11 @@ void DTGmarginForAdqPatchPostProcessCmd::execute(const optRuntimeData&) // calculate DTG MRG CSR and adjust ENS if neccessary if (problemeHebdo_->adequacyPatchRuntimeData->wasCSRTriggeredAtAreaHour(Area, hour)) { - dtgMrgCsr = std::max(0.0, dtgMrg - ens); - ens = std::max(0.0, ens - dtgMrg); + if (adqPatchParams_.curtailmentSharing.recomputeDTGMRG) + { + dtgMrgCsr = std::max(0.0, dtgMrg - ens); + ens = std::max(0.0, ens - dtgMrg); + } // set MRG PRICE to value of unsupplied energy cost, if LOLD=1.0 (ENS>0.5) if (ens > 0.5) mrgCost = -area_list_[Area]->thermal.unsuppliedEnergyCost; @@ -177,14 +204,15 @@ void HydroLevelsFinalUpdatePostProcessCmd::execute(const optRuntimeData&) // -------------------------------------- // Curtailment sharing for adq patch // -------------------------------------- -CurtailmentSharingPostProcessCmd::CurtailmentSharingPostProcessCmd(const AdqPatchParams& adqPatchParams, - PROBLEME_HEBDO* problemeHebdo, - AreaList& areas, - unsigned int thread_number) : - basePostProcessCommand(problemeHebdo), - area_list_(areas), - adqPatchParams_(adqPatchParams), - thread_number_(thread_number) +CurtailmentSharingPostProcessCmd::CurtailmentSharingPostProcessCmd( + const AdqPatchParams& adqPatchParams, + PROBLEME_HEBDO* problemeHebdo, + AreaList& areas, + unsigned int thread_number) : + basePostProcessCommand(problemeHebdo), + area_list_(areas), + adqPatchParams_(adqPatchParams), + thread_number_(thread_number) { } @@ -217,11 +245,11 @@ double CurtailmentSharingPostProcessCmd::calculateDensNewAndTotalLmrViolation() { for (uint hour = 0; hour < nbHoursInWeek; hour++) { - const auto [netPositionInit, densNew, totalNodeBalance] - = calculateAreaFlowBalance(problemeHebdo_, - adqPatchParams_.localMatching.setToZeroOutsideInsideLinks, - Area, - hour); + const auto [netPositionInit, densNew, totalNodeBalance] = calculateAreaFlowBalance( + problemeHebdo_, + adqPatchParams_.localMatching.setToZeroOutsideInsideLinks, + Area, + hour); // adjust densNew according to the new specification/request by ELIA /* DENS_new (node A) = max [ 0; ENS_init (node A) + net_position_init (node A) + ? flows (node 1 -> node A) - DTG.MRG(node A)] */ @@ -237,10 +265,11 @@ double CurtailmentSharingPostProcessCmd::calculateDensNewAndTotalLmrViolation() .ValeursHorairesDeDefaillanceNegative[hour]; // check LMR violations totalLmrViolation += LmrViolationAreaHour( - problemeHebdo_, - totalNodeBalance, - adqPatchParams_.curtailmentSharing.thresholdDisplayViolations, - Area, hour); + problemeHebdo_, + totalNodeBalance, + adqPatchParams_.curtailmentSharing.thresholdDisplayViolations, + Area, + hour); } } } diff --git a/src/solver/optimisation/post_process_commands.h b/src/solver/optimisation/post_process_commands.h index d04daf02ce..4a58237bb2 100644 --- a/src/solver/optimisation/post_process_commands.h +++ b/src/solver/optimisation/post_process_commands.h @@ -51,14 +51,18 @@ class RemixHydroPostProcessCmd : public basePostProcessCommand class DTGmarginForAdqPatchPostProcessCmd : public basePostProcessCommand { + using AdqPatchParams = Antares::Data::AdequacyPatch::AdqPatchParams; + public: - DTGmarginForAdqPatchPostProcessCmd(PROBLEME_HEBDO* problemeHebdo, + DTGmarginForAdqPatchPostProcessCmd(const AdqPatchParams& adqPatchParams, + PROBLEME_HEBDO* problemeHebdo, AreaList& areas, unsigned int thread_number); void execute(const optRuntimeData& opt_runtime_data) override; private: + const AdqPatchParams& adqPatchParams_; const AreaList& area_list_; unsigned int thread_number_ = 0; }; @@ -91,6 +95,7 @@ class HydroLevelsFinalUpdatePostProcessCmd : public basePostProcessCommand class CurtailmentSharingPostProcessCmd : public basePostProcessCommand { using AdqPatchParams = Antares::Data::AdequacyPatch::AdqPatchParams; + public: CurtailmentSharingPostProcessCmd(const AdqPatchParams& adqPatchParams, PROBLEME_HEBDO* problemeHebdo, diff --git a/src/solver/ts-generator/thermal.cpp b/src/solver/ts-generator/thermal.cpp index 5c3f75b137..8f3f75e132 100644 --- a/src/solver/ts-generator/thermal.cpp +++ b/src/solver/ts-generator/thermal.cpp @@ -86,8 +86,6 @@ class GeneratorTempData final private: uint nbThermalTimeseries_; - const uint nbHoursPerYear = HOURS_PER_YEAR; - const uint daysPerYear = DAYS_PER_YEAR; MersenneTwister& rndgenerator; @@ -107,8 +105,9 @@ class GeneratorTempData final double ap[366]; double bf[366]; double bp[366]; - double FPOW[366][102]; - double PPOW[366][102]; + + std::vector> FPOW; + std::vector> PPOW; String pTempFilename; Solver::Progression::Task& pProgression; @@ -130,6 +129,9 @@ GeneratorTempData::GeneratorTempData(Data::Study& study, nbThermalTimeseries_ = parameters.nbTimeSeriesThermal; derated = parameters.derated; + + FPOW.resize(DAYS_PER_YEAR); + PPOW.resize(DAYS_PER_YEAR); } void GeneratorTempData::writeResultsToDisk(const Data::Area& area, @@ -167,7 +169,7 @@ void GeneratorTempData::prepareIndispoFromLaw(Data::ThermalLaw law, { case Data::thermalLawUniform: { - for (uint d = 0; d < daysPerYear; ++d) + for (uint d = 0; d < DAYS_PER_YEAR; ++d) { double D = (double)duration[d]; double xtemp = volatility * (D - 1.); @@ -178,7 +180,7 @@ void GeneratorTempData::prepareIndispoFromLaw(Data::ThermalLaw law, } case Data::thermalLawGeometric: { - for (uint d = 0; d < daysPerYear; ++d) + for (uint d = 0; d < DAYS_PER_YEAR; ++d) { double D = (double)duration[d]; double xtemp = volatility * volatility * D * (D - 1.); @@ -283,8 +285,11 @@ void GeneratorTempData::operator()(Data::Area& area, Data::ThermalCluster& clust int FOD_reel = 0; int POD_reel = 0; - for (uint d = 0; d < daysPerYear; ++d) + for (uint d = 0; d < DAYS_PER_YEAR; ++d) { + FPOW[d].resize(cluster.unitCount + 1); + PPOW[d].resize(cluster.unitCount + 1); + PODOfTheDay = (int)POD[d]; FODOfTheDay = (int)FOD[d]; @@ -356,9 +361,8 @@ void GeneratorTempData::operator()(Data::Area& area, Data::ThermalCluster& clust if (tsIndex > 1) dstSeries = cluster.series.timeSeries[tsIndex - 2]; - for (uint dayInTheYear = 0; dayInTheYear < daysPerYear; ++dayInTheYear) + for (uint dayInTheYear = 0; dayInTheYear < DAYS_PER_YEAR; ++dayInTheYear) { - assert(AUN <= 100 and "Thermal Prepro: AUN is out of bounds (>=100)"); assert(dayInTheYear < 366); assert(not(lf[dayInTheYear] < 0.)); assert(not(lp[dayInTheYear] < 0.)); diff --git a/src/tests/src/libs/antares/study/scenario-builder/test-sc-builder-file-read-line.cpp b/src/tests/src/libs/antares/study/scenario-builder/test-sc-builder-file-read-line.cpp index 36935b8e36..03fca5f5d9 100644 --- a/src/tests/src/libs/antares/study/scenario-builder/test-sc-builder-file-read-line.cpp +++ b/src/tests/src/libs/antares/study/scenario-builder/test-sc-builder-file-read-line.cpp @@ -409,4 +409,25 @@ BOOST_FIXTURE_TEST_CASE(binding_constraints_group_groupTest__Load_TS_4_for_year_ BOOST_CHECK_EQUAL(actual, tsNumber-1); } +// ======================== +// Tests on TSNumberData +// ======================== +BOOST_FIXTURE_TEST_CASE(thermalTSNumberData, Fixture) +{ + ScenarioBuilder::thermalTSNumberData tsdata; + tsdata.attachArea(area_1); + tsdata.reset(*study); + tsdata.setTSnumber(thCluster_12.get(), 2, 22); + tsdata.setTSnumber(thCluster_12.get(), 5, 32); //out of bounds + + study->parameters.nbTimeSeriesThermal = 1; + thCluster_12->tsGenBehavior = LocalTSGenerationBehavior::forceNoGen; + thCluster_12->series.timeSeries.resize(30, 8760); + + tsdata.apply(*study); + + BOOST_CHECK_EQUAL(thCluster_12->series.timeseriesNumbers[0][2], 21); + BOOST_CHECK_EQUAL(thCluster_12->series.timeseriesNumbers[0][5], 0); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/src/tests/src/solver/optimisation/adequacy_patch.cpp b/src/tests/src/solver/optimisation/adequacy_patch.cpp index fcc06b4fd2..f9101143a5 100644 --- a/src/tests/src/solver/optimisation/adequacy_patch.cpp +++ b/src/tests/src/solver/optimisation/adequacy_patch.cpp @@ -489,7 +489,6 @@ BOOST_AUTO_TEST_CASE(check_valid_adq_param) auto p = createParams(); BOOST_CHECK_NO_THROW(p.checkAdqPatchSimulationModeEconomyOnly(Antares::Data::SimulationMode::Economy)); BOOST_CHECK_NO_THROW(p.checkAdqPatchIncludeHurdleCost(true)); - BOOST_CHECK_NO_THROW(p.checkAdqPatchDisabledLocalMatching()); } BOOST_AUTO_TEST_CASE(check_adq_param_wrong_mode) @@ -504,10 +503,3 @@ BOOST_AUTO_TEST_CASE(check_adq_param_wrong_hurdle_cost) auto p = createParams(); BOOST_CHECK_THROW(p.checkAdqPatchIncludeHurdleCost(false), Error::IncompatibleHurdleCostCSR); } - -BOOST_AUTO_TEST_CASE(check_adq_param_wrong_lmr_disabled) -{ - auto p = createParams(); - p.localMatching.enabled = false; - BOOST_CHECK_THROW(p.checkAdqPatchDisabledLocalMatching(), Error::AdqPatchDisabledLMR); -} From 432bc4b14979ee39193062d505798b88f42dca1e Mon Sep 17 00:00:00 2001 From: Vincent Payet Date: Fri, 29 Mar 2024 12:11:58 +0100 Subject: [PATCH 281/315] simtest version --- simtest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simtest.json b/simtest.json index 8fbede7352..570b89427c 100644 --- a/simtest.json +++ b/simtest.json @@ -1,3 +1,3 @@ { - "version": "v8.8.1" + "version": "v8.8.2" } From 0573c5fa2e7ce1f3f22c77f29b3326ab4e2c1a40 Mon Sep 17 00:00:00 2001 From: payetvin <113102157+payetvin@users.noreply.github.com> Date: Mon, 27 May 2024 09:41:30 +0200 Subject: [PATCH 282/315] Version 8.8.5 (#2110) Co-authored-by: guilpier-code <62292552+guilpier-code@users.noreply.github.com> Co-authored-by: Florian OMNES --- .github/workflows/centos7.yml | 47 ++++++------ .github/workflows/new_release.yml | 29 ++++++-- .github/workflows/oracle8.yml | 55 +++++++++----- .github/workflows/ubuntu.yml | 72 ++++++++++++++++--- .github/workflows/windows-vcpkg.yml | 32 +++++---- simtest.json | 2 +- src/CMakeLists.txt | 2 +- .../src/yuni/io/filename-manipulation.cpp | 6 +- src/solver/variable/economy/profitByPlant.h | 3 +- .../test_binding_constraints.cpp | 2 +- .../end-to-end/simple_study/simple-study.cpp | 2 +- .../libs/antares/array/tests-matrix-load.cpp | 2 +- .../libs/antares/array/tests-matrix-save.cpp | 2 +- .../antares/concurrency/test_concurrency.cpp | 2 +- .../area/test-save-area-optimization-ini.cpp | 2 +- .../study/area/test-save-link-properties.cpp | 2 +- .../study/constraint/test_constraint.cpp | 2 +- .../antares/study/constraint/test_group.cpp | 2 +- .../antares/study/output-folder/study.cpp | 2 +- .../test-sc-builder-file-read-line.cpp | 2 +- .../test-sc-builder-file-save.cpp | 2 +- .../antares/study/series/timeseries-tests.cpp | 2 +- .../short-term-storage-input-output.cpp | 2 +- .../src/libs/antares/study/test_study.cpp | 2 +- .../thermal-price-definition.cpp | 2 +- src/tests/src/libs/antares/test_utils.cpp | 2 +- .../libs/antares/writer/test_zip_writer.cpp | 2 +- .../test-unfeasible-problem-analyzer.cpp | 2 +- .../solver/optimisation/adequacy_patch.cpp | 2 +- .../test-store-timeseries-number.cpp | 2 +- .../solver/simulation/test-time_series.cpp | 2 +- .../solver/simulation/tests-ts-numbers.cpp | 2 +- 32 files changed, 197 insertions(+), 97 deletions(-) diff --git a/.github/workflows/centos7.yml b/.github/workflows/centos7.yml index fd0f4ecc27..46b3e34ab8 100644 --- a/.github/workflows/centos7.yml +++ b/.github/workflows/centos7.yml @@ -12,12 +12,16 @@ on: inputs: run-tests: required: true - type: boolean + type: string + target_branch: + required: true + type: string env: GITHUB_TOKEN: ${{ github.token }} IS_RELEASE: ${{ github.event_name == 'workflow_dispatch' }} IS_PUSH: ${{ github.event_name == 'push' }} + REF: ${{ inputs.target_branch =='' && github.ref_name || inputs.target_branch}} jobs: @@ -33,7 +37,14 @@ jobs: - name: Checkout run: | - git clone $GITHUB_SERVER_URL/$GITHUB_REPOSITORY.git -b $GITHUB_REF_NAME . + git clone $GITHUB_SERVER_URL/$GITHUB_REPOSITORY.git -b ${{ env.REF }} . + + - name: Install gcc 10 + run: | + yum install -y centos-release-scl + yum install -y devtoolset-10-gcc* + + - uses: ./.github/workflows/install-cmake-328 - name: Init submodule run: | @@ -59,22 +70,26 @@ jobs: unzip -q ortools.zip rm ortools.zip - - name: Install gcc 10 + - name: Install gh if needed + if: ${{ env.IS_RELEASE == 'true' }} run: | - yum install -y centos-release-scl - yum install -y devtoolset-10-gcc* + yum -y install dnf + dnf -y install 'dnf-command(config-manager)' + dnf -y config-manager --add-repo https://cli.github.com/packages/rpm/gh-cli.repo + dnf -y install gh + - name: Configure run: | source /opt/rh/devtoolset-10/enable - cmake3 -B _build -S src \ + cmake -B _build -S src \ -DCMAKE_C_COMPILER_LAUNCHER=ccache \ -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \ -DDEPS_INSTALL_DIR=/rte-antares-deps-Release \ -DCMAKE_BUILD_TYPE=Release \ -DBUILD_TESTING=ON \ -DBUILD_not_system=OFF \ - -DBUILD_TOOLS=OFF \ + -DBUILD_TOOLS=ON \ -DBUILD_UI=OFF \ -DCMAKE_PREFIX_PATH=${{ env.ORTOOLSDIR }}/install \ @@ -82,18 +97,18 @@ jobs: run: | source /opt/rh/devtoolset-10/enable source /opt/rh/rh-git227/enable - cmake3 --build _build --config Release -j$(nproc) + cmake --build _build --config Release -j$(nproc) ccache -s - name: Installer .rpm creation run: | cd _build - cpack3 -G RPM + cpack -G RPM - name: Solver archive creation run: | cd _build - cmake3 --install . --prefix install + cmake --install . --prefix install pushd . cd install/bin tar czf ../../antares-solver_centos7.tar.gz antares-*-solver libsirius_solver.so @@ -103,7 +118,7 @@ jobs: - name: .tar.gz creation run: | cd _build - cpack3 -G TGZ + cpack -G TGZ - name: Installer TGZ push uses: actions/upload-artifact@v3 @@ -115,14 +130,6 @@ jobs: with: path: _build/*.rpm - - name: Install gh - if: ${{ env.IS_RELEASE == 'true' }} - run: | - yum -y install dnf - dnf -y install 'dnf-command(config-manager)' - dnf -y config-manager --add-repo https://cli.github.com/packages/rpm/gh-cli.repo - dnf -y install gh - - name: Publish assets if: ${{ env.IS_RELEASE == 'true' }} env: @@ -131,4 +138,4 @@ jobs: run: | gh release upload "$tag" _build/*.tar.gz _build/*.rpm - \ No newline at end of file + diff --git a/.github/workflows/new_release.yml b/.github/workflows/new_release.yml index bdb156a776..6cf6da390a 100644 --- a/.github/workflows/new_release.yml +++ b/.github/workflows/new_release.yml @@ -3,6 +3,9 @@ name: Create new release on: workflow_dispatch: inputs: + target_branch: + description: "Target branch or full commit SHA" + required: true release_tag: description: "Release tag" required: true @@ -12,6 +15,11 @@ on: run-tests: description: "Run all tests (true/false)" required: true + type: string + set_latest: + description: "Set the release as latest" + required: true + type: boolean jobs: release: name: Release pushed tag @@ -23,12 +31,15 @@ jobs: tag: ${{ github.event.inputs.release_tag }} title: ${{ github.event.inputs.release_name }} tests: ${{ github.event.inputs.run-tests }} + target_branch: ${{ github.event.inputs.target_branch }} + latest: ${{ github.event.inputs.set_latest }} run: | gh release create "$tag" \ --repo="$GITHUB_REPOSITORY" \ --title="$title" \ - --notes="Run tests: $tests" - + --notes="Run tests: $tests"\ + --target="$target_branch" \ + --latest=$latest ubuntu: @@ -36,32 +47,36 @@ jobs: needs: release uses: ./.github/workflows/ubuntu.yml with: - run-tests: ${{ fromJSON(inputs.run-tests) }} + run-tests: ${{ inputs.run-tests }} + target_branch: ${{ inputs.target_branch }} windows: name: Release - Windows needs: release uses: ./.github/workflows/windows-vcpkg.yml with: - run-tests: ${{ fromJSON(inputs.run-tests) }} + run-tests: ${{ inputs.run-tests }} + target_branch: ${{ inputs.target_branch }} centos7: name: Release - centos7 needs: release uses: ./.github/workflows/centos7.yml with: - run-tests: ${{ fromJSON(inputs.run-tests) }} + run-tests: ${{ inputs.run-tests }} + target_branch: ${{ inputs.target_branch }} oracle8: name: Release - oracle8 needs: release uses: ./.github/workflows/oracle8.yml with: - run-tests: ${{ fromJSON(inputs.run-tests) }} + run-tests: ${{ inputs.run-tests }} + target_branch: ${{ inputs.target_branch }} user_guide: name: User Guide needs: release uses: ./.github/workflows/build-userguide.yml with: - run-tests: ${{ fromJSON(inputs.run-tests) }} + run-tests: ${{ inputs.run-tests }} diff --git a/.github/workflows/oracle8.yml b/.github/workflows/oracle8.yml index 10e94ddb92..76009b7d65 100644 --- a/.github/workflows/oracle8.yml +++ b/.github/workflows/oracle8.yml @@ -6,25 +6,32 @@ on: push: branches: - develop + - dependabot/* + schedule: - cron: '21 2 * * *' workflow_call: inputs: run-tests: required: true - type: boolean + type: string + target_branch: + required: true + type: string env: GITHUB_TOKEN: ${{ github.token }} IS_RELEASE: ${{ github.event_name == 'workflow_dispatch' }} IS_PUSH: ${{ github.event_name == 'push' }} + REF: ${{ inputs.target_branch =='' && github.ref_name || inputs.target_branch}} + jobs: build: name: Build env: - ORTOOLSDIR: ${{ github.workspace }}/or-tools + ORTOOLS_DIR: ${{ github.workspace }}/or-tools runs-on: ubuntu-latest container: 'oraclelinux:8' @@ -38,12 +45,24 @@ jobs: - name: Install libraries run: | - dnf install -y epel-release git cmake wget rpm-build redhat-lsb-core - dnf install -y unzip libuuid-devel boost-test boost-devel gcc-toolset-10-toolchain zlib-devel + dnf install -y epel-release git cmake wget rpm-build redhat-lsb-core + dnf install -y unzip libuuid-devel boost-test boost-devel gcc-toolset-11 zlib-devel - name: Checkout run: | - git clone $GITHUB_SERVER_URL/$GITHUB_REPOSITORY.git -b $GITHUB_REF_NAME . + git clone $GITHUB_SERVER_URL/$GITHUB_REPOSITORY.git -b ${{ env.REF }} . + + - name: Config OR-Tools URL + run: | + echo "ORTOOLS_URL=https://github.com/rte-france/or-tools/releases/download/$(cat ortools_tag)/ortools_cxx_oraclelinux-8_static_sirius.zip" >> $GITHUB_ENV + + - name: Download & extract OR-Tools + run: | + mkdir -p ${{env.ORTOOLS_DIR}} + cd ${{env.ORTOOLS_DIR}} + wget ${{env.ORTOOLS_URL}} -O ortools.zip + unzip ortools.zip + rm ortools.zip - name: Init submodule run: | @@ -54,18 +73,26 @@ jobs: run: | pip3 install -r src/tests/examples/requirements.txt + - name: Install gh if needed + if: ${{ env.IS_RELEASE == 'true' }} + run: | + dnf -y install 'dnf-command(config-manager)' + dnf -y config-manager --add-repo https://cli.github.com/packages/rpm/gh-cli.repo + dnf -y install gh + - name: Configure run: | - source /opt/rh/gcc-toolset-10/enable + source /opt/rh/gcc-toolset-11/enable cmake -B _build -S src \ -DCMAKE_BUILD_TYPE=Release \ - -DBUILD_TESTING=ON \ - -DBUILD_TOOLS=OFF \ + -DBUILD_TESTING=OFF \ + -DBUILD_TOOLS=ON \ -DBUILD_UI=OFF \ + -DCMAKE_PREFIX_PATH=${{ env.ORTOOLS_DIR }}/install - name: Build run: | - source /opt/rh/gcc-toolset-10/enable + source /opt/rh/gcc-toolset-11/enable cmake --build _build --config Release -j$(nproc) - name: Run unit and end-to-end tests @@ -104,18 +131,10 @@ jobs: with: path: _build/*.rpm - - name: Install gh - if: ${{ env.IS_RELEASE == 'true' }} - run: | - dnf -y install 'dnf-command(config-manager)' - dnf -y config-manager --add-repo https://cli.github.com/packages/rpm/gh-cli.repo - dnf -y install gh - - name: Publish assets if: ${{ env.IS_RELEASE == 'true' }} env: GITHUB_TOKEN: ${{ github.token }} tag: ${{ github.event.inputs.release_tag }} run: | - gh release upload "$tag" _build/*.tar.gz _build/*.rpm - + gh release upload "$tag" _build/*.tar.gz _build/*.rpm diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml index f85572cdbc..d961d2e5a0 100644 --- a/.github/workflows/ubuntu.yml +++ b/.github/workflows/ubuntu.yml @@ -10,19 +10,28 @@ on: - issue-* - release/* - doc/* + - dependabot/* schedule: - cron: '21 2 * * *' workflow_call: inputs: run-tests: required: true - type: boolean + type: string + target_branch: + required: true + type: string env: GITHUB_TOKEN: ${{ github.token }} IS_RELEASE: ${{ github.event_name == 'workflow_dispatch' }} RUN_SIMPLE_TESTS: ${{ github.event_name == 'push' || inputs.run-tests == 'true' }} RUN_EXTENDED_TESTS: ${{ github.event_name == 'schedule' || inputs.run-tests == 'true' }} + REF: ${{ inputs.target_branch =='' && github.ref || inputs.target_branch}} + VCPKG_ROOT: ${{ github.workspace }}/vcpkg + vcpkgPackages: yaml-cpp antlr4 + triplet: x64-linux + WX_CONFIG: /usr/bin/wx-config jobs: @@ -34,15 +43,39 @@ jobs: runs-on: ubuntu-20.04 if: "!contains(github.event.head_commit.message, '[skip ci]')" - + steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 + with: + ref: ${{ env.REF }} - name: ccache uses: hendrikmuhs/ccache-action@v1.2 with: key: ${{ env.os }} + + - name : Init VCPKG submodule + run: | + git submodule update --init vcpkg + + # Restore both vcpkg and its artifacts from the GitHub cache service. + - name: Restore vcpkg and its artifacts. + uses: actions/cache@v4 + with: + # The first path is the location of vcpkg (it contains the vcpkg executable and data files). + # The other paths starting with '!' are exclusions: they contain termporary files generated during the build of the installed packages. + path: | + ${{ env.VCPKG_ROOT }} + !${{ env.VCPKG_ROOT }}/buildtrees + !${{ env.VCPKG_ROOT }}/packages + !${{ env.VCPKG_ROOT }}/downloads + # The key is composed in a way that it gets properly invalidated: this must happen whenever vcpkg's Git commit id changes, or the list of packages changes. In this case a cache miss must happen and a new entry with a new key with be pushed to GitHub the cache service. + # The key includes: hash of the vcpkg.json file, the hash of the vcpkg Git commit id, and the used vcpkg's triplet. The vcpkg's commit id would suffice, but computing an hash out it does not harm. + # Note: given a key, the cache content is immutable. If a cache entry has been created improperly, in order the recreate the right content the key must be changed as well, and it must be brand new (i.e. not existing already). + key: | + ${{ hashFiles( 'vcpkg_manifest/vcpkg.json' ) }}-${{ hashFiles( '.git/modules/vcpkg/HEAD' )}}-${{ env.triplet }} + - name: Install libraries run: | sudo apt-get update @@ -50,6 +83,19 @@ jobs: sudo apt-get install libboost-test-dev sudo apt-get install g++-10 gcc-10 + - name: export wxWidgets script + shell: bash + run: | + export WX_CONFIG=${{env.WX_CONFIG}} + + - name : Install deps with VCPKG + run: | + cd vcpkg + ./bootstrap-vcpkg.sh + vcpkg install ${{env.vcpkgPackages}} --triplet ${{env.triplet}} + rm -rf buildtrees packages downloads + shell: bash + - name: Read antares-deps version id: antares-deps-version uses: notiz-dev/github-action-json-property@release @@ -72,7 +118,7 @@ jobs: - name: Set up Python id: setup-python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.12' @@ -85,11 +131,15 @@ jobs: run: | git submodule update --init src/antares-deps git submodule update --init --remote --recursive src/tests/resources/Antares_Simulator_Tests + + - name: Configure run: | cmake -B _build -S src \ -DCMAKE_C_COMPILER_LAUNCHER=ccache \ + -DVCPKG_ROOT="${{env.VCPKG_ROOT}}" \ + -DVCPKG_TARGET_TRIPLET=${{ env.triplet }} \ -DCMAKE_C_COMPILER=/usr/bin/gcc-10 \ -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \ -DCMAKE_CXX_COMPILER=/usr/bin/g++-10 \ @@ -138,7 +188,7 @@ jobs: - name: Upload logs for failed tests if: ${{ failure() }} - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: test-log path: ${{ github.workspace }}/_build/Testing/Temporary/LastTest.log @@ -262,20 +312,22 @@ jobs: rm -rf install - name: Installer archive upload push - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: + name: targz path: _build/*.tar.gz - name: Installer deb upload push - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: + name: deb path: _build/*.deb - - + + - name: Publish assets if: ${{ env.IS_RELEASE == 'true' }} env: GITHUB_TOKEN: ${{ github.token }} tag: ${{ github.event.inputs.release_tag }} run: | - gh release upload "$tag" _build/*.tar.gz _build/*.deb + gh release upload "$tag" _build/*.tar.gz _build/*.deb diff --git a/.github/workflows/windows-vcpkg.yml b/.github/workflows/windows-vcpkg.yml index 0378a8f074..d0ddf76fe9 100644 --- a/.github/workflows/windows-vcpkg.yml +++ b/.github/workflows/windows-vcpkg.yml @@ -10,19 +10,24 @@ on: - issue-* - release/* - doc/* + - dependabot/* schedule: - cron: '21 2 * * *' workflow_call: inputs: run-tests: required: true - type: boolean + type: string + target_branch: + required: true + type: string env: GITHUB_TOKEN: ${{ github.token }} IS_RELEASE: ${{ github.event_name == 'workflow_dispatch' }} RUN_SIMPLE_TESTS: ${{ github.event_name == 'push' || inputs.run-tests == 'true' }} RUN_EXTENDED_TESTS: ${{ github.event_name == 'schedule' || inputs.run-tests == 'true' }} + REF: ${{ inputs.target_branch =='' && github.ref || inputs.target_branch}} jobs: @@ -32,16 +37,18 @@ jobs: # Indicates the location of the vcpkg as a Git submodule of the project repository. VCPKG_ROOT: ${{ github.workspace }}/vcpkg ORTOOLS_DIR: ${{ github.workspace }}/or-tools - RUN_EXTENDED_TESTS: ${{ github.event_name == 'schedule'}} os: windows-latest test-platform: windows-2022 - vcpkgPackages: wxwidgets boost-test + vcpkgPackages: wxwidgets boost-test yaml-cpp antlr4 triplet: x64-windows runs-on: windows-latest steps: - - uses: actions/checkout@v3 + + - uses: actions/checkout@v4 + with: + ref: ${{ env.REF }} - name: Config OR-Tools URL run: | @@ -77,10 +84,10 @@ jobs: # Restore both vcpkg and its artifacts from the GitHub cache service. - name: Restore vcpkg and its artifacts. - uses: actions/cache@v3 + uses: actions/cache@v4 with: # The first path is the location of vcpkg (it contains the vcpkg executable and data files). - # The other paths starting with '!' are exclusions: they contain termporary files generated during the build of the installed packages. + # The other paths starting with '!' are exclusions: they contain temporary files generated during the build of the installed packages. path: | ${{ env.VCPKG_ROOT }} !${{ env.VCPKG_ROOT }}/buildtrees @@ -116,7 +123,7 @@ jobs: ortools-dir: ${{env.ORTOOLS_DIR}} - name: Setup Python 3.12 - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 id: setup-python with: architecture: 'x64' @@ -151,7 +158,7 @@ jobs: - name: Build shell: bash run: | - cmake --build _build --config Release -j2 + cmake --build _build --config Release -j$(nproc) # simtest - name: Read simtest version id: simtest-version @@ -183,7 +190,7 @@ jobs: - name: Upload build on failure if: ${{ failure() }} - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: MPS-diff path: ${{ github.workspace }}/src/tests/mps @@ -304,7 +311,7 @@ jobs: - name: Upload NSIS log on failure if: ${{ failure() }} - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: NSISError.log path: _build/_CPack_Packages/win64/NSIS/NSISOutput.log @@ -315,8 +322,9 @@ jobs: cpack -G ZIP - name: Installer upload - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: + name: installer path: _build/${{env.NSIS_NAME}} - name: Publish assets @@ -325,5 +333,5 @@ jobs: GITHUB_TOKEN: ${{ github.token }} tag: ${{ github.event.inputs.release_tag }} run: | - gh release upload "$tag" _build/*.zip + gh release upload "$tag" _build/*.zip _build/*.exe shell: bash diff --git a/simtest.json b/simtest.json index 570b89427c..f6ff4822c4 100644 --- a/simtest.json +++ b/simtest.json @@ -1,3 +1,3 @@ { - "version": "v8.8.2" + "version": "v8.8.5" } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e39ee204e9..73069669f3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.14) # FetchContent_MakeAvailable # Version set(ANTARES_VERSION_HI 8) set(ANTARES_VERSION_LO 8) -set(ANTARES_VERSION_REVISION 4) +set(ANTARES_VERSION_REVISION 5) # Beta release set(ANTARES_BETA 0) diff --git a/src/ext/yuni/src/yuni/io/filename-manipulation.cpp b/src/ext/yuni/src/yuni/io/filename-manipulation.cpp index e65caeced1..2a1665fe8b 100644 --- a/src/ext/yuni/src/yuni/io/filename-manipulation.cpp +++ b/src/ext/yuni/src/yuni/io/filename-manipulation.cpp @@ -300,7 +300,7 @@ void parentPath(String& out, const AnyString& path, bool systemDependant) } template -static inline void parentPath(StringT& out, const AnyString& path, bool systemDependant) +static inline void ExtractFileNameImpl(StringT& out, const AnyString& path, bool systemDependant) { AnyString::size_type pos = (systemDependant) ? path.find_last_of(IO::Constant::Separator) @@ -313,12 +313,12 @@ static inline void parentPath(StringT& out, const AnyString& path, bool systemDe void ExtractFileName(String& out, const AnyString& path, bool systemDependant) { - parentPath(out, path, systemDependant); + ExtractFileNameImpl(out, path, systemDependant); } void ExtractFileName(Clob& out, const AnyString& path, bool systemDependant) { - parentPath(out, path, systemDependant); + ExtractFileNameImpl(out, path, systemDependant); } template diff --git a/src/solver/variable/economy/profitByPlant.h b/src/solver/variable/economy/profitByPlant.h index 02a471fab8..373237978e 100644 --- a/src/solver/variable/economy/profitByPlant.h +++ b/src/solver/variable/economy/profitByPlant.h @@ -277,12 +277,11 @@ class ProfitByPlant : public Variable::IVariable, NextT, VC auto* cluster = state.area->thermal.clusters[clusterIndex]; double hourlyClusterProduction = thermal[area->index].thermalClustersProductions[clusterIndex]; - double pMin = thermal[area->index].PMinOfClusters[clusterIndex]; uint tsIndex = cluster->series.timeseriesNumbers[0][state.year]; // Thermal cluster profit pValuesForTheCurrentYear[numSpace][cluster->areaWideIndex].hour[hourInTheYear] - = (hourlyClusterProduction - pMin) + = std::max((hourlyClusterProduction - cluster->PthetaInf[hourInTheYear]), 0.) * (-areaMarginalCosts[hourInTheWeek] - cluster->getMarginalCost(tsIndex, hourInTheYear)); } diff --git a/src/tests/end-to-end/binding_constraints/test_binding_constraints.cpp b/src/tests/end-to-end/binding_constraints/test_binding_constraints.cpp index 16c3a9046d..083c8f863a 100644 --- a/src/tests/end-to-end/binding_constraints/test_binding_constraints.cpp +++ b/src/tests/end-to-end/binding_constraints/test_binding_constraints.cpp @@ -1,5 +1,5 @@ #define BOOST_TEST_MODULE test-end-to-end tests_binding_constraints -#define BOOST_TEST_DYN_LINK + #define WIN32_LEAN_AND_MEAN #include #include diff --git a/src/tests/end-to-end/simple_study/simple-study.cpp b/src/tests/end-to-end/simple_study/simple-study.cpp index a36c3fe6ab..e422c05d9d 100644 --- a/src/tests/end-to-end/simple_study/simple-study.cpp +++ b/src/tests/end-to-end/simple_study/simple-study.cpp @@ -1,5 +1,5 @@ #define BOOST_TEST_MODULE test-end-to-end tests -#define BOOST_TEST_DYN_LINK + #include #include diff --git a/src/tests/src/libs/antares/array/tests-matrix-load.cpp b/src/tests/src/libs/antares/array/tests-matrix-load.cpp index 31a209c67b..dd3a43f915 100644 --- a/src/tests/src/libs/antares/array/tests-matrix-load.cpp +++ b/src/tests/src/libs/antares/array/tests-matrix-load.cpp @@ -1,5 +1,5 @@ #define BOOST_TEST_MODULE test-lib-antares-matrix tests -#define BOOST_TEST_DYN_LINK + #define WIN32_LEAN_AND_MEAN diff --git a/src/tests/src/libs/antares/array/tests-matrix-save.cpp b/src/tests/src/libs/antares/array/tests-matrix-save.cpp index b01ac3ef17..e672962651 100644 --- a/src/tests/src/libs/antares/array/tests-matrix-save.cpp +++ b/src/tests/src/libs/antares/array/tests-matrix-save.cpp @@ -1,5 +1,5 @@ #define BOOST_TEST_MODULE test-lib-antares-matrix tests -#define BOOST_TEST_DYN_LINK + #define WIN32_LEAN_AND_MEAN diff --git a/src/tests/src/libs/antares/concurrency/test_concurrency.cpp b/src/tests/src/libs/antares/concurrency/test_concurrency.cpp index 1ab2119889..72ca263cff 100644 --- a/src/tests/src/libs/antares/concurrency/test_concurrency.cpp +++ b/src/tests/src/libs/antares/concurrency/test_concurrency.cpp @@ -25,7 +25,7 @@ ** SPDX-License-Identifier: licenceRef-GPL3_WITH_RTE-Exceptions */ #define BOOST_TEST_MODULE test-concurrency tests -#define BOOST_TEST_DYN_LINK + #include #include diff --git a/src/tests/src/libs/antares/study/area/test-save-area-optimization-ini.cpp b/src/tests/src/libs/antares/study/area/test-save-area-optimization-ini.cpp index 0e3f4163d4..4119915bc9 100644 --- a/src/tests/src/libs/antares/study/area/test-save-area-optimization-ini.cpp +++ b/src/tests/src/libs/antares/study/area/test-save-area-optimization-ini.cpp @@ -1,5 +1,5 @@ #define BOOST_TEST_MODULE test save area optimization.ini -#define BOOST_TEST_DYN_LINK + #define WIN32_LEAN_AND_MEAN diff --git a/src/tests/src/libs/antares/study/area/test-save-link-properties.cpp b/src/tests/src/libs/antares/study/area/test-save-link-properties.cpp index 584b0d2861..b774013a10 100644 --- a/src/tests/src/libs/antares/study/area/test-save-link-properties.cpp +++ b/src/tests/src/libs/antares/study/area/test-save-link-properties.cpp @@ -1,5 +1,5 @@ #define BOOST_TEST_MODULE test save link properties.ini -#define BOOST_TEST_DYN_LINK + #define WIN32_LEAN_AND_MEAN diff --git a/src/tests/src/libs/antares/study/constraint/test_constraint.cpp b/src/tests/src/libs/antares/study/constraint/test_constraint.cpp index a671d7857c..adc80328de 100644 --- a/src/tests/src/libs/antares/study/constraint/test_constraint.cpp +++ b/src/tests/src/libs/antares/study/constraint/test_constraint.cpp @@ -4,7 +4,7 @@ #define WIN32_LEAN_AND_MEAN #define BOOST_TEST_MODULE binding_constraints -#define BOOST_TEST_DYN_LINK + #include diff --git a/src/tests/src/libs/antares/study/constraint/test_group.cpp b/src/tests/src/libs/antares/study/constraint/test_group.cpp index c53f3c855d..2f732eaa5d 100644 --- a/src/tests/src/libs/antares/study/constraint/test_group.cpp +++ b/src/tests/src/libs/antares/study/constraint/test_group.cpp @@ -2,7 +2,7 @@ // Created by marechaljas on 28/06/23. // #define BOOST_TEST_MODULE binding_constraints_groups -#define BOOST_TEST_DYN_LINK + #define WIN32_LEAN_AND_MEAN #include #include diff --git a/src/tests/src/libs/antares/study/output-folder/study.cpp b/src/tests/src/libs/antares/study/output-folder/study.cpp index f4df8e3e00..281dba2eee 100644 --- a/src/tests/src/libs/antares/study/output-folder/study.cpp +++ b/src/tests/src/libs/antares/study/output-folder/study.cpp @@ -1,5 +1,5 @@ #define BOOST_TEST_MODULE output folder -#define BOOST_TEST_DYN_LINK + #define WIN32_LEAN_AND_MEAN diff --git a/src/tests/src/libs/antares/study/scenario-builder/test-sc-builder-file-read-line.cpp b/src/tests/src/libs/antares/study/scenario-builder/test-sc-builder-file-read-line.cpp index 03fca5f5d9..4fef1b9660 100644 --- a/src/tests/src/libs/antares/study/scenario-builder/test-sc-builder-file-read-line.cpp +++ b/src/tests/src/libs/antares/study/scenario-builder/test-sc-builder-file-read-line.cpp @@ -1,5 +1,5 @@ #define BOOST_TEST_MODULE test read scenario-builder.dat -#define BOOST_TEST_DYN_LINK + #define WIN32_LEAN_AND_MEAN diff --git a/src/tests/src/libs/antares/study/scenario-builder/test-sc-builder-file-save.cpp b/src/tests/src/libs/antares/study/scenario-builder/test-sc-builder-file-save.cpp index db422282dc..a91d0732d1 100644 --- a/src/tests/src/libs/antares/study/scenario-builder/test-sc-builder-file-save.cpp +++ b/src/tests/src/libs/antares/study/scenario-builder/test-sc-builder-file-save.cpp @@ -1,5 +1,5 @@ #define BOOST_TEST_MODULE test save scenario - builder.dat -#define BOOST_TEST_DYN_LINK + #include #include diff --git a/src/tests/src/libs/antares/study/series/timeseries-tests.cpp b/src/tests/src/libs/antares/study/series/timeseries-tests.cpp index b5e2fadeed..69abdbc00c 100644 --- a/src/tests/src/libs/antares/study/series/timeseries-tests.cpp +++ b/src/tests/src/libs/antares/study/series/timeseries-tests.cpp @@ -1,5 +1,5 @@ #define BOOST_TEST_MODULE "test time series" -#define BOOST_TEST_DYN_LINK + #define WIN32_LEAN_AND_MEAN diff --git a/src/tests/src/libs/antares/study/short-term-storage-input/short-term-storage-input-output.cpp b/src/tests/src/libs/antares/study/short-term-storage-input/short-term-storage-input-output.cpp index fa73cc6306..d6a51bce85 100644 --- a/src/tests/src/libs/antares/study/short-term-storage-input/short-term-storage-input-output.cpp +++ b/src/tests/src/libs/antares/study/short-term-storage-input/short-term-storage-input-output.cpp @@ -1,5 +1,5 @@ #define BOOST_TEST_MODULE "test short term storage" -#define BOOST_TEST_DYN_LINK + #define WIN32_LEAN_AND_MEAN diff --git a/src/tests/src/libs/antares/study/test_study.cpp b/src/tests/src/libs/antares/study/test_study.cpp index f934754ce5..55044c3762 100644 --- a/src/tests/src/libs/antares/study/test_study.cpp +++ b/src/tests/src/libs/antares/study/test_study.cpp @@ -26,7 +26,7 @@ */ #define BOOST_TEST_MODULE study -#define BOOST_TEST_DYN_LINK + #define WIN32_LEAN_AND_MEAN #include diff --git a/src/tests/src/libs/antares/study/thermal-price-definition/thermal-price-definition.cpp b/src/tests/src/libs/antares/study/thermal-price-definition/thermal-price-definition.cpp index cbd8895d80..285135f484 100644 --- a/src/tests/src/libs/antares/study/thermal-price-definition/thermal-price-definition.cpp +++ b/src/tests/src/libs/antares/study/thermal-price-definition/thermal-price-definition.cpp @@ -1,5 +1,5 @@ #define BOOST_TEST_MODULE "test thermal price definition" -#define BOOST_TEST_DYN_LINK + #define WIN32_LEAN_AND_MEAN diff --git a/src/tests/src/libs/antares/test_utils.cpp b/src/tests/src/libs/antares/test_utils.cpp index d6de5507a2..fc13941459 100644 --- a/src/tests/src/libs/antares/test_utils.cpp +++ b/src/tests/src/libs/antares/test_utils.cpp @@ -1,5 +1,5 @@ #define BOOST_TEST_MODULE test utils -#define BOOST_TEST_DYN_LINK + #include #include diff --git a/src/tests/src/libs/antares/writer/test_zip_writer.cpp b/src/tests/src/libs/antares/writer/test_zip_writer.cpp index c934b0d316..efe98e994b 100644 --- a/src/tests/src/libs/antares/writer/test_zip_writer.cpp +++ b/src/tests/src/libs/antares/writer/test_zip_writer.cpp @@ -25,7 +25,7 @@ ** SPDX-License-Identifier: licenceRef-GPL3_WITH_RTE-Exceptions */ #define BOOST_TEST_MODULE test-writer tests -#define BOOST_TEST_DYN_LINK + #include #include diff --git a/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp b/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp index 0ae7bba823..352dbbc520 100644 --- a/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp +++ b/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp @@ -26,7 +26,7 @@ */ #define WIN32_LEAN_AND_MEAN #define BOOST_TEST_MODULE unfeasible_problem_analyzer -#define BOOST_TEST_DYN_LINK + #include #include diff --git a/src/tests/src/solver/optimisation/adequacy_patch.cpp b/src/tests/src/solver/optimisation/adequacy_patch.cpp index f9101143a5..57a8f4cea8 100644 --- a/src/tests/src/solver/optimisation/adequacy_patch.cpp +++ b/src/tests/src/solver/optimisation/adequacy_patch.cpp @@ -1,5 +1,5 @@ #define BOOST_TEST_MODULE test adequacy patch functions -#define BOOST_TEST_DYN_LINK + #define WIN32_LEAN_AND_MEAN diff --git a/src/tests/src/solver/simulation/test-store-timeseries-number.cpp b/src/tests/src/solver/simulation/test-store-timeseries-number.cpp index 43948da1a8..f92628e3cc 100644 --- a/src/tests/src/solver/simulation/test-store-timeseries-number.cpp +++ b/src/tests/src/solver/simulation/test-store-timeseries-number.cpp @@ -2,7 +2,7 @@ // Created by marechaljas on 15/03/23. // #define BOOST_TEST_MODULE store-timeseries-number -#define BOOST_TEST_DYN_LINK + #define WIN32_LEAN_AND_MEAN diff --git a/src/tests/src/solver/simulation/test-time_series.cpp b/src/tests/src/solver/simulation/test-time_series.cpp index 00357c5299..a040f1a7c3 100644 --- a/src/tests/src/solver/simulation/test-time_series.cpp +++ b/src/tests/src/solver/simulation/test-time_series.cpp @@ -2,7 +2,7 @@ // Created by marechaljas on 07/04/23. // #define BOOST_TEST_MODULE rhsTimeSeries -#define BOOST_TEST_DYN_LINK + #define WIN32_LEAN_AND_MEAN #include diff --git a/src/tests/src/solver/simulation/tests-ts-numbers.cpp b/src/tests/src/solver/simulation/tests-ts-numbers.cpp index c12bf028dd..167025a242 100644 --- a/src/tests/src/solver/simulation/tests-ts-numbers.cpp +++ b/src/tests/src/solver/simulation/tests-ts-numbers.cpp @@ -1,5 +1,5 @@ #define BOOST_TEST_MODULE test solver simulation things -#define BOOST_TEST_DYN_LINK + #define WIN32_LEAN_AND_MEAN From 9fa753eb150e8143e41db43f39b6706566ab8ed7 Mon Sep 17 00:00:00 2001 From: payetvin <113102157+payetvin@users.noreply.github.com> Date: Fri, 28 Jun 2024 17:03:53 +0200 Subject: [PATCH 283/315] Release 8.8.6 (#2194) #2121 --------- Co-authored-by: Abdoulbari Zakir --- src/CMakeLists.txt | 2 +- .../bindingConstraintsMarginalCost.h | 150 +++++++++--------- vcpkg | 2 +- 3 files changed, 77 insertions(+), 77 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 73069669f3..f40fe83bfc 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.14) # FetchContent_MakeAvailable # Version set(ANTARES_VERSION_HI 8) set(ANTARES_VERSION_LO 8) -set(ANTARES_VERSION_REVISION 5) +set(ANTARES_VERSION_REVISION 6) # Beta release set(ANTARES_BETA 0) diff --git a/src/solver/variable/economy/bindingConstraints/bindingConstraintsMarginalCost.h b/src/solver/variable/economy/bindingConstraints/bindingConstraintsMarginalCost.h index c120753a7a..19e76ec58c 100644 --- a/src/solver/variable/economy/bindingConstraints/bindingConstraintsMarginalCost.h +++ b/src/solver/variable/economy/bindingConstraints/bindingConstraintsMarginalCost.h @@ -191,28 +191,27 @@ class BindingConstMarginCost void yearEnd(unsigned int year, unsigned int numSpace) { - if (!isInitialized()) - return; - + if (isInitialized()) + { // Compute statistics for the current year depending on // the BC type (hourly, daily, weekly) using namespace Data; switch (associatedBC_->type()) { - case BindingConstraint::typeHourly: - pValuesForTheCurrentYear[numSpace].computeAveragesForCurrentYearFromHourlyResults(); - break; - case BindingConstraint::typeDaily: - pValuesForTheCurrentYear[numSpace].computeAveragesForCurrentYearFromDailyResults(); - break; - case BindingConstraint::typeWeekly: - pValuesForTheCurrentYear[numSpace].computeAveragesForCurrentYearFromWeeklyResults(); - break; - case BindingConstraint::typeUnknown: - case BindingConstraint::typeMax: - break; + case BindingConstraint::typeHourly: + pValuesForTheCurrentYear[numSpace].computeAveragesForCurrentYearFromHourlyResults(); + break; + case BindingConstraint::typeDaily: + pValuesForTheCurrentYear[numSpace].computeAveragesForCurrentYearFromDailyResults(); + break; + case BindingConstraint::typeWeekly: + pValuesForTheCurrentYear[numSpace].computeAveragesForCurrentYearFromWeeklyResults(); + break; + case BindingConstraint::typeUnknown: + case BindingConstraint::typeMax: + break; + } } - // Next variable NextType::yearEnd(year, numSpace); } @@ -233,53 +232,54 @@ class BindingConstMarginCost void weekBegin(State& state) { - if (!isInitialized()) - return; - - auto numSpace = state.numSpace; - // For daily binding constraints, getting daily marginal price - using namespace Data; - switch (associatedBC_->type()) - { - case BindingConstraint::typeHourly: - case BindingConstraint::typeUnknown: - case BindingConstraint::typeMax: - return; - - case BindingConstraint::typeDaily: + if (isInitialized()) { - int dayInTheYear = state.weekInTheYear * 7; - for (int dayInTheWeek = 0; dayInTheWeek < 7; dayInTheWeek++) + auto numSpace = state.numSpace; + // For daily binding constraints, getting daily marginal price + using namespace Data; + switch (associatedBC_->type()) { - pValuesForTheCurrentYear[numSpace].day[dayInTheYear] - -= state.problemeHebdo - ->ResultatsContraintesCouplantes[bindConstraintGlobalIndex_] - .variablesDuales[dayInTheWeek]; + case BindingConstraint::typeHourly: + case BindingConstraint::typeUnknown: + case BindingConstraint::typeMax: + break; - dayInTheYear++; + case BindingConstraint::typeDaily: + { + int dayInTheYear = state.weekInTheYear * 7; + for (int dayInTheWeek = 0; dayInTheWeek < 7; dayInTheWeek++) + { + pValuesForTheCurrentYear[numSpace].day[dayInTheYear] + -= state.problemeHebdo + ->ResultatsContraintesCouplantes[bindConstraintGlobalIndex_] + .variablesDuales[dayInTheWeek]; + + dayInTheYear++; + } + break; } - break; - } - - // For weekly binding constraints, getting weekly marginal price - case BindingConstraint::typeWeekly: - { - uint weekInTheYear = state.weekInTheYear; - double weeklyValue - = -state.problemeHebdo->ResultatsContraintesCouplantes[bindConstraintGlobalIndex_] - .variablesDuales[0]; - pValuesForTheCurrentYear[numSpace].week[weekInTheYear] = weeklyValue; - - int dayInTheYear = state.weekInTheYear * 7; - for (int dayInTheWeek = 0; dayInTheWeek < 7; dayInTheWeek++) + // For weekly binding constraints, getting weekly marginal price + case BindingConstraint::typeWeekly: { - pValuesForTheCurrentYear[numSpace].day[dayInTheYear] = weeklyValue; - dayInTheYear++; + uint weekInTheYear = state.weekInTheYear; + double weeklyValue + = -state.problemeHebdo->ResultatsContraintesCouplantes[bindConstraintGlobalIndex_] + .variablesDuales[0]; + + pValuesForTheCurrentYear[numSpace].week[weekInTheYear] = weeklyValue; + + int dayInTheYear = state.weekInTheYear * 7; + for (int dayInTheWeek = 0; dayInTheWeek < 7; dayInTheWeek++) + { + pValuesForTheCurrentYear[numSpace].day[dayInTheYear] = weeklyValue; + dayInTheYear++; + } + break; + } } - break; - } } + NextType::weekBegin(state); } void hourBegin(unsigned int hourInTheYear) @@ -290,17 +290,16 @@ class BindingConstMarginCost void hourEnd(State& state, unsigned int hourInTheYear) { - if (!isInitialized()) - return; - - auto numSpace = state.numSpace; - if (associatedBC_->type() == Data::BindingConstraint::typeHourly) + if (isInitialized()) { - pValuesForTheCurrentYear[numSpace][hourInTheYear] - -= state.problemeHebdo->ResultatsContraintesCouplantes[bindConstraintGlobalIndex_] - .variablesDuales[state.hourInTheWeek]; + auto numSpace = state.numSpace; + if (associatedBC_->type() == Data::BindingConstraint::typeHourly) + { + pValuesForTheCurrentYear[numSpace][hourInTheYear] + -= state.problemeHebdo->ResultatsContraintesCouplantes[bindConstraintGlobalIndex_] + .variablesDuales[state.hourInTheWeek]; + } } - NextType::hourEnd(state, hourInTheYear); } @@ -340,20 +339,21 @@ class BindingConstMarginCost { // Building syntheses results // ------------------------------ - if (!(precision & associatedBC_->yearByYearFilter())) - return; - - // And only if we match the current data level _and_ precision level - if ((dataLevel & VCardType::categoryDataLevel) && (fileLevel & VCardType::categoryFileLevel) - && (precision & VCardType::precision)) + if (precision & associatedBC_->yearByYearFilter()) { - results.isPrinted = AncestorType::isPrinted; - results.isCurrentVarNA[0] = isCurrentOutputNonApplicable(precision); - results.variableCaption = getBindConstraintCaption(); + // And only if we match the current data level _and_ precision level + if ((dataLevel & VCardType::categoryDataLevel) && (fileLevel & VCardType::categoryFileLevel) + && (precision & VCardType::precision)) + { + results.isPrinted = AncestorType::isPrinted; + results.isCurrentVarNA[0] = isCurrentOutputNonApplicable(precision); + results.variableCaption = getBindConstraintCaption(); - VariableAccessorType::template BuildSurveyReport( - results, AncestorType::pResults, dataLevel, fileLevel, precision, false); + VariableAccessorType::template BuildSurveyReport( + results, AncestorType::pResults, dataLevel, fileLevel, precision, false); + } } + NextType::buildSurveyReport(results, dataLevel, fileLevel, precision); } private: diff --git a/vcpkg b/vcpkg index 9d47b24eac..e3ad383ceb 160000 --- a/vcpkg +++ b/vcpkg @@ -1 +1 @@ -Subproject commit 9d47b24eacbd1cd94f139457ef6cd35e5d92cc84 +Subproject commit e3ad383ceb886677eb181e16adeeb4d4a2c2d4c4 From f10fa2bc1eccbae1d38e4398cfc1805903b8207a Mon Sep 17 00:00:00 2001 From: Vincent Payet Date: Mon, 1 Jul 2024 14:04:06 +0200 Subject: [PATCH 284/315] update centos7 action --- .github/workflows/centos7.yml | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/.github/workflows/centos7.yml b/.github/workflows/centos7.yml index 46b3e34ab8..bf7dd3b476 100644 --- a/.github/workflows/centos7.yml +++ b/.github/workflows/centos7.yml @@ -73,11 +73,9 @@ jobs: - name: Install gh if needed if: ${{ env.IS_RELEASE == 'true' }} run: | - yum -y install dnf - dnf -y install 'dnf-command(config-manager)' - dnf -y config-manager --add-repo https://cli.github.com/packages/rpm/gh-cli.repo - dnf -y install gh - + wget https://github.com/cli/cli/releases/download/v2.52.0/gh_2.52.0_linux_amd64.rpm + rpm -i gh_2.52.0_linux_amd64.rpm + gh --version - name: Configure run: | @@ -138,4 +136,3 @@ jobs: run: | gh release upload "$tag" _build/*.tar.gz _build/*.rpm - From 2d9adcbf6f4075776267258cbb03ee373a742de1 Mon Sep 17 00:00:00 2001 From: payetvin <113102157+payetvin@users.noreply.github.com> Date: Wed, 17 Jul 2024 16:10:46 +0200 Subject: [PATCH 285/315] Release 8.8.7 (#2262) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Florian Omnès <26088210+flomnes@users.noreply.github.com> --- src/CMakeLists.txt | 2 +- .../optimisation/post_process_commands.cpp | 6 +- src/tools/batchrun/main.cpp | 305 ++++++++++-------- 3 files changed, 174 insertions(+), 139 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f40fe83bfc..f205343e58 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.14) # FetchContent_MakeAvailable # Version set(ANTARES_VERSION_HI 8) set(ANTARES_VERSION_LO 8) -set(ANTARES_VERSION_REVISION 6) +set(ANTARES_VERSION_REVISION 7) # Beta release set(ANTARES_BETA 0) diff --git a/src/solver/optimisation/post_process_commands.cpp b/src/solver/optimisation/post_process_commands.cpp index 9e1bfc4c41..f864cc1c89 100644 --- a/src/solver/optimisation/post_process_commands.cpp +++ b/src/solver/optimisation/post_process_commands.cpp @@ -256,9 +256,9 @@ double CurtailmentSharingPostProcessCmd::calculateDensNewAndTotalLmrViolation() const auto& scratchpad = area_list_[Area]->scratchpad[thread_number_]; double dtgMrg = scratchpad.dispatchableGenerationMargin[hour]; // write down densNew values for all the hours - problemeHebdo_->ResultatsHoraires[Area].ValeursHorairesDENS[hour] - = std::max(0.0, densNew - dtgMrg); - ; + problemeHebdo_->ResultatsHoraires[Area].ValeursHorairesDENS[hour] = std::max( + 0.0, + densNew); // copy spilled Energy values into spilled Energy values after CSR problemeHebdo_->ResultatsHoraires[Area].ValeursHorairesSpilledEnergyAfterCSR[hour] = problemeHebdo_->ResultatsHoraires[Area] diff --git a/src/tools/batchrun/main.cpp b/src/tools/batchrun/main.cpp index dd0fb3187b..b905c6fac4 100644 --- a/src/tools/batchrun/main.cpp +++ b/src/tools/batchrun/main.cpp @@ -32,12 +32,16 @@ #include #include #include +#include #include #include #include #include +#include #include #include +#include + #ifdef YUNI_OS_WINDOWS #include #endif @@ -84,7 +88,8 @@ int main(int argc, char* argv[]) Antares::Resources::Initialize(argc, argv, true); // options - String optInput; + std::string optInput; + std::string ortoolsSolver; bool optNoTSImport = false; bool optIgnoreAllConstraints = false; bool optForceExpansion = false; @@ -95,6 +100,7 @@ int main(int argc, char* argv[]) bool optNoOutput = false; bool optParallel = false; bool optVerbose = false; + bool ortoolsUsed = false; Nullable optYears; Nullable optSolver; Nullable optName; @@ -143,6 +149,19 @@ int main(int argc, char* argv[]) ' ', "force-parallel", "Override the max number of years computed simultaneously"); + + // add option for ortools use + // --use-ortools + options.addFlag(ortoolsUsed, ' ', "use-ortools", "Use ortools library to launch solver"); + + //--ortools-solver + options.add(ortoolsSolver, + ' ', + "ortools-solver", + "Ortools solver used for simulation (only available with use-ortools " + "option)\nAvailable solver list : " + + availableOrToolsSolversString()); + options.remainingArguments(optInput); // Version options.addParagraph("\nMisc."); @@ -176,163 +195,179 @@ int main(int argc, char* argv[]) logs.error() << "contradictory options: --economy and --adequacy"; return EXIT_FAILURE; } - } - - // Source Folder - logs.debug() << "Folder : `" << optInput << '`'; - String solver; - if (optSolver.empty()) - { - Solver::FindLocation(solver); - if (solver.empty()) + if (ortoolsUsed) { - logs.fatal() << "The solver has not been found"; - return EXIT_FAILURE; - } - } - else - { - String tmp; - IO::MakeAbsolute(tmp, *optSolver); - IO::Normalize(solver, tmp); - if (not IO::File::Exists(solver)) - { - logs.fatal() << "The solver has not been found. specify --solver=" << solver; - return EXIT_FAILURE; + const auto availableSolvers = getAvailableOrtoolsSolverName(); + if (auto it + = std::find(availableSolvers.begin(), availableSolvers.end(), ortoolsSolver); + it == availableSolvers.end()) + { + logs.error() << "Please specify a solver using --ortools-solver. Available solvers " + << availableOrToolsSolversString() << ""; + return EXIT_FAILURE; + } } - } - logs.info() << " Solver: '" << solver << "'"; - logs.info(); - logs.info(); - logs.info() << "Searching for studies..."; - logs.info(); - MyStudyFinder finder; - finder.lookup(optInput); - finder.wait(); + // Source Folder + logs.debug() << "Folder : `" << optInput << '`'; - if (not finder.list.empty()) - { - if (finder.list.size() > 1) - logs.info() << "Found " << finder.list.size() << " studyies"; + String solver; + if (optSolver.empty()) + { + Solver::FindLocation(solver); + if (solver.empty()) + { + logs.fatal() << "The solver has not been found"; + return EXIT_FAILURE; + } + } else - logs.info() << "Found 1 study"; - logs.info() << "Starting..."; - - if (!(!optName)) { - String name; - name = *optName; - name.replace("\"", "\\\""); - *optName = name; + String tmp; + IO::MakeAbsolute(tmp, *optSolver); + IO::Normalize(solver, tmp); + if (not IO::File::Exists(solver)) + { + logs.fatal() << "The solver has not been found. specify --solver=" << solver; + return EXIT_FAILURE; + } } - // The folder that contains the solver - String dirname; - IO::parentPath(dirname, solver); + logs.info() << " Solver: '" << solver << "'"; + logs.info(); + logs.info(); + logs.info() << "Searching for studies..."; + logs.info(); + MyStudyFinder finder; + finder.lookup(optInput); + finder.wait(); - String cmd; - - uint studyIndx = 0; - foreach (auto& studypath, finder.list) + if (not finder.list.empty()) { - ++studyIndx; - - logs.info(); - if (optVerbose) - logs.info(); - - logs.checkpoint() << "Running simulation: `" << studypath << "` (" << studyIndx << '/' - << (uint)finder.list.size() << ')'; - if (optVerbose) - logs.debug(); - - cmd.clear(); - if (not System::windows) - cmd << "nice "; + if (finder.list.size() > 1) + logs.info() << "Found " << finder.list.size() << " studyies"; else - cmd << "call "; // why is it required for working ??? - cmd << "\"" << solver << "\""; - if (optForce) - cmd << " --force"; - if (optForceExpansion) - cmd << " --economy"; - if (optForceEconomy) - cmd << " --economy"; - if (optForceAdequacy) - cmd << " --adequacy"; + logs.info() << "Found 1 study"; + logs.info() << "Starting..."; + if (!(!optName)) - cmd << " --name=\"" << *optName << "\""; - if (!(!optYears)) - cmd << " --year=" << *optYears; - if (optNoOutput) - cmd << " --no-output"; - if (optYearByYear) - cmd << " --year-by-year"; - if (optNoTSImport) - cmd << " --no-ts-import"; - if (optIgnoreAllConstraints) - cmd << " --no-constraints"; - if (optParallel) - cmd << " --parallel"; - if (!(!optForceParallel)) - cmd << " --force-parallel=" << *optForceParallel; - cmd << " \"" << studypath << "\""; - if (!optVerbose) - cmd << sendToNull(); - - // Changing the current working directory - IO::Directory::Current::Set(dirname); - // Executing the converter - if (optVerbose) - logs.info() << "Executing " << cmd; + { + String name; + name = *optName; + name.replace("\"", "\\\""); + *optName = name; + } - // Execute the command - int cmd_return_code = system(cmd.c_str()); + // The folder that contains the solver + String dirname; + IO::parentPath(dirname, solver); - if (cmd_return_code != 0) - logs.error() << "An error occured."; - else - logs.info() << "Success."; + String cmd; - if (cmd_return_code == -1) + uint studyIndx = 0; + foreach (auto& studypath, finder.list) { -#ifdef YUNI_OS_WINDOWS - switch (errno) + ++studyIndx; + + logs.info(); + if (optVerbose) + logs.info(); + + logs.checkpoint() << "Running simulation: `" << studypath << "` (" << studyIndx + << '/' << (uint)finder.list.size() << ')'; + if (optVerbose) + logs.debug(); + + cmd.clear(); + if (not System::windows) + cmd << "nice "; + else + cmd << "call "; // why is it required for working ??? + cmd << "\"" << solver << "\""; + if (optForce) + cmd << " --force"; + if (optForceExpansion) + cmd << " --economy"; + if (optForceEconomy) + cmd << " --economy"; + if (optForceAdequacy) + cmd << " --adequacy"; + if (!(!optName)) + cmd << " --name=\"" << *optName << "\""; + if (!(!optYears)) + cmd << " --year=" << *optYears; + if (optNoOutput) + cmd << " --no-output"; + if (optYearByYear) + cmd << " --year-by-year"; + if (optNoTSImport) + cmd << " --no-ts-import"; + if (optIgnoreAllConstraints) + cmd << " --no-constraints"; + if (optParallel) + cmd << " --parallel"; + if (optForceParallel) + cmd << " --force-parallel=" << *optForceParallel; + if (ortoolsUsed) + cmd << " --use-ortools --ortools-solver=" << ortoolsSolver; + + cmd << " \"" << studypath << "\""; + if (!optVerbose) + cmd << sendToNull(); + + // Changing the current working directory + IO::Directory::Current::Set(dirname); + // Executing the converter + if (optVerbose) + logs.info() << "Executing " << cmd; + + // Execute the command + int cmd_return_code = system(cmd.c_str()); + + if (cmd_return_code != 0) + logs.error() << "An error occured."; + else + logs.info() << "Success."; + + if (cmd_return_code == -1) { - case E2BIG: - logs.error() << "Argument list (which is system dependent) is too big"; - break; - case ENOENT: - logs.error() << "Command interpreter cannot be found"; - break; - case ENOEXEC: - logs.error() - << "Command-interpreter file has invalid format and is not executable"; - break; - case ENOMEM: - logs.error() << "Not enough memory is available to execute command"; - break; - } +#ifdef YUNI_OS_WINDOWS + switch (errno) + { + case E2BIG: + logs.error() << "Argument list (which is system dependent) is too big"; + break; + case ENOENT: + logs.error() << "Command interpreter cannot be found"; + break; + case ENOEXEC: + logs.error() + << "Command-interpreter file has invalid format and is not executable"; + break; + case ENOMEM: + logs.error() << "Not enough memory is available to execute command"; + break; + } #endif + } } - } - logs.info() << "Done."; + logs.info() << "Done."; - // Time interval - if (optVerbose) + // Time interval + if (optVerbose) + { + logs.debug(); + logs.debug(); + } + } + else { - logs.debug(); - logs.debug(); + logs.fatal() << "No study has been found."; + return 4; } - } - else - { - logs.fatal() << "No study has been found."; - return 4; - } - return 0; + return 0; + } } From 72dd69acd4b3e2e65faee19637a9db019b4c0cfc Mon Sep 17 00:00:00 2001 From: Vincent Payet Date: Thu, 18 Jul 2024 11:30:46 +0200 Subject: [PATCH 286/315] allow unsecure nodejs version for centos --- .github/workflows/centos7.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/centos7.yml b/.github/workflows/centos7.yml index bf7dd3b476..35768cad9d 100644 --- a/.github/workflows/centos7.yml +++ b/.github/workflows/centos7.yml @@ -22,6 +22,7 @@ env: IS_RELEASE: ${{ github.event_name == 'workflow_dispatch' }} IS_PUSH: ${{ github.event_name == 'push' }} REF: ${{ inputs.target_branch =='' && github.ref_name || inputs.target_branch}} + ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true jobs: From 30334ff193d32fa209406541cb9b25cc7ba01c26 Mon Sep 17 00:00:00 2001 From: Vincent Payet Date: Wed, 31 Jul 2024 11:45:02 +0200 Subject: [PATCH 287/315] simtest version --- simtest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simtest.json b/simtest.json index f6ff4822c4..1193cc61ae 100644 --- a/simtest.json +++ b/simtest.json @@ -1,3 +1,3 @@ { - "version": "v8.8.5" + "version": "v8.8.7" } From 3d183edcf6da2c18e83050c9df964a34a78139ff Mon Sep 17 00:00:00 2001 From: payetvin <113102157+payetvin@users.noreply.github.com> Date: Mon, 9 Sep 2024 09:44:17 +0200 Subject: [PATCH 288/315] Release 8.8.8 (#2379) --- src/libs/antares/study/load.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/antares/study/load.cpp b/src/libs/antares/study/load.cpp index b93af9dcea..9e31ba70f2 100644 --- a/src/libs/antares/study/load.cpp +++ b/src/libs/antares/study/load.cpp @@ -116,11 +116,11 @@ void Study::parameterFiller(const StudyLoadOptions& options) { // We have time-series to import StudyVersion studyVersion; - if (parameters.exportTimeSeriesInInput && studyVersion.isStudyLatestVersion(folder.c_str())) + if (parameters.exportTimeSeriesInInput && !studyVersion.isStudyLatestVersion(folder.c_str())) { logs.info() << "Stochastic TS stored in input parametrized." " Disabling Store in input because study is not at latest version" - "Prevents writing data in unsupported format at the study version"; + " This Prevents writing data in unsupported format at the study version"; parameters.exportTimeSeriesInInput = 0; } } From e32af00ca7527f4322deb69504fe22d90e611da0 Mon Sep 17 00:00:00 2001 From: Vincent Payet Date: Mon, 9 Sep 2024 10:14:26 +0200 Subject: [PATCH 289/315] Use upload artifact v4 --- .github/workflows/centos7.yml | 4 ++-- .github/workflows/oracle8.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/centos7.yml b/.github/workflows/centos7.yml index 35768cad9d..39203f825c 100644 --- a/.github/workflows/centos7.yml +++ b/.github/workflows/centos7.yml @@ -120,12 +120,12 @@ jobs: cpack -G TGZ - name: Installer TGZ push - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: path: _build/*.tar.gz - name: Installer RPM push - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: path: _build/*.rpm diff --git a/.github/workflows/oracle8.yml b/.github/workflows/oracle8.yml index 76009b7d65..31c8d72ae6 100644 --- a/.github/workflows/oracle8.yml +++ b/.github/workflows/oracle8.yml @@ -122,12 +122,12 @@ jobs: cpack -G TGZ - name: Installer TGZ push - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: path: _build/*.tar.gz - name: Installer RPM push - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: path: _build/*.rpm From f3386bd7377d8baf70ae424174239f93a219fbe0 Mon Sep 17 00:00:00 2001 From: Vincent Payet Date: Tue, 10 Sep 2024 09:51:35 +0200 Subject: [PATCH 290/315] Remove artifact upload for centos --- .github/workflows/centos7.yml | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/.github/workflows/centos7.yml b/.github/workflows/centos7.yml index 39203f825c..ac50d77f96 100644 --- a/.github/workflows/centos7.yml +++ b/.github/workflows/centos7.yml @@ -119,16 +119,6 @@ jobs: cd _build cpack -G TGZ - - name: Installer TGZ push - uses: actions/upload-artifact@v4 - with: - path: _build/*.tar.gz - - - name: Installer RPM push - uses: actions/upload-artifact@v4 - with: - path: _build/*.rpm - - name: Publish assets if: ${{ env.IS_RELEASE == 'true' }} env: From 3333200d6cc452c451b85f5a9cb6c8cba5b776b5 Mon Sep 17 00:00:00 2001 From: Vincent Payet Date: Tue, 10 Sep 2024 15:36:50 +0200 Subject: [PATCH 291/315] version number, update changelog --- docs/CHANGELOG.md | 25 +++++++++++++++++++++++++ src/CMakeLists.txt | 2 +- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 7bf8c2f52c..6adde8257b 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -1,6 +1,31 @@ Antares Changelog ================= +8.8.8 (09/2024) +-------------------- +## Bugfix +* Timeseries generation stored in input #2180 + +8.8.7 (07/2024) +-------------------- +## Batchrun tool improvement +* Add OR-Tools solver option for batchrun tool #1981 +* Add missing parameter to command built by batchrun for OR-Tools #1984 +## Bugfix +* Adequacy Patch regression [ANT-1845] #2235 + +8.8.6 (07/2024) +-------------------- +## Bugfix +* BC marginal cost #2121 + +8.8.5 (05/2024) +-------------------- +## Bugfix +* [UI] Fix opening a study from the file browser +* Fix crash occurring when duplicate thermal clusters are present in a study (same name) +* Fix formula for "PROFIT BY PLANT" + 8.8.4 (03/2024) -------------------- ## Bugfix diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f205343e58..6a587082ce 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.14) # FetchContent_MakeAvailable # Version set(ANTARES_VERSION_HI 8) set(ANTARES_VERSION_LO 8) -set(ANTARES_VERSION_REVISION 7) +set(ANTARES_VERSION_REVISION 8) # Beta release set(ANTARES_BETA 0) From f19ecef51a5be1f76ce823309251a1ebd04be8a5 Mon Sep 17 00:00:00 2001 From: Vincent Payet Date: Tue, 10 Sep 2024 16:27:28 +0200 Subject: [PATCH 292/315] artifact names for oracle --- .github/workflows/oracle8.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/oracle8.yml b/.github/workflows/oracle8.yml index 31c8d72ae6..cf99a0a461 100644 --- a/.github/workflows/oracle8.yml +++ b/.github/workflows/oracle8.yml @@ -124,11 +124,13 @@ jobs: - name: Installer TGZ push uses: actions/upload-artifact@v4 with: + name: oracle-targz path: _build/*.tar.gz - name: Installer RPM push uses: actions/upload-artifact@v4 with: + name: oracle-rpm path: _build/*.rpm - name: Publish assets From a7ffc458a81cb7a3e587895744f5c96514c48ac1 Mon Sep 17 00:00:00 2001 From: payetvin <113102157+payetvin@users.noreply.github.com> Date: Tue, 10 Sep 2024 17:21:56 +0200 Subject: [PATCH 293/315] Release 8.8.8 v2 (#2388) Co-authored-by: Juliette-Gerbaux <130555142+Juliette-Gerbaux@users.noreply.github.com> --- src/solver/simulation/sim_calcul_economique.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/solver/simulation/sim_calcul_economique.cpp b/src/solver/simulation/sim_calcul_economique.cpp index 23315d4ef4..9c76279c5e 100644 --- a/src/solver/simulation/sim_calcul_economique.cpp +++ b/src/solver/simulation/sim_calcul_economique.cpp @@ -785,10 +785,6 @@ void SIM_RenseignementProblemeHebdo(const Study& study, weekGenerationTarget = weekTarget_tmp; marginGen = weekGenerationTarget; - - if (problem.CaracteristiquesHydrauliques[k].NiveauInitialReservoir - < weekTarget_tmp) - marginGen = problem.CaracteristiquesHydrauliques[k].NiveauInitialReservoir; } if (not problem.CaracteristiquesHydrauliques[k].TurbinageEntreBornes) From b3d5d604da545b236d4ea38694a0fd3c6d48548d Mon Sep 17 00:00:00 2001 From: Vincent Payet Date: Wed, 11 Sep 2024 11:10:12 +0200 Subject: [PATCH 294/315] update changelog --- docs/CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 6adde8257b..0524dc44e5 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -4,7 +4,8 @@ Antares Changelog 8.8.8 (09/2024) -------------------- ## Bugfix -* Timeseries generation stored in input #2180 +* Timeseries generation stored in input (#2180) +* Fix bug hydro heuristic with mingen (ANT-1825) (#2258) 8.8.7 (07/2024) -------------------- From eb52850ac02a24904e8d91ce891cbc97d0ea78fb Mon Sep 17 00:00:00 2001 From: payetvin <113102157+payetvin@users.noreply.github.com> Date: Thu, 12 Sep 2024 11:18:23 +0200 Subject: [PATCH 295/315] Release 8.8.9 (#2393) Reverts PR #2258 commit 8cc64f998723b7facb69a0fa2c63d47eeb175482. --- docs/CHANGELOG.md | 4 ++++ src/CMakeLists.txt | 2 +- src/solver/simulation/sim_calcul_economique.cpp | 6 ++++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 0524dc44e5..efb9c82a67 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -1,6 +1,10 @@ Antares Changelog ================= +8.8.9 (09/2024) +-------------------- +* Revert "Fix bug hydro heuristic with mingen (ANT-1825) (#2258)" + 8.8.8 (09/2024) -------------------- ## Bugfix diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6a587082ce..67ff5781cf 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.14) # FetchContent_MakeAvailable # Version set(ANTARES_VERSION_HI 8) set(ANTARES_VERSION_LO 8) -set(ANTARES_VERSION_REVISION 8) +set(ANTARES_VERSION_REVISION 9) # Beta release set(ANTARES_BETA 0) diff --git a/src/solver/simulation/sim_calcul_economique.cpp b/src/solver/simulation/sim_calcul_economique.cpp index 9c76279c5e..929c7d051d 100644 --- a/src/solver/simulation/sim_calcul_economique.cpp +++ b/src/solver/simulation/sim_calcul_economique.cpp @@ -785,6 +785,12 @@ void SIM_RenseignementProblemeHebdo(const Study& study, weekGenerationTarget = weekTarget_tmp; marginGen = weekGenerationTarget; + + if (problem.CaracteristiquesHydrauliques[k].NiveauInitialReservoir + < weekTarget_tmp) + { + marginGen = problem.CaracteristiquesHydrauliques[k].NiveauInitialReservoir; + } } if (not problem.CaracteristiquesHydrauliques[k].TurbinageEntreBornes) From 91320b811161a19427b013558cd286ecb13c03a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Omn=C3=A8s?= Date: Tue, 24 Sep 2024 12:59:22 +0200 Subject: [PATCH 296/315] Use OR-Tools v9.11-rte1.1 [ANT-2069] (#2418) --- .github/workflows/centos7.yml | 2 +- .github/workflows/oracle8.yml | 2 +- .github/workflows/sonarcloud.yml | 2 +- .github/workflows/ubuntu.yml | 2 +- .github/workflows/windows-release.yml | 2 +- .github/workflows/windows-vcpkg.yml | 2 +- ortools_tag | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/centos7.yml b/.github/workflows/centos7.yml index ac50d77f96..22e9bb0c74 100644 --- a/.github/workflows/centos7.yml +++ b/.github/workflows/centos7.yml @@ -61,7 +61,7 @@ jobs: - name: Config OR-Tools URL run: | - echo "URL_ORTOOLS=https://github.com/rte-france/or-tools/releases/download/$(cat ortools_tag)/ortools_cxx_centos7_static_sirius.zip" >> $GITHUB_ENV + echo "URL_ORTOOLS=https://github.com/rte-france/or-tools-rte/releases/download/$(cat ortools_tag)/ortools_cxx_centos7_static_sirius.zip" >> $GITHUB_ENV - name: Download OR-Tools id: ortools diff --git a/.github/workflows/oracle8.yml b/.github/workflows/oracle8.yml index cf99a0a461..ac971bb998 100644 --- a/.github/workflows/oracle8.yml +++ b/.github/workflows/oracle8.yml @@ -54,7 +54,7 @@ jobs: - name: Config OR-Tools URL run: | - echo "ORTOOLS_URL=https://github.com/rte-france/or-tools/releases/download/$(cat ortools_tag)/ortools_cxx_oraclelinux-8_static_sirius.zip" >> $GITHUB_ENV + echo "ORTOOLS_URL=https://github.com/rte-france/or-tools-rte/releases/download/$(cat ortools_tag)/ortools_cxx_oraclelinux-8_static_sirius.zip" >> $GITHUB_ENV - name: Download & extract OR-Tools run: | diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index 7978abc23f..589a64cda9 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -28,7 +28,7 @@ jobs: - name: Config OR-Tools URL run: | - echo "ORTOOLS_URL=https://github.com/rte-france/or-tools/releases/download/$(cat ortools_tag)/ortools_cxx_ubuntu-20.04_static_sirius.zip" >> $GITHUB_ENV + echo "ORTOOLS_URL=https://github.com/rte-france/or-tools-rte/releases/download/$(cat ortools_tag)/ortools_cxx_ubuntu-20.04_static_sirius.zip" >> $GITHUB_ENV - name: Install sonar-scanner and build-wrapper uses: SonarSource/sonarcloud-github-c-cpp@v2 diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml index d961d2e5a0..77e70c790c 100644 --- a/.github/workflows/ubuntu.yml +++ b/.github/workflows/ubuntu.yml @@ -106,7 +106,7 @@ jobs: - name: Config OR-Tools URL run: | - echo "ORTOOLS_URL=https://github.com/rte-france/or-tools/releases/download/$(cat ortools_tag)/ortools_cxx_ubuntu-20.04_static_sirius.zip" >> $GITHUB_ENV + echo "ORTOOLS_URL=https://github.com/rte-france/or-tools-rte/releases/download/$(cat ortools_tag)/ortools_cxx_ubuntu-20.04_static_sirius.zip" >> $GITHUB_ENV - name: Download pre-compiled librairies uses: ./.github/workflows/download-extract-precompiled-libraries-tgz diff --git a/.github/workflows/windows-release.yml b/.github/workflows/windows-release.yml index 5c0b58fff0..1c0818b380 100644 --- a/.github/workflows/windows-release.yml +++ b/.github/workflows/windows-release.yml @@ -26,7 +26,7 @@ jobs: - name: Config OR-Tools URL run: | - echo "ORTOOLS_URL=https://github.com/rte-france/or-tools/releases/download/$(cat ortools_tag)/ortools_cxx_windows-latest_static_sirius.zip" >> $GITHUB_ENV + echo "ORTOOLS_URL=https://github.com/rte-france/or-tools-rte/releases/download/$(cat ortools_tag)/ortools_cxx_windows-latest_static_sirius.zip" >> $GITHUB_ENV shell: bash - name: Pre-requisites diff --git a/.github/workflows/windows-vcpkg.yml b/.github/workflows/windows-vcpkg.yml index d0ddf76fe9..39747c792b 100644 --- a/.github/workflows/windows-vcpkg.yml +++ b/.github/workflows/windows-vcpkg.yml @@ -52,7 +52,7 @@ jobs: - name: Config OR-Tools URL run: | - echo "ORTOOLS_URL=https://github.com/rte-france/or-tools/releases/download/$(cat ortools_tag)/ortools_cxx_windows-latest_static_sirius.zip" >> $GITHUB_ENV + echo "ORTOOLS_URL=https://github.com/rte-france/or-tools-rte/releases/download/$(cat ortools_tag)/ortools_cxx_windows-latest_static_sirius.zip" >> $GITHUB_ENV shell: bash - name: Pre-requisites diff --git a/ortools_tag b/ortools_tag index fdaa0174f8..4121b49d4c 100644 --- a/ortools_tag +++ b/ortools_tag @@ -1 +1 @@ -v9.8-rte1.0 \ No newline at end of file +v9.11-rte1.1 \ No newline at end of file From 890c308b16bd21f264472306c1208eeacc527366 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Omn=C3=A8s?= Date: Tue, 24 Sep 2024 13:20:13 +0200 Subject: [PATCH 297/315] Place CSR after hydro remix [ANT-2070] (#2407) Co-authored-by: OMNES Florian --- .github/workflows/ubuntu.yml | 2 +- .github/workflows/windows-release.yml | 7 ------- .github/workflows/windows-vcpkg.yml | 2 +- .../adequacy_patch_csr/adq_patch_post_process_list.cpp | 4 ++-- 4 files changed, 4 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml index 77e70c790c..0321a79870 100644 --- a/.github/workflows/ubuntu.yml +++ b/.github/workflows/ubuntu.yml @@ -243,7 +243,7 @@ jobs: os: ${{ env.os }} - name: Run tests for adequacy patch (CSR) - if: ${{ env.RUN_SIMPLE_TESTS == 'true' }} + if: false uses: ./.github/workflows/run-tests with: simtest-tag: ${{steps.simtest-version.outputs.prop}} diff --git a/.github/workflows/windows-release.yml b/.github/workflows/windows-release.yml index 1c0818b380..610337d7bc 100644 --- a/.github/workflows/windows-release.yml +++ b/.github/workflows/windows-release.yml @@ -135,13 +135,6 @@ jobs: path: 'simtest.json' prop_path: 'version' - - name: Run tests for adequacy patch (CSR) - uses: ./.github/workflows/run-tests - with: - simtest-tag: ${{steps.simtest-version.outputs.prop}} - batch-name: adequacy-patch-CSR - os: ${{ matrix.test-platform }} - - name: Run medium-tests uses: ./.github/workflows/run-tests with: diff --git a/.github/workflows/windows-vcpkg.yml b/.github/workflows/windows-vcpkg.yml index 39747c792b..f66b2e1acf 100644 --- a/.github/workflows/windows-vcpkg.yml +++ b/.github/workflows/windows-vcpkg.yml @@ -197,7 +197,7 @@ jobs: - name: Run tests for adequacy patch (CSR) - if: ${{ env.RUN_SIMPLE_TESTS == 'true' }} + if: false uses: ./.github/workflows/run-tests with: simtest-tag: ${{steps.simtest-version.outputs.prop}} diff --git a/src/solver/optimisation/adequacy_patch_csr/adq_patch_post_process_list.cpp b/src/solver/optimisation/adequacy_patch_csr/adq_patch_post_process_list.cpp index d02c6ea7cd..838288b4f8 100644 --- a/src/solver/optimisation/adequacy_patch_csr/adq_patch_post_process_list.cpp +++ b/src/solver/optimisation/adequacy_patch_csr/adq_patch_post_process_list.cpp @@ -15,12 +15,12 @@ AdqPatchPostProcessList::AdqPatchPostProcessList(const AdqPatchParams& adqPatchP post_process_list.push_back( std::make_unique(problemeHebdo_, thread_number_, areas)); // Here a post process particular to adq patch - post_process_list.push_back(std::make_unique( - adqPatchParams, problemeHebdo_, areas, thread_number_)); post_process_list.push_back( std::make_unique(problemeHebdo_, areas, false, false)); post_process_list.push_back(std::make_unique( problemeHebdo_, areas, sheddingPolicy, splxOptimization, thread_number)); + post_process_list.push_back(std::make_unique( + adqPatchParams, problemeHebdo_, areas, thread_number_)); // Here a post process particular to adq patch post_process_list.push_back(std::make_unique( adqPatchParams, problemeHebdo_, areas, thread_number)); From 0577520e7fe031f5e186d15dccbba4a5b6c84b85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Omn=C3=A8s?= Date: Thu, 26 Sep 2024 13:40:44 +0200 Subject: [PATCH 298/315] Force enable-first-step=false (#2419) --- .../study/parameters/adq-patch-params.cpp | 16 ++- .../study/parameters/adq-patch-params.h | 2 +- .../solver/optimisation/adequacy_patch.cpp | 133 ------------------ 3 files changed, 10 insertions(+), 141 deletions(-) diff --git a/src/libs/antares/study/parameters/adq-patch-params.cpp b/src/libs/antares/study/parameters/adq-patch-params.cpp index b6deae7352..00b0a6cf64 100644 --- a/src/libs/antares/study/parameters/adq-patch-params.cpp +++ b/src/libs/antares/study/parameters/adq-patch-params.cpp @@ -25,7 +25,15 @@ bool LocalMatching::updateFromKeyValue(const Yuni::String& key, const Yuni::Stri if (key == "set-to-null-ntc-between-physical-out-for-first-step") return value.to(setToZeroOutsideOutsideLinks); if (key == "enable-first-step") - return value.to(enabled); + { + if (value == "true") + { + logs.info() << "Property enable-first-step has been disabled, it is known to cause " + "errors and inconsistent results"; + } + return true; + } + return false; } @@ -143,12 +151,6 @@ void AdqPatchParams::addExcludedVariables(std::vector& out) const out.emplace_back("SPIL. ENRG. CSR"); out.emplace_back("DTG MRG CSR"); } - - // If the adequacy patch is enabled, but the LMR is disabled, the DENS variable shouldn't exist - if (enabled && !localMatching.enabled) - { - out.emplace_back("DENS"); - } } diff --git a/src/libs/antares/study/parameters/adq-patch-params.h b/src/libs/antares/study/parameters/adq-patch-params.h index e3c56115b2..44791d3c0f 100644 --- a/src/libs/antares/study/parameters/adq-patch-params.h +++ b/src/libs/antares/study/parameters/adq-patch-params.h @@ -59,7 +59,7 @@ enum class AdqPatchPTO struct LocalMatching { - bool enabled = true; + const bool enabled = false; //! Transmission capacities from physical areas outside adequacy patch (area type 1) to //! physical areas inside adequacy patch (area type 2). NTC is set to null (if true) //! only in the first step of adequacy patch local matching rule. diff --git a/src/tests/src/solver/optimisation/adequacy_patch.cpp b/src/tests/src/solver/optimisation/adequacy_patch.cpp index 57a8f4cea8..fd9e2f84e5 100644 --- a/src/tests/src/solver/optimisation/adequacy_patch.cpp +++ b/src/tests/src/solver/optimisation/adequacy_patch.cpp @@ -20,43 +20,6 @@ static double extremiteOrigine = 5; using namespace Antares::Data::AdequacyPatch; -// NOTE -// Xmax limits the flux origin -> extremity (direct) -// -Xmin limits the flux extremity -> origin (indirect) - -std::pair setNTCboundsForOneTimeStep(AdequacyPatchMode originType, - AdequacyPatchMode extremityType, - bool SetNTCOutsideToOutsideToZero, - bool SetNTCOutsideToInsideToZero) -{ - PROBLEME_HEBDO problem; - problem.adequacyPatchRuntimeData = std::make_shared(); - problem.adequacyPatchRuntimeData->originAreaMode.resize(1); - problem.adequacyPatchRuntimeData->extremityAreaMode.resize(1); - - problem.adequacyPatchRuntimeData->originAreaMode[0] = originType; - problem.adequacyPatchRuntimeData->extremityAreaMode[0] = extremityType; - problem.adequacyPatchRuntimeData->AdequacyFirstStep = true; - - AdqPatchParams adqPatchParams; - adqPatchParams.enabled = true; - adqPatchParams.localMatching.setToZeroOutsideOutsideLinks = SetNTCOutsideToOutsideToZero; - adqPatchParams.localMatching.setToZeroOutsideInsideLinks = SetNTCOutsideToInsideToZero; - - VALEURS_DE_NTC_ET_RESISTANCES ValeursDeNTC; - ValeursDeNTC.ValeurDeNTCOrigineVersExtremite.assign(1, 0.); - ValeursDeNTC.ValeurDeNTCExtremiteVersOrigine.assign(1, 0.); - ValeursDeNTC.ValeurDeNTCOrigineVersExtremite[0] = origineExtremite; - ValeursDeNTC.ValeurDeNTCExtremiteVersOrigine[0] = extremiteOrigine; - - double Xmin(0.); - double Xmax(0.); - - setNTCbounds(Xmax, Xmin, ValeursDeNTC, 0, &problem, adqPatchParams); - - return std::make_pair(Xmin, Xmax); -} - static const double flowArea0toArea1_positive = 10; static const double flowArea0toArea1_negative = -10; static const double flowArea2toArea0_positive = 30; @@ -120,107 +83,11 @@ AdqPatchParams createParams() AdqPatchParams p; p.enabled = true; p.curtailmentSharing.includeHurdleCost = true; - p.localMatching.enabled = true; p.curtailmentSharing.priceTakingOrder = AdqPatchPTO::isDens; return p; } -// Virtual -> Virtual (0 -> 0) -// No change in bounds is expected -BOOST_AUTO_TEST_CASE(setNTCboundsForOneTimeStep_virtual_virtual_no_change_expected) -{ - double Xmin, Xmax; - std::tie(Xmin, Xmax) = setNTCboundsForOneTimeStep( - virtualArea, virtualArea, true /*SetNTCOutsideToOutsideToZero*/, false); - BOOST_CHECK_EQUAL(Xmax, origineExtremite); - BOOST_CHECK_EQUAL(Xmin, -extremiteOrigine); -} - -// Virtual -> physical area inside adq-patch (0 -> 2) -// No change in bounds is expected -BOOST_AUTO_TEST_CASE(setNTCboundsForOneTimeStep_virtual_inside_no_change_expected) -{ - double Xmin, Xmax; - std::tie(Xmin, Xmax) = setNTCboundsForOneTimeStep( - virtualArea, physicalAreaInsideAdqPatch, true /*SetNTCOutsideToOutsideToZero*/, false); - BOOST_CHECK_EQUAL(Xmax, origineExtremite); - BOOST_CHECK_EQUAL(Xmin, -extremiteOrigine); -} - -// Virtual -> physical area outside adq-patch (0 -> 1) -// No change in bounds is expected -BOOST_AUTO_TEST_CASE(setNTCboundsForOneTimeStep_virtual_outside_no_change_expected) -{ - double Xmin, Xmax; - std::tie(Xmin, Xmax) = setNTCboundsForOneTimeStep( - virtualArea, physicalAreaOutsideAdqPatch, true /*SetNTCOutsideToOutsideToZero*/, false); - BOOST_CHECK_EQUAL(Xmax, origineExtremite); - BOOST_CHECK_EQUAL(Xmin, -extremiteOrigine); -} - -// physical area outside adq-patch -> physical area outside adq-patch (1 -> 1) -// NTC should be set to 0 in both directions -BOOST_AUTO_TEST_CASE(setNTCboundsForOneTimeStep_outside_outside_zero_expected_both_directions) -{ - double Xmin, Xmax; - std::tie(Xmin, Xmax) = setNTCboundsForOneTimeStep(physicalAreaOutsideAdqPatch, - physicalAreaOutsideAdqPatch, - true /*SetNTCOutsideToOutsideToZero*/, - false); - BOOST_CHECK_EQUAL(Xmax, 0); - BOOST_CHECK_EQUAL(Xmin, 0); -} - -// physical area outside adq-patch -> physical area outside adq-patch (1 -> 1) -// SetNTCOutsideToOutsideToZero = true -// NTC should be set to 0 in both directions -BOOST_AUTO_TEST_CASE(setNTCboundsForOneTimeStep_outside_outside_no_change_expected) -{ - double Xmin, Xmax; - std::tie(Xmin, Xmax) = setNTCboundsForOneTimeStep( - physicalAreaOutsideAdqPatch, physicalAreaOutsideAdqPatch, false, false); - - BOOST_CHECK_EQUAL(Xmax, origineExtremite); - BOOST_CHECK_EQUAL(Xmin, -extremiteOrigine); -} - -// physical area inside adq-patch -> physical area outside adq-patch (2 -> 1) -// NTC should be set to 0 in both directions -BOOST_AUTO_TEST_CASE(setNTCboundsForOneTimeStep_inside_outside_zero_expected_both_directions) -{ - double Xmin, Xmax; - std::tie(Xmin, Xmax) = setNTCboundsForOneTimeStep( - physicalAreaInsideAdqPatch, physicalAreaOutsideAdqPatch, false, false); - BOOST_CHECK_EQUAL(Xmax, 0); - BOOST_CHECK_EQUAL(Xmin, 0); -} - -// physical area outside adq-patch -> physical area inside adq-patch (1 -> 2) -// NTC should be set to 0 in both directions -BOOST_AUTO_TEST_CASE(setNTCboundsForOneTimeStep_outside_inside_zero_expected_both_directions) -{ - double Xmin, Xmax; - std::tie(Xmin, Xmax) = setNTCboundsForOneTimeStep(physicalAreaOutsideAdqPatch, - physicalAreaInsideAdqPatch, - false, - true /*SetNTCOutsideToInsideToZero*/); - BOOST_CHECK_EQUAL(Xmax, 0); - BOOST_CHECK_EQUAL(Xmin, 0); -} - -// physical area outside adq-patch -> physical area inside adq-patch (1 -> 2) -// NTC should be unchanged in direction origin->extremity (direct) -// NTC should be set to 0 in direction extremity->origin (indirect) -BOOST_AUTO_TEST_CASE(setNTCboundsForOneTimeStep_outside_inside_change_expected_one_direction) -{ - double Xmin, Xmax; - std::tie(Xmin, Xmax) = setNTCboundsForOneTimeStep( - physicalAreaOutsideAdqPatch, physicalAreaInsideAdqPatch, false, false); - BOOST_CHECK_EQUAL(Xmax, origineExtremite); - BOOST_CHECK_EQUAL(Xmin, 0); -} - // Area 0 is physical area inside adq-patch connected to two areas: // Area1 virtual-area, and Area2-virtual area // flow from Area0 -> Area1 is positive From 8dbf5c11e911adef6abd472a2c6c8b675a3bf8f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Omn=C3=A8s?= Date: Fri, 27 Sep 2024 13:20:36 +0200 Subject: [PATCH 299/315] Adequacy patch CSR - revamp output variables [ANT-1932] (#2421) Backport of #2306 --- .github/workflows/ubuntu.yml | 8 -- .github/workflows/windows-vcpkg.yml | 9 -- .../study/parameters/adq-patch-params.cpp | 2 +- .../study/parameters/adq-patch-params.h | 2 - src/solver/optimisation/CMakeLists.txt | 2 + .../adequacy_patch_csr/post_processing.cpp | 62 +++++++++++ .../adequacy_patch_csr/post_processing.h | 29 +++++ .../set_variable_boundaries.cpp | 3 +- .../optimisation/post_process_commands.cpp | 45 ++++---- .../simulation/sim_alloc_probleme_hebdo.cpp | 4 +- .../sim_structure_probleme_economique.h | 6 +- src/solver/variable/CMakeLists.txt | 3 +- src/solver/variable/economy/all.h | 36 +++---- ...dEnergyAfterCSR.h => unsupliedEnergyCsr.h} | 102 +++++++++--------- .../solver/optimisation/adequacy_patch.cpp | 74 +++++++++++++ 15 files changed, 262 insertions(+), 125 deletions(-) create mode 100644 src/solver/optimisation/adequacy_patch_csr/post_processing.cpp create mode 100644 src/solver/optimisation/adequacy_patch_csr/post_processing.h rename src/solver/variable/economy/{spilledEnergyAfterCSR.h => unsupliedEnergyCsr.h} (72%) diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml index 0321a79870..8b29e7cfb3 100644 --- a/.github/workflows/ubuntu.yml +++ b/.github/workflows/ubuntu.yml @@ -242,14 +242,6 @@ jobs: batch-name: valid-mps os: ${{ env.os }} - - name: Run tests for adequacy patch (CSR) - if: false - uses: ./.github/workflows/run-tests - with: - simtest-tag: ${{steps.simtest-version.outputs.prop}} - batch-name: adequacy-patch-CSR - os: ${{ env.os }} - - name: Run parallel tests if: ${{ env.RUN_EXTENDED_TESTS == 'true' }} uses: ./.github/workflows/run-tests diff --git a/.github/workflows/windows-vcpkg.yml b/.github/workflows/windows-vcpkg.yml index f66b2e1acf..14ec769c8e 100644 --- a/.github/workflows/windows-vcpkg.yml +++ b/.github/workflows/windows-vcpkg.yml @@ -195,15 +195,6 @@ jobs: name: MPS-diff path: ${{ github.workspace }}/src/tests/mps - - - name: Run tests for adequacy patch (CSR) - if: false - uses: ./.github/workflows/run-tests - with: - simtest-tag: ${{steps.simtest-version.outputs.prop}} - batch-name: adequacy-patch-CSR - os: ${{ env.test-platform }} - - name: Run tests about infinity on BCs RHS if: ${{ env.RUN_SIMPLE_TESTS == 'true' }} uses: ./.github/workflows/run-tests diff --git a/src/libs/antares/study/parameters/adq-patch-params.cpp b/src/libs/antares/study/parameters/adq-patch-params.cpp index 00b0a6cf64..eedef3aaef 100644 --- a/src/libs/antares/study/parameters/adq-patch-params.cpp +++ b/src/libs/antares/study/parameters/adq-patch-params.cpp @@ -148,7 +148,7 @@ void AdqPatchParams::addExcludedVariables(std::vector& out) const { out.emplace_back("DENS"); out.emplace_back("LMR VIOL."); - out.emplace_back("SPIL. ENRG. CSR"); + out.emplace_back("UNSP. ENRG CSR"); out.emplace_back("DTG MRG CSR"); } } diff --git a/src/libs/antares/study/parameters/adq-patch-params.h b/src/libs/antares/study/parameters/adq-patch-params.h index 44791d3c0f..47ec5599c2 100644 --- a/src/libs/antares/study/parameters/adq-patch-params.h +++ b/src/libs/antares/study/parameters/adq-patch-params.h @@ -92,8 +92,6 @@ class CurtailmentSharing //! Check CSR cost function prior & after CSR optimization bool checkCsrCostFunction; - bool recomputeDTGMRG = false; - bool updateFromKeyValue(const Yuni::String& key, const Yuni::String& value); void addProperties(IniFile::Section* section) const; diff --git a/src/solver/optimisation/CMakeLists.txt b/src/solver/optimisation/CMakeLists.txt index 4ca7205048..f552b874f2 100644 --- a/src/solver/optimisation/CMakeLists.txt +++ b/src/solver/optimisation/CMakeLists.txt @@ -50,6 +50,8 @@ set(RTESOLVER_OPT adequacy_patch_csr/hourly_csr_problem.h adequacy_patch_csr/adq_patch_post_process_list.h adequacy_patch_csr/adq_patch_post_process_list.cpp + adequacy_patch_csr/post_processing.cpp + adequacy_patch_csr/post_processing.h adequacy_patch_local_matching/adq_patch_local_matching.h adequacy_patch_local_matching/adq_patch_local_matching.cpp adequacy_patch_csr/adq_patch_curtailment_sharing.h diff --git a/src/solver/optimisation/adequacy_patch_csr/post_processing.cpp b/src/solver/optimisation/adequacy_patch_csr/post_processing.cpp new file mode 100644 index 0000000000..725ec9c364 --- /dev/null +++ b/src/solver/optimisation/adequacy_patch_csr/post_processing.cpp @@ -0,0 +1,62 @@ +/* +** Copyright 2007-2024, RTE (https://www.rte-france.com) +** See AUTHORS.txt +** SPDX-License-Identifier: MPL-2.0 +** This file is part of Antares-Simulator, +** Adequacy and Performance assessment for interconnected energy networks. +** +** Antares_Simulator is free software: you can redistribute it and/or modify +** it under the terms of the Mozilla Public Licence 2.0 as published by +** the Mozilla Foundation, either version 2 of the License, or +** (at your option) any later version. +** +** 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 +** Mozilla Public Licence 2.0 for more details. +** +** You should have received a copy of the Mozilla Public Licence 2.0 +** along with Antares_Simulator. If not, see . +*/ +#include "post_processing.h" + +#include + +namespace Antares::Data::AdequacyPatch +{ +double recomputeDTG_MRG(bool triggered, double dtgMrg, double ens) +{ + if (triggered) + { + return std::max(0.0, dtgMrg - ens); + } + else + { + return dtgMrg; + } +} + +double recomputeENS_MRG(bool triggered, double dtgMrg, double ens) +{ + if (triggered) + { + return std::max(0.0, ens - dtgMrg); + } + else + { + return ens; + } +} + +double recomputeMRGPrice(double ensCsr, double originalCost, double unsuppliedEnergyCost) +{ + if (ensCsr > 0.5) + { + return -unsuppliedEnergyCost; + } + else + { + return originalCost; + } +} +} // namespace Antares::Data::AdequacyPatch diff --git a/src/solver/optimisation/adequacy_patch_csr/post_processing.h b/src/solver/optimisation/adequacy_patch_csr/post_processing.h new file mode 100644 index 0000000000..3ae5ee2d91 --- /dev/null +++ b/src/solver/optimisation/adequacy_patch_csr/post_processing.h @@ -0,0 +1,29 @@ +/* +** Copyright 2007-2024, RTE (https://www.rte-france.com) +** See AUTHORS.txt +** SPDX-License-Identifier: MPL-2.0 +** This file is part of Antares-Simulator, +** Adequacy and Performance assessment for interconnected energy networks. +** +** Antares_Simulator is free software: you can redistribute it and/or modify +** it under the terms of the Mozilla Public Licence 2.0 as published by +** the Mozilla Foundation, either version 2 of the License, or +** (at your option) any later version. +** +** 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 +** Mozilla Public Licence 2.0 for more details. +** +** You should have received a copy of the Mozilla Public Licence 2.0 +** along with Antares_Simulator. If not, see . +*/ + +#pragma once + +namespace Antares::Data::AdequacyPatch +{ +double recomputeDTG_MRG(bool triggered, double dtgMrg, double ens); +double recomputeENS_MRG(bool triggered, double dtgMrg, double ens); +double recomputeMRGPrice(double ensCsr, double originalCost, double unsuppliedEnergyCost); +} // namespace Antares::Data::AdequacyPatch diff --git a/src/solver/optimisation/adequacy_patch_csr/set_variable_boundaries.cpp b/src/solver/optimisation/adequacy_patch_csr/set_variable_boundaries.cpp index 0bb5d91925..7cb72b7b0d 100644 --- a/src/solver/optimisation/adequacy_patch_csr/set_variable_boundaries.cpp +++ b/src/solver/optimisation/adequacy_patch_csr/set_variable_boundaries.cpp @@ -93,8 +93,7 @@ void HourlyCSRProblem::setBoundsOnSpilledEnergy() .ValeursHorairesDeDefaillanceNegative[triggeredHour]; double* AdresseDuResultat = &(problemeHebdo_->ResultatsHoraires[area] - .ValeursHorairesSpilledEnergyAfterCSR[triggeredHour]); - + .ValeursHorairesDeDefaillanceNegative[triggeredHour]); problemeAResoudre_.AdresseOuPlacerLaValeurDesVariablesOptimisees[var] = AdresseDuResultat; diff --git a/src/solver/optimisation/post_process_commands.cpp b/src/solver/optimisation/post_process_commands.cpp index f864cc1c89..31e70626d3 100644 --- a/src/solver/optimisation/post_process_commands.cpp +++ b/src/solver/optimisation/post_process_commands.cpp @@ -23,6 +23,7 @@ #include "../simulation/common-eco-adq.h" #include "../simulation/adequacy_patch_runtime_data.h" #include "adequacy_patch_local_matching/adequacy_patch_weekly_optimization.h" +#include "adequacy_patch_csr/post_processing.h" #include "adequacy_patch_csr/adq_patch_curtailment_sharing.h" namespace Antares::Solver::Simulation @@ -141,28 +142,23 @@ void DTGmarginForAdqPatchPostProcessCmd::execute(const optRuntimeData&) for (uint hour = 0; hour < nbHoursInWeek; hour++) { - // define access to the required variables + auto& hourlyResults = problemeHebdo_->ResultatsHoraires[Area]; const auto& scratchpad = area_list_[Area]->scratchpad[thread_number_]; - double dtgMrg = scratchpad.dispatchableGenerationMargin[hour]; + const double dtgMrg = scratchpad.dispatchableGenerationMargin[hour]; + const double ens = hourlyResults.ValeursHorairesDeDefaillancePositive[hour]; + const bool triggered = problemeHebdo_->adequacyPatchRuntimeData + ->wasCSRTriggeredAtAreaHour(Area, hour); + hourlyResults.ValeursHorairesDtgMrgCsr[hour] = recomputeDTG_MRG(triggered, dtgMrg, ens); + hourlyResults.ValeursHorairesDeDefaillancePositiveCSR[hour] = recomputeENS_MRG( + triggered, + dtgMrg, + ens); - auto& hourlyResults = problemeHebdo_->ResultatsHoraires[Area]; - double& dtgMrgCsr = hourlyResults.ValeursHorairesDtgMrgCsr[hour]; - double& ens = hourlyResults.ValeursHorairesDeDefaillancePositive[hour]; - double& mrgCost = hourlyResults.CoutsMarginauxHoraires[hour]; - // calculate DTG MRG CSR and adjust ENS if neccessary - if (problemeHebdo_->adequacyPatchRuntimeData->wasCSRTriggeredAtAreaHour(Area, hour)) - { - if (adqPatchParams_.curtailmentSharing.recomputeDTGMRG) - { - dtgMrgCsr = std::max(0.0, dtgMrg - ens); - ens = std::max(0.0, ens - dtgMrg); - } - // set MRG PRICE to value of unsupplied energy cost, if LOLD=1.0 (ENS>0.5) - if (ens > 0.5) - mrgCost = -area_list_[Area]->thermal.unsuppliedEnergyCost; - } - else - dtgMrgCsr = dtgMrg; + const double unsuppliedEnergyCost = area_list_[Area]->thermal.unsuppliedEnergyCost; + hourlyResults.CoutsMarginauxHoraires[hour] = recomputeMRGPrice( + hourlyResults.ValeursHorairesDtgMrgCsr[hour], + hourlyResults.CoutsMarginauxHoraires[hour], + unsuppliedEnergyCost); } } } @@ -256,13 +252,8 @@ double CurtailmentSharingPostProcessCmd::calculateDensNewAndTotalLmrViolation() const auto& scratchpad = area_list_[Area]->scratchpad[thread_number_]; double dtgMrg = scratchpad.dispatchableGenerationMargin[hour]; // write down densNew values for all the hours - problemeHebdo_->ResultatsHoraires[Area].ValeursHorairesDENS[hour] = std::max( - 0.0, - densNew); - // copy spilled Energy values into spilled Energy values after CSR - problemeHebdo_->ResultatsHoraires[Area].ValeursHorairesSpilledEnergyAfterCSR[hour] - = problemeHebdo_->ResultatsHoraires[Area] - .ValeursHorairesDeDefaillanceNegative[hour]; + problemeHebdo_->ResultatsHoraires[Area].ValeursHorairesDENS[hour] + = std::max(0.0, densNew); // check LMR violations totalLmrViolation += LmrViolationAreaHour( problemeHebdo_, diff --git a/src/solver/simulation/sim_alloc_probleme_hebdo.cpp b/src/solver/simulation/sim_alloc_probleme_hebdo.cpp index 80c5ad5edb..5ee3b74e92 100644 --- a/src/solver/simulation/sim_alloc_probleme_hebdo.cpp +++ b/src/solver/simulation/sim_alloc_probleme_hebdo.cpp @@ -415,12 +415,12 @@ void SIM_AllocateAreas(PROBLEME_HEBDO& problem, problem.ResultatsHoraires[k].ValeursHorairesDeDefaillancePositive .assign(NombreDePasDeTemps, 0.); + problem.ResultatsHoraires[k].ValeursHorairesDeDefaillancePositiveCSR + .assign(NombreDePasDeTemps, 0.); problem.ResultatsHoraires[k].ValeursHorairesDENS .assign(NombreDePasDeTemps, 0.); // adq patch problem.ResultatsHoraires[k].ValeursHorairesLmrViolations .assign(NombreDePasDeTemps, 0); // adq patch - problem.ResultatsHoraires[k].ValeursHorairesSpilledEnergyAfterCSR - .assign(NombreDePasDeTemps, 0.); // adq patch problem.ResultatsHoraires[k].ValeursHorairesDtgMrgCsr .assign(NombreDePasDeTemps, 0.); // adq patch problem.ResultatsHoraires[k].ValeursHorairesDeDefaillancePositiveUp diff --git a/src/solver/simulation/sim_structure_probleme_economique.h b/src/solver/simulation/sim_structure_probleme_economique.h index a357f4f34c..7feea19585 100644 --- a/src/solver/simulation/sim_structure_probleme_economique.h +++ b/src/solver/simulation/sim_structure_probleme_economique.h @@ -429,9 +429,9 @@ struct PRODUCTION_THERMIQUE_OPTIMALE struct RESULTATS_HORAIRES { std::vector ValeursHorairesDeDefaillancePositive; - std::vector ValeursHorairesDENS; // adq patch domestic unsupplied energy - std::vector ValeursHorairesLmrViolations; // adq patch lmr violations - std::vector ValeursHorairesSpilledEnergyAfterCSR; // adq patch spillage after CSR + std::vector ValeursHorairesDeDefaillancePositiveCSR; + std::vector ValeursHorairesDENS; // adq patch domestic unsupplied energy + std::vector ValeursHorairesLmrViolations; // adq patch lmr violations std::vector ValeursHorairesDtgMrgCsr; // adq patch DTG MRG after CSR std::vector ValeursHorairesDeDefaillancePositiveUp; std::vector ValeursHorairesDeDefaillancePositiveDown; diff --git a/src/solver/variable/CMakeLists.txt b/src/solver/variable/CMakeLists.txt index df21955781..fea122e23c 100644 --- a/src/solver/variable/CMakeLists.txt +++ b/src/solver/variable/CMakeLists.txt @@ -109,9 +109,9 @@ set(SRC_VARIABLE_ECONOMY economy/STStorageLevelsByCluster.h economy/STStorageCashFlowByCluster.h economy/unsupliedEnergy.h + economy/unsupliedEnergyCsr.h economy/domesticUnsuppliedEnergy.h economy/localMatchingRuleViolations.h - economy/spilledEnergyAfterCSR.h economy/dtgMarginAfterCsr.h economy/spilledEnergy.h economy/dispatchableGeneration.h @@ -128,6 +128,7 @@ set(SRC_VARIABLE_ECONOMY economy/avail-dispatchable-generation.h economy/dispatchable-generation-margin.h + # Links economy/links/flowLinear.h economy/links/flowLinearAbs.h diff --git a/src/solver/variable/economy/all.h b/src/solver/variable/economy/all.h index b961c8dbf7..3527fcec6d 100644 --- a/src/solver/variable/economy/all.h +++ b/src/solver/variable/economy/all.h @@ -63,7 +63,6 @@ #include "unsupliedEnergy.h" #include "domesticUnsuppliedEnergy.h" #include "localMatchingRuleViolations.h" -#include "spilledEnergyAfterCSR.h" #include "dtgMarginAfterCsr.h" #include "spilledEnergy.h" @@ -73,6 +72,7 @@ #include "avail-dispatchable-generation.h" #include "dispatchable-generation-margin.h" +#include "unsupliedEnergyCsr.h" // By thermal plant #include "productionByDispatchablePlant.h" @@ -161,22 +161,24 @@ typedef // Prices >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> VariablesPerArea; /*! @@ -240,8 +242,6 @@ typedef // Prices LMRViolations, Common::SpatialAggregate< SpilledEnergy, - Common::SpatialAggregate< - SpilledEnergyAfterCSR, // LOLD Common::SpatialAggregate< LOLD, @@ -271,7 +271,7 @@ typedef // Prices // - // refs: // #55 - >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> VariablesPerSetOfAreas; typedef BindingConstMarginCost< // Marginal cost for a binding constraint diff --git a/src/solver/variable/economy/spilledEnergyAfterCSR.h b/src/solver/variable/economy/unsupliedEnergyCsr.h similarity index 72% rename from src/solver/variable/economy/spilledEnergyAfterCSR.h rename to src/solver/variable/economy/unsupliedEnergyCsr.h index c36ae1aee5..979977d972 100644 --- a/src/solver/variable/economy/spilledEnergyAfterCSR.h +++ b/src/solver/variable/economy/unsupliedEnergyCsr.h @@ -1,53 +1,53 @@ /* -** Copyright 2007-2023 RTE -** Authors: Antares_Simulator Team -** -** This file is part of Antares_Simulator. +** Copyright 2007-2024, RTE (https://www.rte-france.com) +** See AUTHORS.txt +** SPDX-License-Identifier: MPL-2.0 +** This file is part of Antares-Simulator, +** Adequacy and Performance assessment for interconnected energy networks. ** ** 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 +** it under the terms of the Mozilla Public Licence 2.0 as published by +** the Mozilla Foundation, either version 2 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 . +** Mozilla Public Licence 2.0 for more details. ** -** SPDX-License-Identifier: licenceRef-GPL3_WITH_RTE-Exceptions +** You should have received a copy of the Mozilla Public Licence 2.0 +** along with Antares_Simulator. If not, see . */ -#ifndef __SOLVER_VARIABLE_ECONOMY_SpilledEnergyAfterCSR_H__ -#define __SOLVER_VARIABLE_ECONOMY_SpilledEnergyAfterCSR_H__ +#pragma once #include "../variable.h" -namespace Antares::Solver::Variable::Economy +namespace Antares +{ +namespace Solver +{ +namespace Variable { -struct VCardSpilledEnergyAfterCSR +namespace Economy +{ +struct VCardUnsupliedEnergyCSR { //! Caption static std::string Caption() { - return "SPIL. ENRG. CSR"; + return "UNSP. ENRG CSR"; } + //! Unit static std::string Unit() { return "MWh"; } + //! The short description of the variable static std::string Description() { - return "Spilled Energy After CSR Optimization (generation that cannot be satisfied) " - "after CSR optimization"; + return "Unsuplied Energy after CSR (demand that cannot be satisfied)"; } //! The expecte results @@ -59,8 +59,7 @@ struct VCardSpilledEnergyAfterCSR ResultsType; //! The VCard to look for for calculating spatial aggregates - typedef VCardSpilledEnergyAfterCSR VCardForSpatialAggregate; - + typedef VCardUnsupliedEnergyCSR VCardForSpatialAggregate; enum { //! Data Level @@ -82,9 +81,8 @@ struct VCardSpilledEnergyAfterCSR //! Intermediate values hasIntermediateValues = 1, //! Can this variable be non applicable (0 : no, 1 : yes) - isPossiblyNonApplicable = 0, + isPossiblyNonApplicable = 0 }; - typedef IntermediateValues IntermediateValuesBaseType; typedef IntermediateValues* IntermediateValuesType; @@ -92,21 +90,17 @@ struct VCardSpilledEnergyAfterCSR }; // class VCard -/*! -** \brief C02 Average value of the overrall SpilledEnergyAfterCSR emissions expected from all -** the thermal dispatchable clusters -*/ template -class SpilledEnergyAfterCSR - : public Variable::IVariable, NextT, VCardSpilledEnergyAfterCSR> +class UnsupliedEnergyCSR + : public Variable::IVariable, NextT, VCardUnsupliedEnergyCSR> { public: //! Type of the next static variable typedef NextT NextType; //! VCard - typedef VCardSpilledEnergyAfterCSR VCardType; + typedef VCardUnsupliedEnergyCSR VCardType; //! Ancestor - typedef Variable::IVariable, NextT, VCardType> AncestorType; + typedef Variable::IVariable, NextT, VCardType> AncestorType; //! List of expected results typedef typename VCardType::ResultsType ResultsType; @@ -124,15 +118,16 @@ class SpilledEnergyAfterCSR { enum { - count - = ((VCardType::categoryDataLevel & CDataLevel && VCardType::categoryFileLevel & CFile) - ? (NextType::template Statistics::count - + VCardType::columnCount * ResultsType::count) - : NextType::template Statistics::count), + count = ((VCardType::categoryDataLevel & CDataLevel + && VCardType::categoryFileLevel & CFile) + ? (NextType::template Statistics::count + + VCardType::columnCount * ResultsType::count) + : NextType::template Statistics::count), }; }; - ~SpilledEnergyAfterCSR() +public: + ~UnsupliedEnergyCSR() { delete[] pValuesForTheCurrentYear; } @@ -146,7 +141,9 @@ class SpilledEnergyAfterCSR pValuesForTheCurrentYear = new VCardType::IntermediateValuesBaseType[pNbYearsParallel]; for (unsigned int numSpace = 0; numSpace < pNbYearsParallel; numSpace++) + { pValuesForTheCurrentYear[numSpace].initializeFromStudy(study); + } // Next NextType::initializeFromStudy(study); @@ -173,7 +170,9 @@ class SpilledEnergyAfterCSR void simulationBegin() { for (unsigned int numSpace = 0; numSpace < pNbYearsParallel; numSpace++) + { pValuesForTheCurrentYear[numSpace].reset(); + } // Next NextType::simulationBegin(); } @@ -192,10 +191,10 @@ class SpilledEnergyAfterCSR NextType::yearBegin(year, numSpace); } - void yearEndBuild(State& state, unsigned int year) + void yearEndBuild(State& state, unsigned int year, unsigned int numSpace) { // Next variable - NextType::yearEndBuild(state, year); + NextType::yearEndBuild(state, year, numSpace); } void yearEnd(unsigned int year, unsigned int numSpace) @@ -229,10 +228,8 @@ class SpilledEnergyAfterCSR void hourForEachArea(State& state, unsigned int numSpace) { - // Total SpilledEnergyAfterCSR emissions pValuesForTheCurrentYear[numSpace][state.hourInTheYear] - = state.hourlyResults->ValeursHorairesSpilledEnergyAfterCSR[state.hourInTheWeek]; - + = state.hourlyResults->ValeursHorairesDeDefaillancePositiveCSR[state.hourInTheWeek]; // Next variable NextType::hourForEachArea(state, numSpace); } @@ -257,8 +254,8 @@ class SpilledEnergyAfterCSR // Write the data for the current year results.variableCaption = VCardType::Caption(); results.variableUnit = VCardType::Unit(); - pValuesForTheCurrentYear[numSpace].template buildAnnualSurveyReport( - results, fileLevel, precision); + pValuesForTheCurrentYear[numSpace] + .template buildAnnualSurveyReport(results, fileLevel, precision); } } @@ -267,8 +264,9 @@ class SpilledEnergyAfterCSR typename VCardType::IntermediateValuesType pValuesForTheCurrentYear; unsigned int pNbYearsParallel; -}; // class SpilledEnergyAfterCSR - -} // namespace Antares::Solver::Variable::Economy +}; // class UnsupliedEnergyCSR -#endif // __SOLVER_VARIABLE_ECONOMY_SpilledEnergyAfterCSR_H__ +} // namespace Economy +} // namespace Variable +} // namespace Solver +} // namespace Antares diff --git a/src/tests/src/solver/optimisation/adequacy_patch.cpp b/src/tests/src/solver/optimisation/adequacy_patch.cpp index fd9e2f84e5..a8055e8634 100644 --- a/src/tests/src/solver/optimisation/adequacy_patch.cpp +++ b/src/tests/src/solver/optimisation/adequacy_patch.cpp @@ -8,6 +8,7 @@ #include "adequacy_patch_local_matching/adq_patch_local_matching.h" #include "adequacy_patch_csr/adq_patch_curtailment_sharing.h" #include +#include "adequacy_patch_csr/post_processing.h" #include "antares/study/parameters/adq-patch-params.h" #include #include @@ -19,6 +20,7 @@ static double origineExtremite = -1; static double extremiteOrigine = 5; using namespace Antares::Data::AdequacyPatch; +namespace tt = boost::test_tools; static const double flowArea0toArea1_positive = 10; static const double flowArea0toArea1_negative = -10; @@ -370,3 +372,75 @@ BOOST_AUTO_TEST_CASE(check_adq_param_wrong_hurdle_cost) auto p = createParams(); BOOST_CHECK_THROW(p.checkAdqPatchIncludeHurdleCost(false), Error::IncompatibleHurdleCostCSR); } + +BOOST_AUTO_TEST_SUITE(adq_patch_post_processing) + +BOOST_AUTO_TEST_CASE(dtg_mrg_triggered_low_ens) +{ + const bool triggered = true; + const double dtgMrg = 32.; + const double ens = 21.; + + BOOST_TEST(recomputeDTG_MRG(triggered, dtgMrg, ens) == 11., tt::tolerance(1.e-6)); + + BOOST_TEST(recomputeDTG_MRG(triggered, dtgMrg, ens) + recomputeENS_MRG(triggered, dtgMrg, ens) + == std::abs(dtgMrg - ens), + tt::tolerance(1.e-6)); +} + +BOOST_AUTO_TEST_CASE(dtg_mrg_triggered_high_ens) +{ + const bool triggered = true; + const double dtgMrg = 32.; + const double ens = 42.; + + BOOST_TEST(recomputeDTG_MRG(triggered, dtgMrg, ens) == 0., tt::tolerance(1.e-6)); + + BOOST_TEST(recomputeDTG_MRG(triggered, dtgMrg, ens) + recomputeENS_MRG(triggered, dtgMrg, ens) + == std::abs(dtgMrg - ens), + tt::tolerance(1.e-6)); +} + +BOOST_AUTO_TEST_CASE(dtg_mrg_not_triggered_low_ens) +{ + const bool triggered = false; + const double dtgMrg = 32.; + const double ens = 21.; + + BOOST_TEST(recomputeDTG_MRG(triggered, dtgMrg, ens) == dtgMrg, tt::tolerance(1.e-6)); + BOOST_TEST(recomputeDTG_MRG(triggered, dtgMrg, ens) + recomputeENS_MRG(triggered, dtgMrg, ens) + == dtgMrg + ens, + tt::tolerance(1.e-6)); +} + +BOOST_AUTO_TEST_CASE(dtg_mrg_not_triggered_high_ens) +{ + const bool triggered = false; + const double dtgMrg = 32.; + const double ens = 42.; + + BOOST_TEST(recomputeDTG_MRG(triggered, dtgMrg, ens) == dtgMrg, tt::tolerance(1.e-6)); + BOOST_TEST(recomputeDTG_MRG(triggered, dtgMrg, ens) + recomputeENS_MRG(triggered, dtgMrg, ens) + == dtgMrg + ens, + tt::tolerance(1.e-6)); +} + +BOOST_AUTO_TEST_CASE(mrgprice_high_enscsr) +{ + const double ensCsr = 21.; + const double originalCost = 3.; + const double unsuppliedEnergyCost = 1000.; + BOOST_TEST(recomputeMRGPrice(ensCsr, originalCost, unsuppliedEnergyCost) + == -unsuppliedEnergyCost, + tt::tolerance(1.e-6)); +} + +BOOST_AUTO_TEST_CASE(mrgprice_low_enscsr) +{ + const double ensCsr = 0.; + const double originalCost = 3.; + const double unsuppliedEnergyCost = 1000.; + BOOST_TEST(recomputeMRGPrice(ensCsr, originalCost, unsuppliedEnergyCost) == originalCost, + tt::tolerance(1.e-6)); +} +BOOST_AUTO_TEST_SUITE_END() From 3ebda61a42ab4a33f6a18d6de940c10b006d89fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Omn=C3=A8s?= Date: Fri, 27 Sep 2024 15:02:04 +0200 Subject: [PATCH 300/315] Release 8.8.10 (#2436) --- docs/CHANGELOG.md | 10 ++++++++++ src/CMakeLists.txt | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index efb9c82a67..e4bfbe02e7 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -1,6 +1,16 @@ Antares Changelog ================= +8.8.10 (09/2024) +-------------------- +## Bugfix (adequacy patch) +* Force enable-first-step=false [ANT-2218] (#2419) +* Adequacy patch CSR - revamp output variables [ANT-1932] (#2421) +* Place CSR after hydro remix [ANT-2070] (#2407) + +## Bugfix (other) +* Use OR-Tools v9.11-rte1.1 [ANT-2069] (#2418) + 8.8.9 (09/2024) -------------------- * Revert "Fix bug hydro heuristic with mingen (ANT-1825) (#2258)" diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 67ff5781cf..47617b923c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.14) # FetchContent_MakeAvailable # Version set(ANTARES_VERSION_HI 8) set(ANTARES_VERSION_LO 8) -set(ANTARES_VERSION_REVISION 9) +set(ANTARES_VERSION_REVISION 10) # Beta release set(ANTARES_BETA 0) From 91678db8fb8af588e550e93a45942deb18ec0086 Mon Sep 17 00:00:00 2001 From: Vincent Payet Date: Fri, 27 Sep 2024 17:50:08 +0200 Subject: [PATCH 301/315] use devtoolset 11 for centos --- .github/workflows/centos7.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/centos7.yml b/.github/workflows/centos7.yml index 22e9bb0c74..e2e360db49 100644 --- a/.github/workflows/centos7.yml +++ b/.github/workflows/centos7.yml @@ -43,7 +43,7 @@ jobs: - name: Install gcc 10 run: | yum install -y centos-release-scl - yum install -y devtoolset-10-gcc* + yum install -y devtoolset-11-gcc* - uses: ./.github/workflows/install-cmake-328 @@ -80,7 +80,7 @@ jobs: - name: Configure run: | - source /opt/rh/devtoolset-10/enable + source /opt/rh/devtoolset-11/enable cmake -B _build -S src \ -DCMAKE_C_COMPILER_LAUNCHER=ccache \ -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \ @@ -94,7 +94,7 @@ jobs: - name: Build run: | - source /opt/rh/devtoolset-10/enable + source /opt/rh/devtoolset-11/enable source /opt/rh/rh-git227/enable cmake --build _build --config Release -j$(nproc) ccache -s From 59c94532ee75e1748fbb69bae587d5d53d48c8b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Omn=C3=A8s?= Date: Sun, 29 Sep 2024 09:29:47 +0200 Subject: [PATCH 302/315] Use devtoolset-11 CentOS7 (#2442) --- .github/workflows/centos7.yml | 2 +- .github/workflows/install-cmake-328/action.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/centos7.yml b/.github/workflows/centos7.yml index e2e360db49..268f88a70d 100644 --- a/.github/workflows/centos7.yml +++ b/.github/workflows/centos7.yml @@ -40,7 +40,7 @@ jobs: run: | git clone $GITHUB_SERVER_URL/$GITHUB_REPOSITORY.git -b ${{ env.REF }} . - - name: Install gcc 10 + - name: Install gcc 11 run: | yum install -y centos-release-scl yum install -y devtoolset-11-gcc* diff --git a/.github/workflows/install-cmake-328/action.yml b/.github/workflows/install-cmake-328/action.yml index a6f111746c..9c2beb7876 100644 --- a/.github/workflows/install-cmake-328/action.yml +++ b/.github/workflows/install-cmake-328/action.yml @@ -7,7 +7,7 @@ runs: - name: Build cmake shell: bash run: | - source /opt/rh/devtoolset-10/enable + source /opt/rh/devtoolset-11/enable yum -y install openssl-devel wget https://github.com/Kitware/CMake/releases/download/v3.28.2/cmake-3.28.2.tar.gz tar -xvf cmake-3.28.2.tar.gz From a50603794322242516e61874ce09cf3c2e78b979 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Fri, 4 Oct 2024 12:40:11 +0200 Subject: [PATCH 303/315] remove "Aux" from folder and file names --- src/solver/simulation/solver.hxx | 2 +- src/solver/ts-generator/CMakeLists.txt | 12 ++++++------ .../main/OptimizedGenerator.h | 4 ++-- .../AuxFreeFun.cpp => support/SupportFunctions.cpp} | 4 ++-- .../AuxFreeFun.h => support/SupportFunctions.h} | 2 +- .../SupportStructures.cpp} | 2 +- .../SupportStructures.h} | 0 .../{auxillary => support}/pre-scenario-builder.cpp | 0 .../{auxillary => support}/pre-scenario-builder.h | 0 9 files changed, 13 insertions(+), 13 deletions(-) rename src/solver/ts-generator/optimized-thermal-generator/{auxillary/AuxFreeFun.cpp => support/SupportFunctions.cpp} (98%) rename src/solver/ts-generator/optimized-thermal-generator/{auxillary/AuxFreeFun.h => support/SupportFunctions.h} (98%) rename src/solver/ts-generator/optimized-thermal-generator/{auxillary/AuxillaryStructures.cpp => support/SupportStructures.cpp} (97%) rename src/solver/ts-generator/optimized-thermal-generator/{auxillary/AuxillaryStructures.h => support/SupportStructures.h} (100%) rename src/solver/ts-generator/optimized-thermal-generator/{auxillary => support}/pre-scenario-builder.cpp (100%) rename src/solver/ts-generator/optimized-thermal-generator/{auxillary => support}/pre-scenario-builder.h (100%) diff --git a/src/solver/simulation/solver.hxx b/src/solver/simulation/solver.hxx index 06f906ed4f..42875f216e 100644 --- a/src/solver/simulation/solver.hxx +++ b/src/solver/simulation/solver.hxx @@ -40,7 +40,7 @@ #include "../ts-generator/generator.h" #include "opt_time_writer.h" #include "../hydro/management.h" // Added for use of randomReservoirLevel(...) -#include "../ts-generator/optimized-thermal-generator/auxillary/pre-scenario-builder.h" +#include "../ts-generator/optimized-thermal-generator/support/pre-scenario-builder.h" #include #include diff --git a/src/solver/ts-generator/CMakeLists.txt b/src/solver/ts-generator/CMakeLists.txt index 84a7e58249..02220be4af 100644 --- a/src/solver/ts-generator/CMakeLists.txt +++ b/src/solver/ts-generator/CMakeLists.txt @@ -13,12 +13,12 @@ source_group("ts-generator\\Randomized-thermal-generator" FILES ${SRC_RANDOMIZED # Optimized-thermal-ts-generator # set(SRC_OPTIMIZEDGENERATORS - optimized-thermal-generator/auxillary/AuxillaryStructures.h - optimized-thermal-generator/auxillary/AuxillaryStructures.cpp - optimized-thermal-generator/auxillary/AuxFreeFun.h - optimized-thermal-generator/auxillary/AuxFreeFun.cpp - optimized-thermal-generator/auxillary/pre-scenario-builder.h - optimized-thermal-generator/auxillary/pre-scenario-builder.cpp + optimized-thermal-generator/support/SupportStructures.h + optimized-thermal-generator/support/SupportStructures.cpp + optimized-thermal-generator/support/SupportFunctions.h + optimized-thermal-generator/support/SupportFunctions.cpp + optimized-thermal-generator/support/pre-scenario-builder.h + optimized-thermal-generator/support/pre-scenario-builder.cpp optimized-thermal-generator/main/OptimizedGenerator.h optimized-thermal-generator/main/OptimizedGenerator.cpp optimized-thermal-generator/parameters/OptimizationParameters.h diff --git a/src/solver/ts-generator/optimized-thermal-generator/main/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/main/OptimizedGenerator.h index e5ec2e9c5c..74c913e8b3 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/main/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/main/OptimizedGenerator.h @@ -7,8 +7,8 @@ #include "ortools/linear_solver/linear_solver.h" #include "../../randomized-thermal-generator/RandomizedGenerator.h" #include "../../../../libs/antares/study/maintenance_planning/MaintenanceGroup.h" -#include "../auxillary/AuxillaryStructures.h" -#include "../auxillary/AuxFreeFun.h" +#include "../support/SupportStructures.h" +#include "../support/SupportFunctions.h" #include "../parameters/OptimizationParameters.h" #include diff --git a/src/solver/ts-generator/optimized-thermal-generator/auxillary/AuxFreeFun.cpp b/src/solver/ts-generator/optimized-thermal-generator/support/SupportFunctions.cpp similarity index 98% rename from src/solver/ts-generator/optimized-thermal-generator/auxillary/AuxFreeFun.cpp rename to src/solver/ts-generator/optimized-thermal-generator/support/SupportFunctions.cpp index afe5c1237c..9b2ce80882 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/auxillary/AuxFreeFun.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/support/SupportFunctions.cpp @@ -5,7 +5,7 @@ #include #include #include "../main/OptimizedGenerator.h" -#include "../auxillary/AuxFreeFun.h" +#include "../support/SupportFunctions.h" namespace Antares::Solver::TSGenerator { @@ -79,7 +79,7 @@ std::array calculateAverageRenewableTs( } } -// auxillary functions - for parameter calculations +// support functions - for parameter calculations std::array calculateDailySums( const std::array& hourlyValues) { diff --git a/src/solver/ts-generator/optimized-thermal-generator/auxillary/AuxFreeFun.h b/src/solver/ts-generator/optimized-thermal-generator/support/SupportFunctions.h similarity index 98% rename from src/solver/ts-generator/optimized-thermal-generator/auxillary/AuxFreeFun.h rename to src/solver/ts-generator/optimized-thermal-generator/support/SupportFunctions.h index 492d0236d0..1fb5554937 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/auxillary/AuxFreeFun.h +++ b/src/solver/ts-generator/optimized-thermal-generator/support/SupportFunctions.h @@ -9,7 +9,7 @@ namespace Antares::Solver::TSGenerator { -// auxillary functions +// support functions std::array calculateDailySums( const std::array& hourlyValues); std::array calculateAverageTs(const Matrix& tsValue, diff --git a/src/solver/ts-generator/optimized-thermal-generator/auxillary/AuxillaryStructures.cpp b/src/solver/ts-generator/optimized-thermal-generator/support/SupportStructures.cpp similarity index 97% rename from src/solver/ts-generator/optimized-thermal-generator/auxillary/AuxillaryStructures.cpp rename to src/solver/ts-generator/optimized-thermal-generator/support/SupportStructures.cpp index 22496a2130..ede3325fe4 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/auxillary/AuxillaryStructures.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/support/SupportStructures.cpp @@ -2,7 +2,7 @@ // Created by milos on 14/11/23. // -#include "AuxillaryStructures.h" +#include "SupportStructures.h" namespace Antares::Solver::TSGenerator { diff --git a/src/solver/ts-generator/optimized-thermal-generator/auxillary/AuxillaryStructures.h b/src/solver/ts-generator/optimized-thermal-generator/support/SupportStructures.h similarity index 100% rename from src/solver/ts-generator/optimized-thermal-generator/auxillary/AuxillaryStructures.h rename to src/solver/ts-generator/optimized-thermal-generator/support/SupportStructures.h diff --git a/src/solver/ts-generator/optimized-thermal-generator/auxillary/pre-scenario-builder.cpp b/src/solver/ts-generator/optimized-thermal-generator/support/pre-scenario-builder.cpp similarity index 100% rename from src/solver/ts-generator/optimized-thermal-generator/auxillary/pre-scenario-builder.cpp rename to src/solver/ts-generator/optimized-thermal-generator/support/pre-scenario-builder.cpp diff --git a/src/solver/ts-generator/optimized-thermal-generator/auxillary/pre-scenario-builder.h b/src/solver/ts-generator/optimized-thermal-generator/support/pre-scenario-builder.h similarity index 100% rename from src/solver/ts-generator/optimized-thermal-generator/auxillary/pre-scenario-builder.h rename to src/solver/ts-generator/optimized-thermal-generator/support/pre-scenario-builder.h From 41678569cdae314d3704e2a76940d1f7bc8bfa89 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Fri, 4 Oct 2024 14:45:35 +0200 Subject: [PATCH 304/315] try fix-17 --- .github/workflows/windows-vcpkg.yml | 40 ++++++++++------------------- 1 file changed, 13 insertions(+), 27 deletions(-) diff --git a/.github/workflows/windows-vcpkg.yml b/.github/workflows/windows-vcpkg.yml index 22fd808a1f..4d871e34b9 100644 --- a/.github/workflows/windows-vcpkg.yml +++ b/.github/workflows/windows-vcpkg.yml @@ -59,34 +59,20 @@ jobs: with: key: windows - - name : Init VCPKG submodule - run: | - git submodule update --init vcpkg - - # Restore both vcpkg and its artifacts from the GitHub cache service. - - name: Restore vcpkg and its artifacts. - uses: actions/cache@v3 + - name: Install VCPKG + shell: bash + run: | + git submodule update --init vcpkg && ./vcpkg/bootstrap-vcpkg.bat -disableMetrics + + - name: Restore vcpkg binary dir from cache + id: cache-vcpkg-binary + uses: actions/cache/restore@v4 with: - # The first path is the location of vcpkg (it contains the vcpkg executable and data files). - # The other paths starting with '!' are exclusions: they contain termporary files generated during the build of the installed packages. - path: | - ${{ env.VCPKG_ROOT }} - !${{ env.VCPKG_ROOT }}/buildtrees - !${{ env.VCPKG_ROOT }}/packages - !${{ env.VCPKG_ROOT }}/downloads - # The key is composed in a way that it gets properly invalidated: this must happen whenever vcpkg's Git commit id changes, or the list of packages changes. In this case a cache miss must happen and a new entry with a new key with be pushed to GitHub the cache service. - # The key includes: hash of the vcpkg.json file, the hash of the vcpkg Git commit id, and the used vcpkg's triplet. The vcpkg's commit id would suffice, but computing an hash out it does not harm. - # Note: given a key, the cache content is immutable. If a cache entry has been created improperly, in order the recreate the right content the key must be changed as well, and it must be brand new (i.e. not existing already). - key: | - ${{ hashFiles( 'vcpkg_manifest/vcpkg.json' ) }}-${{ hashFiles( '.git/modules/vcpkg/HEAD' )}}-${{ matrix.triplet }} - - - name : Install deps with VCPKG - run: | - cd vcpkg - ./bootstrap-vcpkg.sh - vcpkg install ${{matrix.vcpkgPackages}} --triplet ${{matrix.triplet}} - rm -rf buildtrees packages downloads - shell: bash + path: ${{ github.workspace }}/vcpkg_cache + key: vcpkg-cache-windows-${{ hashFiles('src/vcpkg.json', '.git/modules/vcpkg/HEAD') }} + # Allows to restore a cache when deps have only partially changed (like adding a dependency) + restore-keys: vcpkg-cache-windows- + - name: Read antares-deps version id: antares-deps-version From 200e38bfa8e0030ad99cb745f8e10c885a6d7352 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Fri, 4 Oct 2024 14:47:03 +0200 Subject: [PATCH 305/315] try fix-18 --- .github/workflows/windows-vcpkg.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/windows-vcpkg.yml b/.github/workflows/windows-vcpkg.yml index 4d871e34b9..a67831d9a3 100644 --- a/.github/workflows/windows-vcpkg.yml +++ b/.github/workflows/windows-vcpkg.yml @@ -60,9 +60,9 @@ jobs: key: windows - name: Install VCPKG - shell: bash - run: | - git submodule update --init vcpkg && ./vcpkg/bootstrap-vcpkg.bat -disableMetrics + shell: bash + run: | + git submodule update --init vcpkg && ./vcpkg/bootstrap-vcpkg.bat -disableMetrics - name: Restore vcpkg binary dir from cache id: cache-vcpkg-binary From c0687326218f8d8292450819390dbb5a095de3c3 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Fri, 4 Oct 2024 15:01:41 +0200 Subject: [PATCH 306/315] try fix-19 --- .github/workflows/windows-vcpkg.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/windows-vcpkg.yml b/.github/workflows/windows-vcpkg.yml index a67831d9a3..f0e7d8af98 100644 --- a/.github/workflows/windows-vcpkg.yml +++ b/.github/workflows/windows-vcpkg.yml @@ -59,10 +59,12 @@ jobs: with: key: windows - - name: Install VCPKG + - name: Install VCPKG and Dependencies shell: bash run: | - git submodule update --init vcpkg && ./vcpkg/bootstrap-vcpkg.bat -disableMetrics + git submodule update --init vcpkg + ./vcpkg/bootstrap-vcpkg.bat -disableMetrics + ./vcpkg/vcpkg install boost --triplet x64-windows - name: Restore vcpkg binary dir from cache id: cache-vcpkg-binary From 2a42a1002112e794c2d131dcea9656b64869cad4 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Mon, 7 Oct 2024 19:05:39 +0200 Subject: [PATCH 307/315] fix wrong merge with 8.8.x --- .github/workflows/windows-vcpkg.yml | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/.github/workflows/windows-vcpkg.yml b/.github/workflows/windows-vcpkg.yml index 81d793a1af..14ec769c8e 100644 --- a/.github/workflows/windows-vcpkg.yml +++ b/.github/workflows/windows-vcpkg.yml @@ -106,20 +106,6 @@ jobs: vcpkg install ${{env.vcpkgPackages}} --triplet ${{env.triplet}} rm -rf buildtrees packages downloads shell: bash - run: | - git submodule update --init vcpkg - ./vcpkg/bootstrap-vcpkg.bat -disableMetrics - ./vcpkg/vcpkg install boost --triplet x64-windows - - - name: Restore vcpkg binary dir from cache - id: cache-vcpkg-binary - uses: actions/cache/restore@v4 - with: - path: ${{ github.workspace }}/vcpkg_cache - key: vcpkg-cache-windows-${{ hashFiles('src/vcpkg.json', '.git/modules/vcpkg/HEAD') }} - # Allows to restore a cache when deps have only partially changed (like adding a dependency) - restore-keys: vcpkg-cache-windows- - - name: Read antares-deps version id: antares-deps-version From 8c3fe998fd1b54c0f3e05971e5663b423c777e8b Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Mon, 7 Oct 2024 19:05:55 +0200 Subject: [PATCH 308/315] fix bad merge - cluster_list --- src/libs/antares/study/parts/thermal/cluster_list.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/antares/study/parts/thermal/cluster_list.cpp b/src/libs/antares/study/parts/thermal/cluster_list.cpp index ecda83f172..fd1c882836 100644 --- a/src/libs/antares/study/parts/thermal/cluster_list.cpp +++ b/src/libs/antares/study/parts/thermal/cluster_list.cpp @@ -509,7 +509,7 @@ bool ThermalClusterList::generateRandomDaysSinceLastMaintenance(Study& study) bool ret = true; MersenneTwister random[seedMax]; - for (auto& [name, c] : cluster) + for (auto& c : clusters) { assert(c->parentArea and "cluster: invalid parent area"); From ef485f3f5142c1ee804286ed1cceae68d285891d Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Mon, 7 Oct 2024 19:36:05 +0200 Subject: [PATCH 309/315] fix merge --- .../optimized-thermal-generator/support/SupportFunctions.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/support/SupportFunctions.cpp b/src/solver/ts-generator/optimized-thermal-generator/support/SupportFunctions.cpp index 9b2ce80882..c8a71191db 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/support/SupportFunctions.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/support/SupportFunctions.cpp @@ -44,7 +44,7 @@ std::array calculateAverageRenewableTsAggregated(const D std::array calculateAverageRenewableTsClusters(const Data::Area& area) { std::array averageTsRenewable = {}; - for (const auto& entryCluster : area.renewable.clusters) + for (const auto& entryCluster : area.renewable.list) { auto& cluster = *entryCluster; // this is not even necessary - because area.renewable.clusters returns list of only From 6c71954ac4adb2be6a85b9ef9203e1a3ef3ff494 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Mon, 7 Oct 2024 21:36:15 +0200 Subject: [PATCH 310/315] fix local fail --- .../optimized-thermal-generator/support/SupportStructures.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/support/SupportStructures.h b/src/solver/ts-generator/optimized-thermal-generator/support/SupportStructures.h index 599180d7b7..a310f10172 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/support/SupportStructures.h +++ b/src/solver/ts-generator/optimized-thermal-generator/support/SupportStructures.h @@ -5,7 +5,7 @@ #pragma once #include "ortools/linear_solver/linear_solver.h" -#include "../../../src/libs/antares/study/area/area.h" +#include "../../../libs/antares/study/area/area.h" using namespace operations_research; From 732699382e8508540270a78e1719bc3748b2e374 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Mon, 7 Oct 2024 22:14:17 +0200 Subject: [PATCH 311/315] fix issues with Namespaces --- .../main/OptimizedGenerator.cpp | 4 ++-- .../optimized-thermal-generator/main/OptimizedGenerator.h | 6 +++--- .../optimization/CreateVariables.cpp | 4 ++-- .../optimization/PrintProblemVarRes.cpp | 4 ++-- .../optimization/ResetProblem.cpp | 4 ++-- .../optimization/SetProblemConstraints.cpp | 4 ++-- .../optimization/SetProblemCost.cpp | 4 ++-- .../optimization/SetVariableBounds.cpp | 4 ++-- .../optimization/SolveProbem.cpp | 4 ++-- .../parameters/CalculateParameters.cpp | 4 ++-- .../parameters/CalculateParametersPerCluster.cpp | 4 ++-- .../optimized-thermal-generator/parameters/Getters.cpp | 4 ++-- .../parameters/OptimizationParameters.h | 6 +++--- .../postoptimization/PostScenarioOptimization.cpp | 4 ++-- .../postoptimization/PostTimeStepOptimization.cpp | 4 ++-- .../postoptimization/WriteResults.cpp | 4 ++-- .../support/SupportFunctions.cpp | 4 ++-- .../support/SupportFunctions.h | 4 ++-- .../support/SupportStructures.cpp | 4 ++-- .../support/SupportStructures.h | 4 ++-- .../randomized-thermal-generator/RandomizedGenerator.h | 8 ++++---- src/solver/ts-generator/thermal.cpp | 4 ++-- 22 files changed, 48 insertions(+), 48 deletions(-) diff --git a/src/solver/ts-generator/optimized-thermal-generator/main/OptimizedGenerator.cpp b/src/solver/ts-generator/optimized-thermal-generator/main/OptimizedGenerator.cpp index c2177c9b26..16f8d5afcb 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/main/OptimizedGenerator.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/main/OptimizedGenerator.cpp @@ -7,7 +7,7 @@ #include #include -namespace Antares::Solver::TSGenerator +namespace Antares::TSGenerator { // optimization problem - methods void OptimizedThermalGenerator::GenerateOptimizedThermalTimeSeries() @@ -69,4 +69,4 @@ void OptimizedThermalGenerator::allocateWhereToWriteTs() return; } -} // namespace Antares::Solver::TSGenerator +} // namespace Antares::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/main/OptimizedGenerator.h b/src/solver/ts-generator/optimized-thermal-generator/main/OptimizedGenerator.h index 74c913e8b3..ab99820b73 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/main/OptimizedGenerator.h +++ b/src/solver/ts-generator/optimized-thermal-generator/main/OptimizedGenerator.h @@ -18,7 +18,7 @@ static const double solverDelta = 10e-4; using namespace operations_research; -namespace Antares::Solver::TSGenerator +namespace Antares::TSGenerator { class OptimizedThermalGenerator : public GeneratorTempData @@ -141,7 +141,7 @@ class OptimizedThermalGenerator : public GeneratorTempData uint year, bool globalThermalTSgeneration, Solver::Progression::Task& progr, - IResultWriter& writer) : + Solver::IResultWriter& writer) : GeneratorTempData(study, progr, writer), maintenanceGroup_(maintenanceGroup), progression_(progr), @@ -177,4 +177,4 @@ class OptimizedThermalGenerator : public GeneratorTempData void GenerateOptimizedThermalTimeSeries(); }; -} // namespace Antares::Solver::TSGenerator \ No newline at end of file +} // namespace Antares::TSGenerator \ No newline at end of file diff --git a/src/solver/ts-generator/optimized-thermal-generator/optimization/CreateVariables.cpp b/src/solver/ts-generator/optimized-thermal-generator/optimization/CreateVariables.cpp index 5fb78051de..3b603bf67f 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/optimization/CreateVariables.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/optimization/CreateVariables.cpp @@ -4,7 +4,7 @@ #include "../main/OptimizedGenerator.h" -namespace Antares::Solver::TSGenerator +namespace Antares::TSGenerator { void OptimizedThermalGenerator::buildProblemVariables(const OptProblemSettings& optSett) { @@ -153,4 +153,4 @@ void OptimizedThermalGenerator::buildEndVariables(const OptProblemSettings& optS return; } -} // namespace Antares::Solver::TSGenerator +} // namespace Antares::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/optimization/PrintProblemVarRes.cpp b/src/solver/ts-generator/optimized-thermal-generator/optimization/PrintProblemVarRes.cpp index 3306fcd039..a99cb4b32b 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/optimization/PrintProblemVarRes.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/optimization/PrintProblemVarRes.cpp @@ -10,7 +10,7 @@ #include "../main/OptimizedGenerator.h" -namespace Antares::Solver::TSGenerator +namespace Antares::TSGenerator { void OptimizationParameters::printProblemVarAndResults(OptProblemSettings& optSett, MPSolver& solver) { @@ -212,4 +212,4 @@ void printColumnToFile(const std::vector>& data, const std::strin } } -} // namespace Antares::Solver::TSGenerator \ No newline at end of file +} // namespace Antares::TSGenerator \ No newline at end of file diff --git a/src/solver/ts-generator/optimized-thermal-generator/optimization/ResetProblem.cpp b/src/solver/ts-generator/optimized-thermal-generator/optimization/ResetProblem.cpp index e58f1b298b..6880ee114a 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/optimization/ResetProblem.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/optimization/ResetProblem.cpp @@ -4,7 +4,7 @@ #include "../main/OptimizedGenerator.h" -namespace Antares::Solver::TSGenerator +namespace Antares::TSGenerator { void OptimizedThermalGenerator::resetProblem() { @@ -16,4 +16,4 @@ void OptimizedThermalGenerator::resetProblem() return; } -} // namespace Antares::Solver::TSGenerator +} // namespace Antares::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/optimization/SetProblemConstraints.cpp b/src/solver/ts-generator/optimized-thermal-generator/optimization/SetProblemConstraints.cpp index f7dd49b83d..148cdeb0e1 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/optimization/SetProblemConstraints.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/optimization/SetProblemConstraints.cpp @@ -4,7 +4,7 @@ #include "../main/OptimizedGenerator.h" -namespace Antares::Solver::TSGenerator +namespace Antares::TSGenerator { void OptimizedThermalGenerator::buildProblemConstraints(const OptProblemSettings& optSett) { @@ -245,4 +245,4 @@ void OptimizedThermalGenerator::insertEndSum(MPConstraint* ct, } } -} // namespace Antares::Solver::TSGenerator +} // namespace Antares::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/optimization/SetProblemCost.cpp b/src/solver/ts-generator/optimized-thermal-generator/optimization/SetProblemCost.cpp index d42cda55e2..c97a75a8e8 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/optimization/SetProblemCost.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/optimization/SetProblemCost.cpp @@ -4,7 +4,7 @@ #include "../main/OptimizedGenerator.h" -namespace Antares::Solver::TSGenerator +namespace Antares::TSGenerator { // create OBJECTIVE FUNCTION - sum through [t] and sum through [u] // sum[days]{ EnsCost*Ens[day] + SpillCost[day] + sum[units][ avgCost*P[t][u] ] } @@ -66,4 +66,4 @@ void OptimizedThermalGenerator::setProblemPowerCost(const OptProblemSettings& op return; } -} // namespace Antares::Solver::TSGenerator +} // namespace Antares::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/optimization/SetVariableBounds.cpp b/src/solver/ts-generator/optimized-thermal-generator/optimization/SetVariableBounds.cpp index 9bb4d7974e..3064a544cc 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/optimization/SetVariableBounds.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/optimization/SetVariableBounds.cpp @@ -4,7 +4,7 @@ #include "../main/OptimizedGenerator.h" -namespace Antares::Solver::TSGenerator +namespace Antares::TSGenerator { // TODO CR27: see if to make this bound or constraint - @@ -93,4 +93,4 @@ void OptimizedThermalGenerator::fixBoundsMntEnd(const Unit& unit, } } -} // namespace Antares::Solver::TSGenerator +} // namespace Antares::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/optimization/SolveProbem.cpp b/src/solver/ts-generator/optimized-thermal-generator/optimization/SolveProbem.cpp index dada198ef5..31dea2844a 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/optimization/SolveProbem.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/optimization/SolveProbem.cpp @@ -4,7 +4,7 @@ #include "../main/OptimizedGenerator.h" -namespace Antares::Solver::TSGenerator +namespace Antares::TSGenerator { // call all methods bool OptimizedThermalGenerator::runOptimizationProblem(OptProblemSettings& optSett) @@ -39,4 +39,4 @@ bool OptimizedThermalGenerator::solveProblem(OptProblemSettings& optSett) return true; } -} // namespace Antares::Solver::TSGenerator +} // namespace Antares::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/parameters/CalculateParameters.cpp b/src/solver/ts-generator/optimized-thermal-generator/parameters/CalculateParameters.cpp index d6f1a2c0b2..cd88b7fdcd 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/parameters/CalculateParameters.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/parameters/CalculateParameters.cpp @@ -4,7 +4,7 @@ #include "../main/OptimizedGenerator.h" -namespace Antares::Solver::TSGenerator +namespace Antares::TSGenerator { // methods are ordered in the line of execution order @@ -267,4 +267,4 @@ bool OptimizationParameters::checkTimeHorizon(OptProblemSettings& optSett) return true; } -} // namespace Antares::Solver::TSGenerator +} // namespace Antares::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/parameters/CalculateParametersPerCluster.cpp b/src/solver/ts-generator/optimized-thermal-generator/parameters/CalculateParametersPerCluster.cpp index 66fc38837c..cef1a807d8 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/parameters/CalculateParametersPerCluster.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/parameters/CalculateParametersPerCluster.cpp @@ -4,7 +4,7 @@ #include "../main/OptimizedGenerator.h" -namespace Antares::Solver::TSGenerator +namespace Antares::TSGenerator { int OptimizationParameters::calculateUnitEarliestStartOfFirstMaintenance( @@ -68,4 +68,4 @@ std::vector OptimizationParameters::calculateNumberOfMaintenances( return numberOfMaintenances; } -} // namespace Antares::Solver::TSGenerator +} // namespace Antares::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/parameters/Getters.cpp b/src/solver/ts-generator/optimized-thermal-generator/parameters/Getters.cpp index 7f9cfba5f9..99ccd2b0af 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/parameters/Getters.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/parameters/Getters.cpp @@ -4,7 +4,7 @@ #include "../main/OptimizedGenerator.h" -namespace Antares::Solver::TSGenerator +namespace Antares::TSGenerator { // Getters double OptimizationParameters::getPowerCost(const Data::ThermalCluster& cluster, @@ -71,4 +71,4 @@ int OptimizationParameters::getDaysSinceLastMaintenance(const Data::ThermalClust return clusterData[&cluster].dynamicInputs.daysSinceLastMaintenance[unit]; } -} // namespace Antares::Solver::TSGenerator +} // namespace Antares::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/parameters/OptimizationParameters.h b/src/solver/ts-generator/optimized-thermal-generator/parameters/OptimizationParameters.h index f8704cf4e8..257f43508d 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/parameters/OptimizationParameters.h +++ b/src/solver/ts-generator/optimized-thermal-generator/parameters/OptimizationParameters.h @@ -7,7 +7,7 @@ #include "../../randomized-thermal-generator/RandomizedGenerator.h" #include "../main/OptimizedGenerator.h" -namespace Antares::Solver::TSGenerator +namespace Antares::TSGenerator { // it is better to immediately calculate and populate structure @@ -71,7 +71,7 @@ class OptimizationParameters : public GeneratorTempData OptimizationVariables& vars, OptimizationResults& scenarioResults, Solver::Progression::Task& progr, - IResultWriter& writer) : + Solver::IResultWriter& writer) : GeneratorTempData(study, progr, writer), maintenanceGroup_(maintenanceGroup), globalThermalTSgeneration_(globalThermalTSgeneration), @@ -169,4 +169,4 @@ class OptimizationParameters : public GeneratorTempData void printAvailability(OptProblemSettings& optSett); }; -} // namespace Antares::Solver::TSGenerator +} // namespace Antares::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/postoptimization/PostScenarioOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/postoptimization/PostScenarioOptimization.cpp index ec28bd0b44..83cfbd1275 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/postoptimization/PostScenarioOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/postoptimization/PostScenarioOptimization.cpp @@ -4,7 +4,7 @@ #include "../main/OptimizedGenerator.h" -namespace Antares::Solver::TSGenerator +namespace Antares::TSGenerator { void OptimizationParameters::postScenarioOptimization(OptProblemSettings& optSett) @@ -174,4 +174,4 @@ void OptimizationParameters::reSetNumberOfMaintenances() return; } -} // namespace Antares::Solver::TSGenerator +} // namespace Antares::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/postoptimization/PostTimeStepOptimization.cpp b/src/solver/ts-generator/optimized-thermal-generator/postoptimization/PostTimeStepOptimization.cpp index 9752b832c2..ef15b50dd5 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/postoptimization/PostTimeStepOptimization.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/postoptimization/PostTimeStepOptimization.cpp @@ -4,7 +4,7 @@ #include "../main/OptimizedGenerator.h" -namespace Antares::Solver::TSGenerator +namespace Antares::TSGenerator { void OptimizationParameters::postTimeStepOptimization(OptProblemSettings& optSett) @@ -151,4 +151,4 @@ void OptimizationParameters::reCalculateNumberOfMaintenances() } } -} // namespace Antares::Solver::TSGenerator +} // namespace Antares::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/postoptimization/WriteResults.cpp b/src/solver/ts-generator/optimized-thermal-generator/postoptimization/WriteResults.cpp index 95e5c61893..19735fb40e 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/postoptimization/WriteResults.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/postoptimization/WriteResults.cpp @@ -4,7 +4,7 @@ #include "../main/OptimizedGenerator.h" -namespace Antares::Solver::TSGenerator +namespace Antares::TSGenerator { // this method is called at the very end @@ -42,4 +42,4 @@ void OptimizedThermalGenerator::writeTsResults() return; } -} // namespace Antares::Solver::TSGenerator +} // namespace Antares::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/support/SupportFunctions.cpp b/src/solver/ts-generator/optimized-thermal-generator/support/SupportFunctions.cpp index c8a71191db..eadb9a5dee 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/support/SupportFunctions.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/support/SupportFunctions.cpp @@ -7,7 +7,7 @@ #include "../main/OptimizedGenerator.h" #include "../support/SupportFunctions.h" -namespace Antares::Solver::TSGenerator +namespace Antares::TSGenerator { // calculate Average time-series functions @@ -196,4 +196,4 @@ std::array calculateAvrUnitDailyCost(const Data::ThermalC return avrCostDailyValues; } -} // namespace Antares::Solver::TSGenerator +} // namespace Antares::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/support/SupportFunctions.h b/src/solver/ts-generator/optimized-thermal-generator/support/SupportFunctions.h index 1fb5554937..ccf618e335 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/support/SupportFunctions.h +++ b/src/solver/ts-generator/optimized-thermal-generator/support/SupportFunctions.h @@ -6,7 +6,7 @@ #include "../main/OptimizedGenerator.h" -namespace Antares::Solver::TSGenerator +namespace Antares::TSGenerator { // support functions @@ -36,4 +36,4 @@ std::array calculateAvrUnitDailyCost(const Data::ThermalC template void printColumnToFile(const std::vector>& data, const std::string& filename); -} // namespace Antares::Solver::TSGenerator +} // namespace Antares::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/support/SupportStructures.cpp b/src/solver/ts-generator/optimized-thermal-generator/support/SupportStructures.cpp index ede3325fe4..e49e11760f 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/support/SupportStructures.cpp +++ b/src/solver/ts-generator/optimized-thermal-generator/support/SupportStructures.cpp @@ -4,7 +4,7 @@ #include "SupportStructures.h" -namespace Antares::Solver::TSGenerator +namespace Antares::TSGenerator { // post-time step optimization - functions int Maintenances::startDay(int limit) const @@ -54,4 +54,4 @@ void Unit::calculateAvailableDailyPower(int tsCount) } } -} // namespace Antares::Solver::TSGenerator +} // namespace Antares::TSGenerator diff --git a/src/solver/ts-generator/optimized-thermal-generator/support/SupportStructures.h b/src/solver/ts-generator/optimized-thermal-generator/support/SupportStructures.h index a310f10172..7f9674f38a 100644 --- a/src/solver/ts-generator/optimized-thermal-generator/support/SupportStructures.h +++ b/src/solver/ts-generator/optimized-thermal-generator/support/SupportStructures.h @@ -9,7 +9,7 @@ using namespace operations_research; -namespace Antares::Solver::TSGenerator +namespace Antares::TSGenerator { // this class stores data about optimization problem settings @@ -81,4 +81,4 @@ struct OptimizationVariables std::vector spill; // pointers to Spill[t] variables }; -} // namespace Antares::Solver::TSGenerator +} // namespace Antares::TSGenerator diff --git a/src/solver/ts-generator/randomized-thermal-generator/RandomizedGenerator.h b/src/solver/ts-generator/randomized-thermal-generator/RandomizedGenerator.h index 9d20d672d5..936193d6e6 100644 --- a/src/solver/ts-generator/randomized-thermal-generator/RandomizedGenerator.h +++ b/src/solver/ts-generator/randomized-thermal-generator/RandomizedGenerator.h @@ -11,7 +11,7 @@ using namespace Yuni; #define FAILURE_RATE_EQ_1 0.999 -namespace Antares::Solver::TSGenerator +namespace Antares::TSGenerator { class GeneratorTempData @@ -20,7 +20,7 @@ class GeneratorTempData friend class OptimizedThermalGenerator; public: - GeneratorTempData(Data::Study& study, Solver::Progression::Task& progr, IResultWriter& writer); + GeneratorTempData(Data::Study& study, Solver::Progression::Task& progr, Solver::IResultWriter& writer); void prepareOutputFoldersForAllAreas(uint year); @@ -76,7 +76,7 @@ class GeneratorTempData String pTempFilename; Solver::Progression::Task& pProgression; - IResultWriter& pWriter; + Solver::IResultWriter& pWriter; }; -} // namespace Antares::Solver::TSGenerator \ No newline at end of file +} // namespace Antares::TSGenerator \ No newline at end of file diff --git a/src/solver/ts-generator/thermal.cpp b/src/solver/ts-generator/thermal.cpp index 074a2a0101..6bb2520467 100644 --- a/src/solver/ts-generator/thermal.cpp +++ b/src/solver/ts-generator/thermal.cpp @@ -29,7 +29,7 @@ #include "randomized-thermal-generator/RandomizedGenerator.h" #include "optimized-thermal-generator/main/OptimizedGenerator.h" -namespace Antares::Solver::TSGenerator +namespace Antares::TSGenerator { bool GenerateRandomizedThermalTimeSeries(Data::Study& study, @@ -111,4 +111,4 @@ bool GenerateThermalTimeSeries(Data::Study& study, } } -} // namespace Antares::Solver::TSGenerator +} // namespace Antares::TSGenerator From 4dd45da24cb163267e5c0f211195053bc83a67e6 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Mon, 7 Oct 2024 22:14:53 +0200 Subject: [PATCH 312/315] fix issue with Namespaces-2 --- .../randomized-thermal-generator/RandomizedGenerator.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/solver/ts-generator/randomized-thermal-generator/RandomizedGenerator.cpp b/src/solver/ts-generator/randomized-thermal-generator/RandomizedGenerator.cpp index 8a31b1ac84..d936f425dc 100644 --- a/src/solver/ts-generator/randomized-thermal-generator/RandomizedGenerator.cpp +++ b/src/solver/ts-generator/randomized-thermal-generator/RandomizedGenerator.cpp @@ -7,12 +7,12 @@ using namespace Yuni; -namespace Antares::Solver::TSGenerator +namespace Antares::TSGenerator { GeneratorTempData::GeneratorTempData(Data::Study& study, Solver::Progression::Task& progr, - IResultWriter& writer) : + Solver::IResultWriter& writer) : study(study), rndgenerator(study.runtime->random[Data::seedTsGenThermal]), pProgression(progr), @@ -501,4 +501,4 @@ void GeneratorTempData::operator()(Data::Area& area, Data::ThermalCluster& clust cluster.calculationOfSpinning(); } -} // namespace Antares::Solver::TSGenerator +} // namespace Antares::TSGenerator From 833b30228835ac5e79730e7eec4fb4159f801ddb Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Tue, 8 Oct 2024 01:16:32 +0200 Subject: [PATCH 313/315] catch RTE ts-gen changes --- .../RandomizedGenerator.cpp | 11 ++++++----- .../RandomizedGenerator.h | 5 +++-- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/solver/ts-generator/randomized-thermal-generator/RandomizedGenerator.cpp b/src/solver/ts-generator/randomized-thermal-generator/RandomizedGenerator.cpp index d936f425dc..fadbb1c3f4 100644 --- a/src/solver/ts-generator/randomized-thermal-generator/RandomizedGenerator.cpp +++ b/src/solver/ts-generator/randomized-thermal-generator/RandomizedGenerator.cpp @@ -25,6 +25,9 @@ GeneratorTempData::GeneratorTempData(Data::Study& study, nbThermalTimeseries = parameters.nbTimeSeriesThermal; derated = parameters.derated; + + FPOW.resize(DAYS_PER_YEAR); + PPOW.resize(DAYS_PER_YEAR); } void GeneratorTempData::writeResultsToDisk(const Data::Area& area, @@ -143,15 +146,11 @@ void GeneratorTempData::operator()(Data::Area& area, Data::ThermalCluster& clust if (0 == cluster.unitCount or 0 == cluster.nominalCapacity) { - cluster.series.timeSeries.reset(1, nbHoursPerYear); - if (archive) writeResultsToDisk(area, cluster); return; } - cluster.series.timeSeries.resize(nbThermalTimeseries, nbHoursPerYear); - const auto& preproData = *(cluster.prepro); int AUN = (int)cluster.unitCount; @@ -184,6 +183,9 @@ void GeneratorTempData::operator()(Data::Area& area, Data::ThermalCluster& clust for (uint d = 0; d < daysPerYear; ++d) { + FPOW[d].resize(cluster.unitCount + 1); + PPOW[d].resize(cluster.unitCount + 1); + PODOfTheDay = (int)POD[d]; FODOfTheDay = (int)FOD[d]; @@ -257,7 +259,6 @@ void GeneratorTempData::operator()(Data::Area& area, Data::ThermalCluster& clust for (uint dayInTheYear = 0; dayInTheYear < daysPerYear; ++dayInTheYear) { - assert(AUN <= 100 and "Thermal Prepro: AUN is out of bounds (>=100)"); assert(dayInTheYear < 366); assert(not(lf[dayInTheYear] < 0.)); assert(not(lp[dayInTheYear] < 0.)); diff --git a/src/solver/ts-generator/randomized-thermal-generator/RandomizedGenerator.h b/src/solver/ts-generator/randomized-thermal-generator/RandomizedGenerator.h index 936193d6e6..1f61d0284a 100644 --- a/src/solver/ts-generator/randomized-thermal-generator/RandomizedGenerator.h +++ b/src/solver/ts-generator/randomized-thermal-generator/RandomizedGenerator.h @@ -71,8 +71,9 @@ class GeneratorTempData double ap[366]; double bf[366]; double bp[366]; - double FPOW[366][102]; - double PPOW[366][102]; + + std::vector> FPOW; + std::vector> PPOW; String pTempFilename; Solver::Progression::Task& pProgression; From fbce28fee75f79b4b25271d74d085abaddcfe257 Mon Sep 17 00:00:00 2001 From: payetvin <113102157+payetvin@users.noreply.github.com> Date: Thu, 10 Oct 2024 12:50:17 +0200 Subject: [PATCH 314/315] Update vcpkg to latest version for branch 8.8.x (#2457) --- vcpkg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vcpkg b/vcpkg index e3ad383ceb..c82f746672 160000 --- a/vcpkg +++ b/vcpkg @@ -1 +1 @@ -Subproject commit e3ad383ceb886677eb181e16adeeb4d4a2c2d4c4 +Subproject commit c82f74667287d3dc386bce81e44964370c91a289 From 76a89f99bb672cc66188b9594a1f307f4e91a679 Mon Sep 17 00:00:00 2001 From: Milos-RTEi Date: Fri, 1 Nov 2024 11:58:36 +0100 Subject: [PATCH 315/315] try fix - increase stack memory --- .github/workflows/windows-vcpkg.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/windows-vcpkg.yml b/.github/workflows/windows-vcpkg.yml index 14ec769c8e..e95b495723 100644 --- a/.github/workflows/windows-vcpkg.yml +++ b/.github/workflows/windows-vcpkg.yml @@ -153,7 +153,8 @@ jobs: -DBUILD_TOOLS=ON \ -DBUILD_not_system=OFF \ -DPython3_EXECUTABLE="${{ env.Python3_ROOT_DIR }}/python.exe" \ - -DCMAKE_VS_GLOBALS="CLToolExe=cl.exe;CLToolPath=${GITHUB_WORKSPACE}/ccache;TrackFileAccess=false;UseMultiToolTask=true;DebugInformationFormat=OldStyle" + -DCMAKE_VS_GLOBALS="CLToolExe=cl.exe;CLToolPath=${GITHUB_WORKSPACE}/ccache;TrackFileAccess=false;UseMultiToolTask=true;DebugInformationFormat=OldStyle" \ + -DCMAKE_EXE_LINKER_FLAGS="/STACK:33554432" - name: Build shell: bash