diff --git a/src/solver/optimisation/CMakeLists.txt b/src/solver/optimisation/CMakeLists.txt index 0d64d42e44..bd6e6c4d64 100644 --- a/src/solver/optimisation/CMakeLists.txt +++ b/src/solver/optimisation/CMakeLists.txt @@ -75,6 +75,8 @@ set(RTESOLVER_OPT include/antares/solver/optimisation/constraints/constraint_builder_utils.h include/antares/solver/optimisation/constraints/AreaBalance.h constraints/AreaBalance.cpp + include/antares/solver/optimisation/constraints/NetPosition.h + constraints/NetPosition.cpp include/antares/solver/optimisation/constraints/FictitiousLoad.h constraints/FictitiousLoad.cpp include/antares/solver/optimisation/constraints/ShortTermStorageLevel.h diff --git a/src/solver/optimisation/constraints/AreaBalance.cpp b/src/solver/optimisation/constraints/AreaBalance.cpp index c0c254854d..b35139d584 100644 --- a/src/solver/optimisation/constraints/AreaBalance.cpp +++ b/src/solver/optimisation/constraints/AreaBalance.cpp @@ -44,22 +44,9 @@ void AreaBalance::add(int pdt, int pays) builder.updateHourWithinWeek(pdt); - int interco = data.IndexDebutIntercoOrigine[pays]; - while (interco >= 0) - { - builder.NTCDirect(interco, 1.0); - interco = data.IndexSuivantIntercoOrigine[interco]; - } - - interco = data.IndexDebutIntercoExtremite[pays]; - while (interco >= 0) - { - builder.NTCDirect(interco, -1.0); - interco = data.IndexSuivantIntercoExtremite[interco]; - } - ExportPaliers(data.PaliersThermiquesDuPays[pays], builder); - builder.HydProd(pays, -1.0) + builder.NetPosition(pays, 1) + .HydProd(pays, -1.0) .Pumping(pays, 1.0) .PositiveUnsuppliedEnergy(pays, -1.0) .NegativeUnsuppliedEnergy(pays, 1.0); diff --git a/src/solver/optimisation/constraints/ConstraintBuilder.cpp b/src/solver/optimisation/constraints/ConstraintBuilder.cpp index 6d7662a605..217a386749 100644 --- a/src/solver/optimisation/constraints/ConstraintBuilder.cpp +++ b/src/solver/optimisation/constraints/ConstraintBuilder.cpp @@ -49,6 +49,12 @@ ConstraintBuilder& ConstraintBuilder::DispatchableProduction(unsigned int index, return *this; } +ConstraintBuilder& ConstraintBuilder::NetPosition(unsigned int index, double coeff) +{ + AddVariable(variableManager_.NetPosition(index, hourInWeek_), coeff); + return *this; +} + ConstraintBuilder& ConstraintBuilder::NumberOfDispatchableUnits(unsigned int index, double coeff) { AddVariable(variableManager_.NumberOfDispatchableUnits(index, hourInWeek_), coeff); diff --git a/src/solver/optimisation/constraints/Group1.cpp b/src/solver/optimisation/constraints/Group1.cpp index 61de7cf2b3..bb5b5c199f 100644 --- a/src/solver/optimisation/constraints/Group1.cpp +++ b/src/solver/optimisation/constraints/Group1.cpp @@ -35,6 +35,15 @@ AreaBalanceData Group1::GetAreaBalanceData() .ShortTermStorage = problemeHebdo_->ShortTermStorage}; } +NetPositionData Group1::GetNetPositionData() +{ + return {.CorrespondanceCntNativesCntOptim = problemeHebdo_->CorrespondanceCntNativesCntOptim, + .IndexDebutIntercoOrigine = problemeHebdo_->IndexDebutIntercoOrigine, + .IndexSuivantIntercoOrigine = problemeHebdo_->IndexSuivantIntercoOrigine, + .IndexDebutIntercoExtremite = problemeHebdo_->IndexDebutIntercoExtremite, + .IndexSuivantIntercoExtremite = problemeHebdo_->IndexSuivantIntercoExtremite}; +} + FictitiousLoadData Group1::GetFictitiousLoadData() { return {.CorrespondanceCntNativesCntOptim = problemeHebdo_->CorrespondanceCntNativesCntOptim, @@ -79,6 +88,9 @@ void Group1::BuildConstraints() auto areaBalanceData = GetAreaBalanceData(); AreaBalance areaBalance(builder_, areaBalanceData); + auto netPositionData = GetNetPositionData(); + NetPosition netPosition(builder_, netPositionData); + auto fictitiousLoadData = GetFictitiousLoadData(); FictitiousLoad fictitiousLoad(builder_, fictitiousLoadData); @@ -116,6 +128,7 @@ void Group1::BuildConstraints() for (uint32_t pays = 0; pays < problemeHebdo_->NombreDePays; pays++) { areaBalance.add(pdt, pays); + netPosition.add(pdt, pays); fictitiousLoad.add(pdt, pays); shortTermStorageLevel.add(pdt, pays); shortTermStorageCostVariationInjectionBackward.add(pdt, pays); diff --git a/src/solver/optimisation/constraints/NetPosition.cpp b/src/solver/optimisation/constraints/NetPosition.cpp new file mode 100644 index 0000000000..3f5edbed75 --- /dev/null +++ b/src/solver/optimisation/constraints/NetPosition.cpp @@ -0,0 +1,47 @@ +/* +** 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 "antares/solver/optimisation/constraints/NetPosition.h" + +void NetPosition::add(int pdt, int pays) +{ + int interco = data.IndexDebutIntercoOrigine[pays]; + while (interco >= 0) + { + builder.NTCDirect(interco, 1.0); + interco = data.IndexSuivantIntercoOrigine[interco]; + } + + interco = data.IndexDebutIntercoExtremite[pays]; + while (interco >= 0) + { + builder.NTCDirect(interco, -1.0); + interco = data.IndexSuivantIntercoExtremite[interco]; + } + + ConstraintNamer namer(builder.data.NomDesContraintes); + namer.UpdateTimeStep(builder.data.weekInTheYear * 168 + pdt); + namer.UpdateArea(builder.data.NomsDesPays[pays]); + namer.NetPosition(builder.data.nombreDeContraintes); + + builder.NetPosition(pays, -1.0); + builder.equalTo().build(); +} diff --git a/src/solver/optimisation/include/antares/solver/optimisation/constraints/ConstraintBuilder.h b/src/solver/optimisation/include/antares/solver/optimisation/constraints/ConstraintBuilder.h index 31019332d3..f7f1906373 100644 --- a/src/solver/optimisation/include/antares/solver/optimisation/constraints/ConstraintBuilder.h +++ b/src/solver/optimisation/include/antares/solver/optimisation/constraints/ConstraintBuilder.h @@ -137,6 +137,8 @@ class ConstraintBuilder int offset = 0, int delta = 0); + ConstraintBuilder& NetPosition(unsigned int index, double coeff); + ConstraintBuilder& HydProd(unsigned int index, double coeff); ConstraintBuilder& HydProdDown(unsigned int index, double coeff); diff --git a/src/solver/optimisation/include/antares/solver/optimisation/constraints/Group1.h b/src/solver/optimisation/include/antares/solver/optimisation/constraints/Group1.h index c74567716e..9f866892b0 100644 --- a/src/solver/optimisation/include/antares/solver/optimisation/constraints/Group1.h +++ b/src/solver/optimisation/include/antares/solver/optimisation/constraints/Group1.h @@ -25,6 +25,7 @@ #include "ConstraintGroup.h" #include "FictitiousLoad.h" #include "FlowDissociation.h" +#include "NetPosition.h" #include "ShortTermStorageLevel.h" class Group1: public ConstraintGroup @@ -36,6 +37,7 @@ class Group1: public ConstraintGroup private: AreaBalanceData GetAreaBalanceData(); + NetPositionData GetNetPositionData(); FictitiousLoadData GetFictitiousLoadData(); ShortTermStorageData GetShortTermStorageData(); diff --git a/src/solver/optimisation/include/antares/solver/optimisation/constraints/NetPosition.h b/src/solver/optimisation/include/antares/solver/optimisation/constraints/NetPosition.h new file mode 100644 index 0000000000..139728cee2 --- /dev/null +++ b/src/solver/optimisation/include/antares/solver/optimisation/constraints/NetPosition.h @@ -0,0 +1,56 @@ +/* +** 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 +#include "ConstraintBuilder.h" + +struct NetPositionData +{ + std::vector& CorrespondanceCntNativesCntOptim; + const std::vector& IndexDebutIntercoOrigine; + const std::vector& IndexSuivantIntercoOrigine; + const std::vector& IndexDebutIntercoExtremite; + const std::vector& IndexSuivantIntercoExtremite; +}; + +/*! + * represent 'Net Position' constraint type + */ + +class NetPosition: public ConstraintFactory +{ +public: + NetPosition(ConstraintBuilder& builder, NetPositionData& data): + ConstraintFactory(builder), + data(data) + { + } + + /*! + * @brief Add variables to the constraint and update constraints Matrix + * @param pdt : timestep + * @param pays : area + */ + + void add(int pdt, int pays); + +private: + NetPositionData& data; +}; diff --git a/src/solver/optimisation/include/antares/solver/optimisation/opt_rename_problem.h b/src/solver/optimisation/include/antares/solver/optimisation/opt_rename_problem.h index c7c3dff284..ab526cbf04 100644 --- a/src/solver/optimisation/include/antares/solver/optimisation/opt_rename_problem.h +++ b/src/solver/optimisation/include/antares/solver/optimisation/opt_rename_problem.h @@ -114,6 +114,7 @@ class VariableNamer: public Namer void PositiveUnsuppliedEnergy(unsigned int variable); void NegativeUnsuppliedEnergy(unsigned int variable); void AreaBalance(unsigned int variable); + void NetPosition(unsigned int variable); private: void SetAreaVariableName(unsigned int variable, @@ -133,6 +134,7 @@ class ConstraintNamer: public Namer const std::string& origin, const std::string& destination); + void NetPosition(unsigned int variable); void AreaBalance(unsigned int constraint); void FictiveLoads(unsigned int constraint); void HydroPower(unsigned int constraint); diff --git a/src/solver/optimisation/opt_construction_variables_optimisees_lineaire.cpp b/src/solver/optimisation/opt_construction_variables_optimisees_lineaire.cpp index d2e68570e9..ace9a312fe 100644 --- a/src/solver/optimisation/opt_construction_variables_optimisees_lineaire.cpp +++ b/src/solver/optimisation/opt_construction_variables_optimisees_lineaire.cpp @@ -86,6 +86,12 @@ void OPT_ConstruireLaListeDesVariablesOptimiseesDuProblemeLineaire(PROBLEME_HEBD NombreDeVariables++; } + // NetPosition + ProblemeAResoudre->TypeDeVariable[NombreDeVariables] = VARIABLE_NON_BORNEE; + variableManager.NetPosition(pays, pdt) = NombreDeVariables; + variableNamer.NetPosition(NombreDeVariables); + NombreDeVariables++; + for (const auto& storage: problemeHebdo->ShortTermStorage[pays]) { const int clusterGlobalIndex = storage.clusterGlobalIndex; diff --git a/src/solver/optimisation/opt_decompte_variables_et_contraintes.cpp b/src/solver/optimisation/opt_decompte_variables_et_contraintes.cpp index 79c29c58ab..720e8bcb83 100644 --- a/src/solver/optimisation/opt_decompte_variables_et_contraintes.cpp +++ b/src/solver/optimisation/opt_decompte_variables_et_contraintes.cpp @@ -281,6 +281,13 @@ int OPT_DecompteDesVariablesEtDesContraintesDuProblemeAOptimiser(PROBLEME_HEBDO* } } + // NetPosition + for (uint32_t pays = 0; pays < problemeHebdo->NombreDePays; pays++) + { + ProblemeAResoudre->NombreDeVariables += nombreDePasDeTempsPourUneOptimisation; + ProblemeAResoudre->NombreDeContraintes += nombreDePasDeTempsPourUneOptimisation; + } + if (problemeHebdo->OptimisationAvecCoutsDeDemarrage) { OPT_DecompteDesVariablesEtDesContraintesCoutsDeDemarrage(problemeHebdo); diff --git a/src/solver/optimisation/opt_gestion_des_bornes_cas_lineaire.cpp b/src/solver/optimisation/opt_gestion_des_bornes_cas_lineaire.cpp index 5c507fbed7..5e6b7673f7 100644 --- a/src/solver/optimisation/opt_gestion_des_bornes_cas_lineaire.cpp +++ b/src/solver/optimisation/opt_gestion_des_bornes_cas_lineaire.cpp @@ -470,6 +470,14 @@ void OPT_InitialiserLesBornesDesVariablesDuProblemeLineaire(PROBLEME_HEBDO* prob AdresseOuPlacerLaValeurDesVariablesOptimisees[var] = adresseDuResultat; } } + for (uint32_t pays = 0; pays < problemeHebdo->NombreDePays; pays++) + { + int var = problemeHebdo->CorrespondanceVarNativesVarOptim[pdtHebdo] + .NumeroDeVariableNetPosition[pays]; + double* adresseDuResultat = &( + problemeHebdo->ResultatsHoraires[pays].NetPositionHoraire[pdtHebdo]); + AdresseOuPlacerLaValeurDesVariablesOptimisees[var] = adresseDuResultat; + } } setBoundsForUnsuppliedEnergy(problemeHebdo, diff --git a/src/solver/optimisation/opt_rename_problem.cpp b/src/solver/optimisation/opt_rename_problem.cpp index b385c0f8f5..622e8fbb09 100644 --- a/src/solver/optimisation/opt_rename_problem.cpp +++ b/src/solver/optimisation/opt_rename_problem.cpp @@ -192,6 +192,11 @@ void VariableNamer::ShortTermStorageCostVariationWithdrawal(unsigned int variabl SetShortTermStorageVariableName(variable, "CostVariationWithdrawal", shortTermStorageName); } +void VariableNamer::NetPosition(unsigned int constraint) +{ + SetAreaElementNameHour(constraint, "NetPositionVariable"); +} + void VariableNamer::HydProd(unsigned int variable) { SetAreaElementNameHour(variable, "HydProd"); @@ -275,6 +280,11 @@ void ConstraintNamer::AreaBalance(unsigned int constraint) SetAreaElementNameHour(constraint, "AreaBalance"); } +void ConstraintNamer::NetPosition(unsigned int constraint) +{ + SetAreaElementNameHour(constraint, "NetPositionConstraint"); +} + void ConstraintNamer::FictiveLoads(unsigned int constraint) { SetAreaElementNameHour(constraint, "FictiveLoads"); diff --git a/src/solver/optimisation/variables/VariableManagement.cpp b/src/solver/optimisation/variables/VariableManagement.cpp index 37d50b5f97..56ae54706f 100644 --- a/src/solver/optimisation/variables/VariableManagement.cpp +++ b/src/solver/optimisation/variables/VariableManagement.cpp @@ -156,6 +156,15 @@ int& VariableManager::ShortTermStorageCostVariationWithdrawal(unsigned int index .SIM_ShortTermStorage.CostVariationWithdrawal[index]; } +int& VariableManager::NetPosition(unsigned int index, + unsigned int hourInWeek, + int offset, + int delta) +{ + auto pdt = GetShiftedTimeStep(offset, delta, hourInWeek); + return CorrespondanceVarNativesVarOptim_[pdt].NumeroDeVariableNetPosition[index]; +} + int& VariableManager::HydProd(unsigned int index, unsigned int hourInWeek, int offset, int delta) { auto pdt = GetShiftedTimeStep(offset, delta, hourInWeek); diff --git a/src/solver/optimisation/variables/VariableManagement.h b/src/solver/optimisation/variables/VariableManagement.h index 252c4007dd..9b730f80d3 100644 --- a/src/solver/optimisation/variables/VariableManagement.h +++ b/src/solver/optimisation/variables/VariableManagement.h @@ -75,6 +75,8 @@ class VariableManager int offset = 0, int delta = 0); + int& NetPosition(unsigned int index, unsigned int hourInWeek, int offset = 0, int delta = 0); + int& HydProd(unsigned int index, unsigned int hourInWeek, int offset = 0, int delta = 0); int& HydProdDown(unsigned int index, unsigned int hourInWeek, int offset = 0, int delta = 0); diff --git a/src/solver/simulation/include/antares/solver/simulation/sim_structure_probleme_economique.h b/src/solver/simulation/include/antares/solver/simulation/sim_structure_probleme_economique.h index 35051ba2d5..a82eee38f5 100644 --- a/src/solver/simulation/include/antares/solver/simulation/sim_structure_probleme_economique.h +++ b/src/solver/simulation/include/antares/solver/simulation/sim_structure_probleme_economique.h @@ -45,6 +45,7 @@ struct CORRESPONDANCES_DES_VARIABLES std::vector NumeroDeVariableDuPalierThermique; + std::vector NumeroDeVariableNetPosition; std::vector NumeroDeVariablesDeLaProdHyd; std::vector NumeroDeVariablesDePompage; @@ -438,6 +439,8 @@ struct RESULTATS_HORAIRES std::vector CoutsMarginauxHoraires; std::vector ProductionThermique; // index is pdtHebdo + std::vector NetPositionHoraire; + std::vector<::ShortTermStorage::RESULTS> ShortTermStorage; }; diff --git a/src/solver/simulation/sim_alloc_probleme_hebdo.cpp b/src/solver/simulation/sim_alloc_probleme_hebdo.cpp index dd7480671c..38d64d762e 100644 --- a/src/solver/simulation/sim_alloc_probleme_hebdo.cpp +++ b/src/solver/simulation/sim_alloc_probleme_hebdo.cpp @@ -157,6 +157,7 @@ void SIM_AllocationProblemePasDeTemps(PROBLEME_HEBDO& problem, variablesMapping.NumeroDeVariableDuPalierThermique .assign(study.runtime.thermalPlantTotalCount, 0); + variablesMapping.NumeroDeVariableNetPosition.assign(nbPays, 0); variablesMapping.NumeroDeVariablesDeLaProdHyd.assign(nbPays, 0); variablesMapping.NumeroDeVariablesDePompage.assign(nbPays, 0); variablesMapping.NumeroDeVariablesDeNiveau.assign(nbPays, 0); @@ -397,6 +398,9 @@ void SIM_AllocateAreas(PROBLEME_HEBDO& problem, problem.ResultatsHoraires[k].TurbinageHoraire.assign(NombreDePasDeTemps, 0.); problem.ResultatsHoraires[k].PompageHoraire.assign(NombreDePasDeTemps, 0.); + + problem.ResultatsHoraires[k].NetPositionHoraire.assign(NombreDePasDeTemps, 0.); + problem.ResultatsHoraires[k].CoutsMarginauxHoraires.assign(NombreDePasDeTemps, 0.); problem.ResultatsHoraires[k].niveauxHoraires.assign(NombreDePasDeTemps, 0.); problem.ResultatsHoraires[k].valeurH2oHoraire.assign(NombreDePasDeTemps, 0.);