diff --git a/src/solver/optimisation/AreaBalance.cpp b/src/solver/optimisation/AreaBalance.cpp new file mode 100644 index 0000000000..6134be2557 --- /dev/null +++ b/src/solver/optimisation/AreaBalance.cpp @@ -0,0 +1,66 @@ +#include "AreaBalance.h" + +static void shortTermStorageBalance(const ::ShortTermStorage::AREA_INPUT& shortTermStorageInput, + ConstraintBuilder& constraintBuilder, + std::vector& InjectionVariable, + std::vector& WithdrawalVariable) +{ + for (const auto& storage : shortTermStorageInput) + { + unsigned index = storage.clusterGlobalIndex; + if (const int varInjection = InjectionVariable[index]; varInjection >= 0) + { + constraintBuilder.include(Variable::ShortTermStorageInjection(index), 1.0); + } + if (const int varWithdrawal = WithdrawalVariable[index]; varWithdrawal >= 0) + { + constraintBuilder.include(Variable::ShortTermStorageWithdrawal(index), -1.0); + } + } +} + +// Constraint definitions +void AreaBalance::add(int pdt, int pays, AreaBalanceData& data) +{ + // /** can be done without this --- keep it for now**/ + // data.NumeroDeContrainteDesBilansPays[pays] = builder.data.nombreDeContraintes; + + // /******/ + // // TODO improve this + + // ConstraintNamer namer(builder.data.NomDesContraintes, builder.data.NamedProblems); + // namer.UpdateTimeStep(builder.data.weekInTheYear * 168 + pdt); + // namer.UpdateArea(builder.data.NomsDesPays[pays]); + // namer.AreaBalance(builder.data.nombreDeContraintes); + + // builder.updateHourWithinWeek(pdt); + + // int interco = data.IndexDebutIntercoOrigine[pays]; + // while (interco >= 0) + // { + // builder.include(Variable::NTCDirect(interco), 1.0); + // interco = data.IndexSuivantIntercoOrigine[interco]; + // } + + // interco = data.IndexDebutIntercoExtremite[pays]; + // while (interco >= 0) + // { + // builder.include(Variable::NTCDirect(interco), -1.0); + // interco = data.IndexSuivantIntercoExtremite[interco]; + // } + + // exportPaliers(data.PaliersThermiquesDuPays, builder); + // builder.include(Variable::HydProd(pays), -1.0) + // .include(Variable::Pumping(pays), 1.0) + // .include(Variable::PositiveUnsuppliedEnergy(pays), -1.0) + // .include(Variable::NegativeUnsuppliedEnergy(pays), 1.0); + + // shortTermStorageBalance( + // data.ShortTermStorage[pays], builder, data.InjectionVariable, data.WithdrawalVariable); + + // builder.equalTo(); + // builder.build(); + logs.info() << "" << data.NumeroDeContrainteDesBilansPays[pays] << "\n"; + int a = 13; + int b = a / 33; +} diff --git a/src/solver/optimisation/AreaBalance.h b/src/solver/optimisation/AreaBalance.h new file mode 100644 index 0000000000..6a970cdab2 --- /dev/null +++ b/src/solver/optimisation/AreaBalance.h @@ -0,0 +1,46 @@ +#pragma once +#include "constraint_builder.h" + +struct AreaBalanceData +{ + AreaBalanceData(std::vector& NumeroDeContrainteDesBilansPays, + std::vector& InjectionVariable, + std::vector& WithdrawalVariable, + const std::vector& IndexDebutIntercoOrigine, + const std::vector& IndexSuivantIntercoOrigine, + const std::vector& IndexDebutIntercoExtremite, + const std::vector& IndexSuivantIntercoExtremite, + const PALIERS_THERMIQUES& PaliersThermiquesDuPays, + const std::vector<::ShortTermStorage::AREA_INPUT>& ShortTermStorage) + + : + NumeroDeContrainteDesBilansPays(NumeroDeContrainteDesBilansPays), + InjectionVariable(InjectionVariable), + WithdrawalVariable(WithdrawalVariable), + IndexDebutIntercoOrigine(IndexDebutIntercoOrigine), + IndexSuivantIntercoOrigine(IndexSuivantIntercoOrigine), + IndexDebutIntercoExtremite(IndexDebutIntercoExtremite), + IndexSuivantIntercoExtremite(IndexSuivantIntercoExtremite), + PaliersThermiquesDuPays(PaliersThermiquesDuPays), + ShortTermStorage(ShortTermStorage) + { + } + + std::vector& NumeroDeContrainteDesBilansPays; + std::vector& InjectionVariable; + std::vector& WithdrawalVariable; + const std::vector& IndexDebutIntercoOrigine; + const std::vector& IndexSuivantIntercoOrigine; + const std::vector& IndexDebutIntercoExtremite; + const std::vector& IndexSuivantIntercoExtremite; + const PALIERS_THERMIQUES& PaliersThermiquesDuPays; + const std::vector<::ShortTermStorage::AREA_INPUT>& ShortTermStorage; +}; + +class AreaBalance : private Constraint +{ +public: + using Constraint::Constraint; + + void add(int pdt, int pays, AreaBalanceData& data); +}; \ No newline at end of file diff --git a/src/solver/optimisation/AreaHydroLevel.cpp b/src/solver/optimisation/AreaHydroLevel.cpp new file mode 100644 index 0000000000..01ead98485 --- /dev/null +++ b/src/solver/optimisation/AreaHydroLevel.cpp @@ -0,0 +1,28 @@ +#include "AreaHydroLevel.h" + +void AreaHydroLevel::add(int pays, int pdt, AreaHydroLevelData& data) +{ + data.NumeroDeContrainteDesNiveauxPays[pays] = builder.data.nombreDeContraintes; + if (data.SuiviNiveauHoraire) + { + builder.updateHourWithinWeek(pdt).include(Variable::HydroLevel(pays), 1.0); + if (pdt > 0) + { + builder.updateHourWithinWeek(pdt - 1).include(Variable::HydroLevel(pays), -1.0); + } + ConstraintNamer namer(builder.data.NomDesContraintes, builder.data.NamedProblems); + + namer.UpdateArea(builder.data.NomsDesPays[pays]); + namer.UpdateTimeStep(builder.data.weekInTheYear * 168 + pdt); + namer.AreaHydroLevel(builder.data.nombreDeContraintes); + data.NumeroDeContrainteDesNiveauxPays[pays] = builder.data.nombreDeContraintes; + builder.updateHourWithinWeek(pdt) + .include(Variable::HydProd(pays), 1.0) + .include(Variable::Pumping(pays), -data.PumpingRatio) + .include(Variable::Overflow(pays), 1.) + .equalTo() + .build(); + } + else + data.NumeroDeContrainteDesNiveauxPays[pays] = -1; +} \ No newline at end of file diff --git a/src/solver/optimisation/AreaHydroLevel.h b/src/solver/optimisation/AreaHydroLevel.h new file mode 100644 index 0000000000..928c834548 --- /dev/null +++ b/src/solver/optimisation/AreaHydroLevel.h @@ -0,0 +1,16 @@ +#pragma once +#include "constraint_builder.h" + +struct AreaHydroLevelData +{ + std::vector& NumeroDeContrainteDesNiveauxPays; + const bool& SuiviNiveauHoraire; + const double& PumpingRatio; +}; + +class AreaHydroLevel : private Constraint +{ + public: + using Constraint::Constraint; + void add(int pays, int pdt, AreaHydroLevelData& data); +}; \ No newline at end of file diff --git a/src/solver/optimisation/BindingConstraintDay.cpp b/src/solver/optimisation/BindingConstraintDay.cpp new file mode 100644 index 0000000000..e48b49742f --- /dev/null +++ b/src/solver/optimisation/BindingConstraintDay.cpp @@ -0,0 +1,88 @@ +#include "BindingConstraintDay.h" + +void BindingConstraintDay::add(int cntCouplante, BindingConstraintDayData& data) +{ + if (data.TypeDeContrainteCouplante != CONTRAINTE_JOURNALIERE) + return; + + const int nbInterco = data.NombreDInterconnexionsDansLaContrainteCouplante; + const int nbClusters = data.NombreDePaliersDispatchDansLaContrainteCouplante; + + const int NombreDePasDeTempsPourUneOptimisation + = builder.data.NombreDePasDeTempsPourUneOptimisation; // TODO + const int NombreDePasDeTempsDUneJournee = data.NombreDePasDeTempsDUneJournee; + int pdtDebut = 0; + while (pdtDebut < NombreDePasDeTempsPourUneOptimisation) + { + int jour = data.NumeroDeJourDuPasDeTemps[pdtDebut]; + + for (int index = 0; index < nbInterco; index++) + { + int interco = data.NumeroDeLInterconnexion[index]; + double poids = data.PoidsDeLInterconnexion[index]; + int offset = data.OffsetTemporelSurLInterco[index]; + + for (int pdt = pdtDebut; pdt < pdtDebut + NombreDePasDeTempsDUneJournee; pdt++) + { + int pdt1; + if (offset >= 0) + { + pdt1 = (pdt + offset) % builder.data.NombreDePasDeTempsPourUneOptimisation; + } + else + { + pdt1 = (pdt + offset + builder.data.NombreDePasDeTemps) + % builder.data.NombreDePasDeTempsPourUneOptimisation; + } + builder.updateHourWithinWeek(pdt1).include( + Variable::NTCDirect(interco), poids, 0, false, builder.data.NombreDePasDeTemps); + } + } + + for (int index = 0; index < nbClusters; index++) + { + int pays = data.PaysDuPalierDispatch[index]; + const PALIERS_THERMIQUES& PaliersThermiquesDuPays = data.PaliersThermiquesDuPays[pays]; + const int palier + = PaliersThermiquesDuPays.NumeroDuPalierDansLEnsembleDesPaliersThermiques + [data.NumeroDuPalierDispatch[index]]; + double poids = data.PoidsDuPalierDispatch[index]; + int offset = data.OffsetTemporelSurLePalierDispatch[index]; + + for (int pdt = pdtDebut; pdt < pdtDebut + NombreDePasDeTempsDUneJournee; pdt++) + { + int pdt1; + if (offset >= 0) + { + pdt1 = (pdt + offset) % builder.data.NombreDePasDeTempsPourUneOptimisation; + } + else + { + pdt1 = (pdt + offset + builder.data.NombreDePasDeTemps) + % builder.data.NombreDePasDeTempsPourUneOptimisation; + } + + builder.updateHourWithinWeek(pdt1).include(Variable::DispatchableProduction(palier), + poids, + 0, + false, + builder.data.NombreDePasDeTemps); + } + } + + data.CorrespondanceCntNativesCntOptimJournalieres[jour] + .NumeroDeContrainteDesContraintesCouplantes[cntCouplante] + = builder.data.nombreDeContraintes; + + char op = data.SensDeLaContrainteCouplante; + builder.operatorRHS(op); + { + ConstraintNamer namer(builder.data.NomDesContraintes, builder.data.NamedProblems); + namer.UpdateTimeStep(jour); + namer.BindingConstraintDay(builder.data.nombreDeContraintes, + data.NomDeLaContrainteCouplante); + } + builder.build(); + pdtDebut += data.NombreDePasDeTempsDUneJournee; + } +} diff --git a/src/solver/optimisation/BindingConstraintDay.h b/src/solver/optimisation/BindingConstraintDay.h new file mode 100644 index 0000000000..0f410aebc7 --- /dev/null +++ b/src/solver/optimisation/BindingConstraintDay.h @@ -0,0 +1,63 @@ +#pragma once +#include "constraint_builder.h" + +struct BindingConstraintDayData : public BindingConstraintData +{ + BindingConstraintDayData(BindingConstraintDayData& data) : + BindingConstraintData(data), + CorrespondanceCntNativesCntOptimJournalieres( + data.CorrespondanceCntNativesCntOptimJournalieres), + NombreDePasDeTempsDUneJournee(data.NombreDePasDeTempsDUneJournee), + NumeroDeJourDuPasDeTemps(data.NumeroDeJourDuPasDeTemps) + { + } + BindingConstraintDayData(const char& TypeDeContrainteCouplante, + const int& NombreDInterconnexionsDansLaContrainteCouplante, + const std::vector& NumeroDeLInterconnexion, + const std::vector& PoidsDeLInterconnexion, + const std::vector& OffsetTemporelSurLInterco, + const int& NombreDePaliersDispatchDansLaContrainteCouplante, + const std::vector& PaysDuPalierDispatch, + const std::vector& NumeroDuPalierDispatch, + const std::vector& PoidsDuPalierDispatch, + const std::vector& OffsetTemporelSurLePalierDispatch, + const char& SensDeLaContrainteCouplante, + const char* const& NomDeLaContrainteCouplante, + const std::vector& PaliersThermiquesDuPays, + std::vector& + CorrespondanceCntNativesCntOptimJournalieres, + const int32_t& NombreDePasDeTempsDUneJournee, + std::vector& NumeroDeJourDuPasDeTemps) : + BindingConstraintData(TypeDeContrainteCouplante, + NombreDInterconnexionsDansLaContrainteCouplante, + NumeroDeLInterconnexion, + PoidsDeLInterconnexion, + OffsetTemporelSurLInterco, + NombreDePaliersDispatchDansLaContrainteCouplante, + PaysDuPalierDispatch, + NumeroDuPalierDispatch, + PoidsDuPalierDispatch, + OffsetTemporelSurLePalierDispatch, + SensDeLaContrainteCouplante, + NomDeLaContrainteCouplante, + PaliersThermiquesDuPays), + CorrespondanceCntNativesCntOptimJournalieres(CorrespondanceCntNativesCntOptimJournalieres), + NombreDePasDeTempsDUneJournee(NombreDePasDeTempsDUneJournee), + NumeroDeJourDuPasDeTemps(NumeroDeJourDuPasDeTemps) + { + } + + // std::vector&>& CorrespondanceCntNativesCntOptimJournalieres; + std::vector& + CorrespondanceCntNativesCntOptimJournalieres; + + const int32_t& NombreDePasDeTempsDUneJournee; + + std::vector& NumeroDeJourDuPasDeTemps; +}; +class BindingConstraintDay : private Constraint +{ +public: + using Constraint::Constraint; + void add(int cntCouplante, BindingConstraintDayData& data); +}; diff --git a/src/solver/optimisation/BindingConstraintHour.cpp b/src/solver/optimisation/BindingConstraintHour.cpp new file mode 100644 index 0000000000..65e4f61fc5 --- /dev/null +++ b/src/solver/optimisation/BindingConstraintHour.cpp @@ -0,0 +1,73 @@ +#include "BindingConstraintHour.h" + +void BindingConstraintHour::add(int pdt, int cntCouplante, BindingConstraintHourData& data) +{ + data.NumeroDeContrainteDesContraintesCouplantes[cntCouplante] + = builder.data.nombreDeContraintes; + + if (data.TypeDeContrainteCouplante != CONTRAINTE_HORAIRE) + return; + + builder.updateHourWithinWeek(pdt); + // Links + const int nbInterco = data.NombreDInterconnexionsDansLaContrainteCouplante; + for (int index = 0; index < nbInterco; index++) + { + const int interco = data.NumeroDeLInterconnexion[index]; + const double poids = data.PoidsDeLInterconnexion[index]; + const int offset = data.OffsetTemporelSurLInterco[index]; + int pdt1; + if (offset >= 0) + { + pdt1 = (pdt + offset) % builder.data.NombreDePasDeTempsPourUneOptimisation; + } + else + { + pdt1 = (pdt + offset + builder.data.NombreDePasDeTemps) + % builder.data.NombreDePasDeTempsPourUneOptimisation; + } + + builder.updateHourWithinWeek(pdt1).include( + Variable::NTCDirect(interco), poids, 0, false, builder.data.NombreDePasDeTemps); + } + + // Thermal clusters + const int nbClusters = data.NombreDePaliersDispatchDansLaContrainteCouplante; + for (int index = 0; index < nbClusters; index++) + { + const int pays = data.PaysDuPalierDispatch[index]; + const PALIERS_THERMIQUES& PaliersThermiquesDuPays = data.PaliersThermiquesDuPays[pays]; + const int palier + = PaliersThermiquesDuPays + .NumeroDuPalierDansLEnsembleDesPaliersThermiques[data.NumeroDuPalierDispatch[index]]; + const double poids = data.PoidsDuPalierDispatch[index]; + const int offset = data.OffsetTemporelSurLePalierDispatch[index]; + int pdt1; + + if (offset >= 0) + { + pdt1 = (pdt + offset) % builder.data.NombreDePasDeTempsPourUneOptimisation; + } + else + { + pdt1 = (pdt + offset + builder.data.NombreDePasDeTemps) + % builder.data.NombreDePasDeTempsPourUneOptimisation; + } + + builder.updateHourWithinWeek(pdt1).include(Variable::DispatchableProduction(palier), + poids, + 0, + false, + builder.data.NombreDePasDeTemps); + } + + char op = data.SensDeLaContrainteCouplante; + builder.operatorRHS(op); + { + ConstraintNamer namer(builder.data.NomDesContraintes, builder.data.NamedProblems); + namer.UpdateTimeStep(builder.data.weekInTheYear * 168 + pdt); + namer.BindingConstraintHour(builder.data.nombreDeContraintes, + data.NomDeLaContrainteCouplante); + } + builder.build(); +} diff --git a/src/solver/optimisation/BindingConstraintHour.h b/src/solver/optimisation/BindingConstraintHour.h new file mode 100644 index 0000000000..b08f2b9db5 --- /dev/null +++ b/src/solver/optimisation/BindingConstraintHour.h @@ -0,0 +1,50 @@ +#pragma once +#include "constraint_builder.h" + +struct BindingConstraintHourData : public BindingConstraintData +{ + BindingConstraintHourData(BindingConstraintHourData& data) : + BindingConstraintData(data), + NumeroDeContrainteDesContraintesCouplantes(data.NumeroDeContrainteDesContraintesCouplantes) + { + } + BindingConstraintHourData(const char& TypeDeContrainteCouplante, + const int& NombreDInterconnexionsDansLaContrainteCouplante, + const std::vector& NumeroDeLInterconnexion, + const std::vector& PoidsDeLInterconnexion, + const std::vector& OffsetTemporelSurLInterco, + const int& NombreDePaliersDispatchDansLaContrainteCouplante, + const std::vector& PaysDuPalierDispatch, + const std::vector& NumeroDuPalierDispatch, + const std::vector& PoidsDuPalierDispatch, + const std::vector& OffsetTemporelSurLePalierDispatch, + const char& SensDeLaContrainteCouplante, + const char* const& NomDeLaContrainteCouplante, + const std::vector& PaliersThermiquesDuPays, + std::vector& NumeroDeContrainteDesContraintesCouplantes) : + BindingConstraintData(TypeDeContrainteCouplante, + NombreDInterconnexionsDansLaContrainteCouplante, + NumeroDeLInterconnexion, + PoidsDeLInterconnexion, + OffsetTemporelSurLInterco, + NombreDePaliersDispatchDansLaContrainteCouplante, + PaysDuPalierDispatch, + NumeroDuPalierDispatch, + PoidsDuPalierDispatch, + OffsetTemporelSurLePalierDispatch, + SensDeLaContrainteCouplante, + NomDeLaContrainteCouplante, + PaliersThermiquesDuPays), + NumeroDeContrainteDesContraintesCouplantes(NumeroDeContrainteDesContraintesCouplantes) + { + } + + std::vector& NumeroDeContrainteDesContraintesCouplantes; +}; + +class BindingConstraintHour : private Constraint +{ + public: + using Constraint::Constraint; + void add(int pdt, int cntCouplante, BindingConstraintHourData& data); +}; diff --git a/src/solver/optimisation/BindingConstraintWeek.cpp b/src/solver/optimisation/BindingConstraintWeek.cpp new file mode 100644 index 0000000000..8c103617ff --- /dev/null +++ b/src/solver/optimisation/BindingConstraintWeek.cpp @@ -0,0 +1,80 @@ +#include "BindingConstraintWeek.h" + +void BindingConstraintWeek::add(int cntCouplante, BindingConstraintWeekData& data) +{ + int semaine = builder.data.weekInTheYear; + if (data.TypeDeContrainteCouplante != CONTRAINTE_HEBDOMADAIRE) + return; + + const int nbInterco = data.NombreDInterconnexionsDansLaContrainteCouplante; + const int nbClusters = data.NombreDePaliersDispatchDansLaContrainteCouplante; + + for (int index = 0; index < nbInterco; index++) + { + int interco = data.NumeroDeLInterconnexion[index]; + double poids = data.PoidsDeLInterconnexion[index]; + int offset = data.OffsetTemporelSurLInterco[index]; + for (int pdt = 0; pdt < builder.data.NombreDePasDeTempsPourUneOptimisation; pdt++) + { + builder.updateHourWithinWeek(pdt); + int pdt1; + if (offset >= 0) + { + pdt1 = (pdt + offset) % builder.data.NombreDePasDeTempsPourUneOptimisation; + } + else + { + pdt1 = (pdt + offset + builder.data.NombreDePasDeTemps) + % builder.data.NombreDePasDeTempsPourUneOptimisation; + } + builder.updateHourWithinWeek(pdt1).include( + Variable::NTCDirect(interco), poids, 0, false, builder.data.NombreDePasDeTemps); + } + } + + for (int index = 0; index < nbClusters; index++) + { + int pays = data.PaysDuPalierDispatch[index]; + const PALIERS_THERMIQUES& PaliersThermiquesDuPays = data.PaliersThermiquesDuPays[pays]; + const int palier + = PaliersThermiquesDuPays + .NumeroDuPalierDansLEnsembleDesPaliersThermiques[data.NumeroDuPalierDispatch[index]]; + double poids = data.PoidsDuPalierDispatch[index]; + int offset = data.OffsetTemporelSurLePalierDispatch[index]; + for (int pdt = 0; pdt < builder.data.NombreDePasDeTempsPourUneOptimisation; pdt++) + { + int pdt1; + + builder.updateHourWithinWeek(pdt); // useless? + if (offset >= 0) + { + pdt1 = (pdt + offset) % builder.data.NombreDePasDeTempsPourUneOptimisation; + } + else + { + pdt1 = (pdt + offset + builder.data.NombreDePasDeTemps) + % builder.data.NombreDePasDeTempsPourUneOptimisation; + } + + builder.updateHourWithinWeek(pdt1).include(Variable::DispatchableProduction(palier), + poids, + offset, + false, + builder.data.NombreDePasDeTemps); + } + } + + char op = data.SensDeLaContrainteCouplante; + builder.operatorRHS(op); + + data.NumeroDeContrainteDesContraintesCouplantes[cntCouplante] + = builder.data.nombreDeContraintes; + // Name + { + ConstraintNamer namer(builder.data.NomDesContraintes, builder.data.NamedProblems); + namer.UpdateTimeStep(semaine); + namer.BindingConstraintWeek(builder.data.nombreDeContraintes, + data.NomDeLaContrainteCouplante); + } + builder.build(); +} \ No newline at end of file diff --git a/src/solver/optimisation/BindingConstraintWeek.h b/src/solver/optimisation/BindingConstraintWeek.h new file mode 100644 index 0000000000..8648537456 --- /dev/null +++ b/src/solver/optimisation/BindingConstraintWeek.h @@ -0,0 +1,52 @@ +#pragma once +#include "constraint_builder.h" + +struct BindingConstraintWeekData : public BindingConstraintData +{ + BindingConstraintWeekData(BindingConstraintWeekData& data) : + BindingConstraintData(data), + NumeroDeContrainteDesContraintesCouplantes(data.NumeroDeContrainteDesContraintesCouplantes) + { + } + + BindingConstraintWeekData(const char& TypeDeContrainteCouplante, + const int& NombreDInterconnexionsDansLaContrainteCouplante, + const std::vector& NumeroDeLInterconnexion, + const std::vector& PoidsDeLInterconnexion, + const std::vector& OffsetTemporelSurLInterco, + const int& NombreDePaliersDispatchDansLaContrainteCouplante, + const std::vector& PaysDuPalierDispatch, + const std::vector& NumeroDuPalierDispatch, + const std::vector& PoidsDuPalierDispatch, + const std::vector& OffsetTemporelSurLePalierDispatch, + const char& SensDeLaContrainteCouplante, + const char* const& NomDeLaContrainteCouplante, + const std::vector& PaliersThermiquesDuPays, + std::vector& NumeroDeContrainteDesContraintesCouplantes) : + BindingConstraintData(TypeDeContrainteCouplante, + NombreDInterconnexionsDansLaContrainteCouplante, + NumeroDeLInterconnexion, + PoidsDeLInterconnexion, + OffsetTemporelSurLInterco, + NombreDePaliersDispatchDansLaContrainteCouplante, + PaysDuPalierDispatch, + NumeroDuPalierDispatch, + PoidsDuPalierDispatch, + OffsetTemporelSurLePalierDispatch, + SensDeLaContrainteCouplante, + NomDeLaContrainteCouplante, + PaliersThermiquesDuPays), + NumeroDeContrainteDesContraintesCouplantes(NumeroDeContrainteDesContraintesCouplantes) + { + } + // std::vector&>& CorrespondanceCntNativesCntOptimJournalieres; + std::vector& NumeroDeContrainteDesContraintesCouplantes; + // CORRESPONDANCES_DES_CONTRAINTES_HEBDOMADAIRES& CorrespondanceCntNativesCntOptimHebdomadaires; +}; + +class BindingConstraintWeek : private Constraint +{ +public: + using Constraint::Constraint; + void add(int cntCouplante, BindingConstraintWeekData& data); +}; \ No newline at end of file diff --git a/src/solver/optimisation/CMakeLists.txt b/src/solver/optimisation/CMakeLists.txt index 05f5e5a352..bcdde70e40 100644 --- a/src/solver/optimisation/CMakeLists.txt +++ b/src/solver/optimisation/CMakeLists.txt @@ -70,6 +70,60 @@ set(RTESOLVER_OPT opt_period_string_generator_base.h opt_rename_problem.h opt_rename_problem.cpp + + constraint_builder.cpp + constraint_builder.h + constraint_builder_utils.h + constraint_builder_utils.cpp + + AreaBalance.h + AreaBalance.cpp + FictitiousLoad.h + FictitiousLoad.cpp + ShortTermStorageLevel.h + ShortTermStorageLevel.cpp + FlowDissociation.h + FlowDissociation.cpp + BindingConstraintHour.h + BindingConstraintHour.cpp + BindingConstraintDay.h + BindingConstraintDay.cpp + BindingConstraintWeek.h + BindingConstraintWeek.cpp + HydroPower.h + HydroPower.cpp + HydroPowerSmoothingUsingVariationSum.h + HydroPowerSmoothingUsingVariationSum.cpp + HydroPowerSmoothingUsingVariationMaxDown.h + HydroPowerSmoothingUsingVariationMaxDown.cpp + HydroPowerSmoothingUsingVariationMaxUp.h + HydroPowerSmoothingUsingVariationMaxUp.cpp + MinHydroPower.h + MinHydroPower.cpp + MaxHydroPower.h + MaxHydroPower.cpp + MaxPumping.h + MaxPumping.cpp + AreaHydroLevel.h + AreaHydroLevel.cpp + FinalStockEquivalent.h + FinalStockEquivalent.cpp + FinalStockExpression.h + FinalStockExpression.cpp + + PMaxDispatchableGeneration.h + PMaxDispatchableGeneration.cpp + PMinDispatchableGeneration.h + PMinDispatchableGeneration.cpp + ConsistenceNODU.h + ConsistenceNODU.cpp + NbUnitsOutageLessThanNbUnitsStop.h + NbUnitsOutageLessThanNbUnitsStop.cpp + NbDispUnitsMinBoundSinceMinUpTime.h + NbDispUnitsMinBoundSinceMinUpTime.cpp + MinDownTime.h + MinDownTime.cpp + ) diff --git a/src/solver/optimisation/ConsistenceNODU.cpp b/src/solver/optimisation/ConsistenceNODU.cpp new file mode 100644 index 0000000000..300e43584f --- /dev/null +++ b/src/solver/optimisation/ConsistenceNODU.cpp @@ -0,0 +1,47 @@ +#include "ConsistenceNODU.h" + +void ConsistenceNODU::add(int pays, + int cluster, + int clusterIndex, + int pdt, + bool Simulation, + StartUpCostsData& data) +{ + if (!Simulation) + { + const PALIERS_THERMIQUES& PaliersThermiquesDuPays = data.PaliersThermiquesDuPays[pays]; + + int NombreDePasDeTempsPourUneOptimisation + = builder.data.NombreDePasDeTempsPourUneOptimisation; + + int Pdtmoins1 = pdt - 1; + if (Pdtmoins1 < 0) + Pdtmoins1 = NombreDePasDeTempsPourUneOptimisation + Pdtmoins1; + + builder.updateHourWithinWeek(pdt) + .include(Variable::NODU(cluster), 1.0) + .updateHourWithinWeek(Pdtmoins1) + .include(Variable::NODU(cluster), -1) + .updateHourWithinWeek(pdt) + .include(Variable::NumberStartingDispatchableUnits(cluster), -1) + .include(Variable::NumberStoppingDispatchableUnits(cluster), 1) + .equalTo(); + + if (builder.NumberOfVariables() > 0) + { + ConstraintNamer namer(builder.data.NomDesContraintes, builder.data.NamedProblems); + namer.UpdateArea(builder.data.NomsDesPays[pays]); + + namer.UpdateTimeStep(builder.data.weekInTheYear * 168 + pdt); + namer.ConsistenceNODU(builder.data.nombreDeContraintes, + PaliersThermiquesDuPays.NomsDesPaliersThermiques[clusterIndex]); + + builder.build(); + } + } + else + { + nbTermesContraintesPourLesCoutsDeDemarrage += 4; + builder.data.nombreDeContraintes++; + } +} diff --git a/src/solver/optimisation/ConsistenceNODU.h b/src/solver/optimisation/ConsistenceNODU.h new file mode 100644 index 0000000000..6d97cd4c92 --- /dev/null +++ b/src/solver/optimisation/ConsistenceNODU.h @@ -0,0 +1,15 @@ +#pragma once +#include "constraint_builder.h" + +class ConsistenceNODU : private Constraint +{ +public: + using Constraint::Constraint; + void add(int pays, + int cluster, + int clusterIndex, + int pdt, + bool Simulation, + StartUpCostsData& data); + int nbTermesContraintesPourLesCoutsDeDemarrage = 0; +}; \ No newline at end of file diff --git a/src/solver/optimisation/FictitiousLoad.cpp b/src/solver/optimisation/FictitiousLoad.cpp new file mode 100644 index 0000000000..01a2647804 --- /dev/null +++ b/src/solver/optimisation/FictitiousLoad.cpp @@ -0,0 +1,28 @@ + +#include "FictitiousLoad.h" + +void FictitiousLoad::add(int pdt, int pays, FictitiousLoadData& data) +{ + /** can be done without this --- keep it for now**/ + data.NumeroDeContraintePourEviterLesChargesFictives[pays] = builder.data.nombreDeContraintes; + + /******/ + + // TODO improve this + { + ConstraintNamer namer(builder.data.NomDesContraintes, builder.data.NamedProblems); + + namer.UpdateTimeStep(builder.data.weekInTheYear * 168 + pdt); + namer.UpdateArea(builder.data.NomsDesPays[pays]); + namer.FictiveLoads(builder.data.nombreDeContraintes); + } + + builder.updateHourWithinWeek(pdt); + exportPaliers(data.PaliersThermiquesDuPays, builder); + auto coeff = data.DefaillanceNegativeUtiliserHydro[pays] ? -1 : 0; + builder.include(Variable::HydProd(pays), coeff) + .include(Variable::NegativeUnsuppliedEnergy(pays), 1.0); + + builder.lessThan(); + builder.build(); +} diff --git a/src/solver/optimisation/FictitiousLoad.h b/src/solver/optimisation/FictitiousLoad.h new file mode 100644 index 0000000000..a62812cecd --- /dev/null +++ b/src/solver/optimisation/FictitiousLoad.h @@ -0,0 +1,15 @@ + +#pragma once +#include "constraint_builder.h" +struct FictitiousLoadData +{ + std::vector& NumeroDeContraintePourEviterLesChargesFictives; + const PALIERS_THERMIQUES& PaliersThermiquesDuPays; + const std::vector& DefaillanceNegativeUtiliserHydro; +}; +class FictitiousLoad : private Constraint +{ +public: + using Constraint::Constraint; + void add(int pdt, int pays, FictitiousLoadData& data); +}; diff --git a/src/solver/optimisation/FinalStockEquivalent.cpp b/src/solver/optimisation/FinalStockEquivalent.cpp new file mode 100644 index 0000000000..28fef46c81 --- /dev/null +++ b/src/solver/optimisation/FinalStockEquivalent.cpp @@ -0,0 +1,23 @@ +#include "FinalStockEquivalent.h" + +void FinalStockEquivalent::add(int pays, FinalStockEquivalentData& data) +{ + const auto pdt = data.pdt; + if (data.AccurateWaterValue && data.DirectLevelAccess) + { /* equivalence constraint : StockFinal- Niveau[T]= 0*/ + + data.NumeroDeContrainteEquivalenceStockFinal[pays] = builder.data.nombreDeContraintes; + ConstraintNamer namer(builder.data.NomDesContraintes, builder.data.NamedProblems); + + namer.UpdateArea(builder.data.NomsDesPays[pays]); + namer.UpdateTimeStep(builder.data.weekInTheYear * 168 + pdt); + namer.FinalStockEquivalent(builder.data.nombreDeContraintes); + + builder.updateHourWithinWeek(pdt) + .include(Variable::FinalStorage(pays), 1.0) + .updateHourWithinWeek(builder.data.NombreDePasDeTempsPourUneOptimisation - 1) + .include(Variable::HydroLevel(pays), -1.0) + .equalTo() + .build(); + } +} diff --git a/src/solver/optimisation/FinalStockEquivalent.h b/src/solver/optimisation/FinalStockEquivalent.h new file mode 100644 index 0000000000..810d6ffe45 --- /dev/null +++ b/src/solver/optimisation/FinalStockEquivalent.h @@ -0,0 +1,17 @@ +#pragma once +#include "constraint_builder.h" + +struct FinalStockEquivalentData +{ + const int& pdt; + const bool& AccurateWaterValue; + const bool& DirectLevelAccess; + std::vector& NumeroDeContrainteEquivalenceStockFinal; +}; + +class FinalStockEquivalent : private Constraint +{ + public: + using Constraint::Constraint; + void add(int pays, FinalStockEquivalentData& data); +}; diff --git a/src/solver/optimisation/FinalStockExpression.cpp b/src/solver/optimisation/FinalStockExpression.cpp new file mode 100644 index 0000000000..18bba99030 --- /dev/null +++ b/src/solver/optimisation/FinalStockExpression.cpp @@ -0,0 +1,24 @@ +#include "FinalStockExpression.h" + +void FinalStockExpression::add(int pays, FinalStockExpressionData& data) +{ + const auto pdt = data.pdt; + + if (data.AccurateWaterValue) + /* expression constraint : - StockFinal +sum (stocklayers) = 0*/ + { + builder.updateHourWithinWeek(pdt).include(Variable::FinalStorage(pays), -1.0); + for (int layerindex = 0; layerindex < 100; layerindex++) + { + builder.include(Variable::LayerStorage(pays, layerindex), 1.0); + } + data.NumeroDeContrainteExpressionStockFinal[pays] = builder.data.nombreDeContraintes; + + ConstraintNamer namer(builder.data.NomDesContraintes, builder.data.NamedProblems); + + namer.UpdateArea(builder.data.NomsDesPays[pays]); + namer.UpdateTimeStep(builder.data.weekInTheYear * 168 + pdt); + namer.FinalStockExpression(builder.data.nombreDeContraintes); + builder.equalTo().build(); + } +} diff --git a/src/solver/optimisation/FinalStockExpression.h b/src/solver/optimisation/FinalStockExpression.h new file mode 100644 index 0000000000..5be07115c7 --- /dev/null +++ b/src/solver/optimisation/FinalStockExpression.h @@ -0,0 +1,16 @@ +#pragma once + +#include "constraint_builder.h" + +struct FinalStockExpressionData +{ + const int& pdt; + const bool& AccurateWaterValue; + std::vector& NumeroDeContrainteExpressionStockFinal; +}; +class FinalStockExpression : private Constraint +{ +public: + using Constraint::Constraint; + void add(int pays, FinalStockExpressionData& data); +}; diff --git a/src/solver/optimisation/FlowDissociation.cpp b/src/solver/optimisation/FlowDissociation.cpp new file mode 100644 index 0000000000..99ce6892ef --- /dev/null +++ b/src/solver/optimisation/FlowDissociation.cpp @@ -0,0 +1,29 @@ +#include "FlowDissociation.h" + +void FlowDissociation::add(int pdt, int interco, FlowDissociationData& data) +{ + if (const COUTS_DE_TRANSPORT& CoutDeTransport = data.CoutDeTransport[interco]; + CoutDeTransport.IntercoGereeAvecDesCouts) + { + // TODO improve this + data.NumeroDeContrainteDeDissociationDeFlux[interco] = builder.data.nombreDeContraintes; + { + const auto origin + = builder.data.NomsDesPays[data.PaysOrigineDeLInterconnexion[interco]]; + const auto destination + = builder.data.NomsDesPays[data.PaysExtremiteDeLInterconnexion[interco]]; + ConstraintNamer namer(builder.data.NomDesContraintes, builder.data.NamedProblems); + namer.UpdateTimeStep(builder.data.weekInTheYear * 168 + pdt); + namer.FlowDissociation(builder.data.nombreDeContraintes, origin, destination); + } + + builder.updateHourWithinWeek(pdt); + builder.include(Variable::NTCDirect(interco), 1.0) + .include(Variable::IntercoDirectCost(interco), -1.0) + .include(Variable::IntercoIndirectCost(interco), 1.0); + + builder.equalTo(); + + builder.build(); + } +} diff --git a/src/solver/optimisation/FlowDissociation.h b/src/solver/optimisation/FlowDissociation.h new file mode 100644 index 0000000000..d8cb1ad806 --- /dev/null +++ b/src/solver/optimisation/FlowDissociation.h @@ -0,0 +1,17 @@ +#pragma once +#include "constraint_builder.h" + +struct FlowDissociationData +{ + std::vector& NumeroDeContrainteDeDissociationDeFlux; + const std::vector& CoutDeTransport; + const std::vector& PaysOrigineDeLInterconnexion; + const std::vector& PaysExtremiteDeLInterconnexion; +}; + +class FlowDissociation : private Constraint +{ +public: + using Constraint::Constraint; + void add(int pdt, int interco, FlowDissociationData& data); +}; diff --git a/src/solver/optimisation/HydroPower.cpp b/src/solver/optimisation/HydroPower.cpp new file mode 100644 index 0000000000..e829263d2c --- /dev/null +++ b/src/solver/optimisation/HydroPower.cpp @@ -0,0 +1,45 @@ +#include "HydroPower.h" + +void HydroPower::add(int pays, HydroPowerData& data) +{ + bool presenceHydro = data.presenceHydro; + bool TurbEntreBornes = data.TurbEntreBornes; + + const int NombreDePasDeTempsPourUneOptimisation + = builder.data.NombreDePasDeTempsPourUneOptimisation; + if (presenceHydro && !TurbEntreBornes) + { + if (data.presencePompage) + { + data.NumeroDeContrainteEnergieHydraulique[pays] = builder.data.nombreDeContraintes; + + const double pumpingRatio = data.pumpingRatio; + for (int pdt = 0; pdt < NombreDePasDeTempsPourUneOptimisation; pdt++) + { + builder.updateHourWithinWeek(pdt); + builder.include(Variable::HydProd(pays), 1.0) + .include(Variable::Pumping(pays), -pumpingRatio); + } + } + else + { + for (int pdt = 0; pdt < NombreDePasDeTempsPourUneOptimisation; pdt++) + { + builder.updateHourWithinWeek(pdt); + builder.include(Variable::HydProd(pays), 1.0); + } + } + data.NumeroDeContrainteEnergieHydraulique[pays] = builder.data.nombreDeContraintes; + + builder.equalTo(); + { + ConstraintNamer namer(builder.data.NomDesContraintes, builder.data.NamedProblems); + namer.UpdateArea(builder.data.NomsDesPays[pays]); + namer.UpdateTimeStep(builder.data.weekInTheYear); + namer.HydroPower(builder.data.nombreDeContraintes); + } + builder.build(); + } + else + data.NumeroDeContrainteEnergieHydraulique[pays] = -1; +} diff --git a/src/solver/optimisation/HydroPower.h b/src/solver/optimisation/HydroPower.h new file mode 100644 index 0000000000..05caf5bbe4 --- /dev/null +++ b/src/solver/optimisation/HydroPower.h @@ -0,0 +1,18 @@ +#pragma once +#include "constraint_builder.h" +struct HydroPowerData +{ + const bool& presenceHydro; + const int& TurbEntreBornes; + const bool& presencePompage; + const int& NombreDePasDeTempsPourUneOptimisation; + std::vector& NumeroDeContrainteEnergieHydraulique; + const double& pumpingRatio; +}; + +class HydroPower : private Constraint +{ +public: + using Constraint::Constraint; + void add(int pays, HydroPowerData& data); +}; diff --git a/src/solver/optimisation/HydroPowerSmoothingUsingVariationMaxDown.cpp b/src/solver/optimisation/HydroPowerSmoothingUsingVariationMaxDown.cpp new file mode 100644 index 0000000000..faee7e34f4 --- /dev/null +++ b/src/solver/optimisation/HydroPowerSmoothingUsingVariationMaxDown.cpp @@ -0,0 +1,21 @@ +#include "HydroPowerSmoothingUsingVariationMaxDown.h" + +void HydroPowerSmoothingUsingVariationMaxDown::add(int pays, int pdt) +{ + // if (!problemeHebdo->CaracteristiquesHydrauliques[pays].PresenceDHydrauliqueModulable) + // { + // return; + // } + + ConstraintNamer namer(builder.data.NomDesContraintes, builder.data.NamedProblems); + namer.UpdateArea(builder.data.NomsDesPays[pays]); + namer.UpdateTimeStep(builder.data.weekInTheYear * 168 + pdt); + namer.HydroPowerSmoothingUsingVariationMaxDown(builder.data.nombreDeContraintes); + + builder.updateHourWithinWeek(pdt) + .include(Variable::HydProd(pays), 1.0) + .updateHourWithinWeek(0) + .include(Variable::HydProdDown(pays), -1.0) + .lessThan() + .build(); +} \ No newline at end of file diff --git a/src/solver/optimisation/HydroPowerSmoothingUsingVariationMaxDown.h b/src/solver/optimisation/HydroPowerSmoothingUsingVariationMaxDown.h new file mode 100644 index 0000000000..4810a40009 --- /dev/null +++ b/src/solver/optimisation/HydroPowerSmoothingUsingVariationMaxDown.h @@ -0,0 +1,9 @@ +#pragma once +#include "constraint_builder.h" + +class HydroPowerSmoothingUsingVariationMaxDown : private Constraint +{ +public: + using Constraint::Constraint; + void add(int pays, int pdt); +}; \ No newline at end of file diff --git a/src/solver/optimisation/HydroPowerSmoothingUsingVariationMaxUp.cpp b/src/solver/optimisation/HydroPowerSmoothingUsingVariationMaxUp.cpp new file mode 100644 index 0000000000..df3e6e3520 --- /dev/null +++ b/src/solver/optimisation/HydroPowerSmoothingUsingVariationMaxUp.cpp @@ -0,0 +1,21 @@ +#include "HydroPowerSmoothingUsingVariationMaxUp.h" + +void HydroPowerSmoothingUsingVariationMaxUp::add(int pays, int pdt) +{ + // if (!problemeHebdo->CaracteristiquesHydrauliques[pays].PresenceDHydrauliqueModulable) + // { + // return; + // } + + ConstraintNamer namer(builder.data.NomDesContraintes, builder.data.NamedProblems); + namer.UpdateArea(builder.data.NomsDesPays[pays]); + namer.UpdateTimeStep(builder.data.weekInTheYear * 168 + pdt); + namer.HydroPowerSmoothingUsingVariationMaxUp(builder.data.nombreDeContraintes); + + builder.updateHourWithinWeek(pdt) + .include(Variable::HydProd(pays), 1.0) + .updateHourWithinWeek(0) + .include(Variable::HydProdUp(pays), -1.0) + .greaterThan() + .build(); +} \ No newline at end of file diff --git a/src/solver/optimisation/HydroPowerSmoothingUsingVariationMaxUp.h b/src/solver/optimisation/HydroPowerSmoothingUsingVariationMaxUp.h new file mode 100644 index 0000000000..2a47f1cfd6 --- /dev/null +++ b/src/solver/optimisation/HydroPowerSmoothingUsingVariationMaxUp.h @@ -0,0 +1,9 @@ +#pragma once +#include "constraint_builder.h" + +class HydroPowerSmoothingUsingVariationMaxUp : private Constraint +{ +public: + using Constraint::Constraint; + void add(int pays, int pdt); +}; \ No newline at end of file diff --git a/src/solver/optimisation/HydroPowerSmoothingUsingVariationSum.cpp b/src/solver/optimisation/HydroPowerSmoothingUsingVariationSum.cpp new file mode 100644 index 0000000000..827c3d3cbe --- /dev/null +++ b/src/solver/optimisation/HydroPowerSmoothingUsingVariationSum.cpp @@ -0,0 +1,31 @@ +#include "HydroPowerSmoothingUsingVariationSum.h" + +void HydroPowerSmoothingUsingVariationSum::add(int pays, + const int nombreDePasDeTempsPourUneOptimisation) +{ + // if (!problemeHebdo->CaracteristiquesHydrauliques[pays].PresenceDHydrauliqueModulable) + // { + // return; + // } + + for (int pdt = 0; pdt < nombreDePasDeTempsPourUneOptimisation; pdt++) + { + int pdt1 = pdt + 1; + if (pdt1 >= nombreDePasDeTempsPourUneOptimisation) + pdt1 = 0; + ConstraintNamer namer(builder.data.NomDesContraintes, builder.data.NamedProblems); + namer.UpdateArea(builder.data.NomsDesPays[pays]); + namer.UpdateTimeStep(builder.data.weekInTheYear * 168 + pdt); + namer.HydroPowerSmoothingUsingVariationSum(builder.data.nombreDeContraintes); + + builder.updateHourWithinWeek(pdt) + .include(Variable::HydProd(pays), 1.0) + .updateHourWithinWeek(pdt1) /* /!\ Re-check*/ + .include(Variable::HydProd(pays), -1.0) + .updateHourWithinWeek(pdt) /* /!\ Re-check*/ + .include(Variable::HydProdDown(pays), -1.0) + .include(Variable::HydProdUp(pays), 1.0) + .equalTo() + .build(); + } +} \ No newline at end of file diff --git a/src/solver/optimisation/HydroPowerSmoothingUsingVariationSum.h b/src/solver/optimisation/HydroPowerSmoothingUsingVariationSum.h new file mode 100644 index 0000000000..effc7ec05f --- /dev/null +++ b/src/solver/optimisation/HydroPowerSmoothingUsingVariationSum.h @@ -0,0 +1,9 @@ + +#pragma once +#include "constraint_builder.h" +class HydroPowerSmoothingUsingVariationSum : private Constraint +{ +public: + using Constraint::Constraint; + void add(int pays , const int nombreDePasDeTempsPourUneOptimisation); +}; \ No newline at end of file diff --git a/src/solver/optimisation/MaxHydroPower.cpp b/src/solver/optimisation/MaxHydroPower.cpp new file mode 100644 index 0000000000..eea3435038 --- /dev/null +++ b/src/solver/optimisation/MaxHydroPower.cpp @@ -0,0 +1,30 @@ +#include "MaxHydroPower.h" + +void MaxHydroPower::add(int pays, MaxHydroPowerData& data) +{ + bool presenceHydro = data.presenceHydro; + bool TurbEntreBornes = data.TurbEntreBornes; + if (presenceHydro && (TurbEntreBornes || data.PresenceDePompageModulable)) + { + data.NumeroDeContrainteMaxEnergieHydraulique[pays] = builder.data.nombreDeContraintes; + + const int NombreDePasDeTempsPourUneOptimisation + = builder.data.NombreDePasDeTempsPourUneOptimisation; + + for (int pdt = 0; pdt < NombreDePasDeTempsPourUneOptimisation; pdt++) + { + builder.updateHourWithinWeek(pdt); + builder.include(Variable::HydProd(pays), 1.0); + } + data.NumeroDeContrainteMaxEnergieHydraulique[pays] = builder.data.nombreDeContraintes; + + ConstraintNamer namer(builder.data.NomDesContraintes, builder.data.NamedProblems); + namer.UpdateArea(builder.data.NomsDesPays[pays]); + namer.UpdateTimeStep(builder.data.weekInTheYear); + namer.MaxHydroPower(builder.data.nombreDeContraintes); + + builder.lessThan().build(); + } + else + data.NumeroDeContrainteMaxEnergieHydraulique[pays] = -1; +} \ No newline at end of file diff --git a/src/solver/optimisation/MaxHydroPower.h b/src/solver/optimisation/MaxHydroPower.h new file mode 100644 index 0000000000..57def58589 --- /dev/null +++ b/src/solver/optimisation/MaxHydroPower.h @@ -0,0 +1,17 @@ +#pragma once +#include "constraint_builder.h" + +struct MaxHydroPowerData +{ + const bool& presenceHydro; + const bool& TurbEntreBornes; + const bool& PresenceDePompageModulable; + const int& NombreDePasDeTempsPourUneOptimisation; + std::vector& NumeroDeContrainteMaxEnergieHydraulique; +}; +class MaxHydroPower : private Constraint +{ +public: + using Constraint::Constraint; + void add(int pays, MaxHydroPowerData& data); +}; \ No newline at end of file diff --git a/src/solver/optimisation/MaxPumping.cpp b/src/solver/optimisation/MaxPumping.cpp new file mode 100644 index 0000000000..7ee3cbd439 --- /dev/null +++ b/src/solver/optimisation/MaxPumping.cpp @@ -0,0 +1,26 @@ +#include "MaxPumping.h" + +void MaxPumping::add(int pays, MaxPumpingData& data) +{ + if (data.PresenceDePompageModulable) + { + data.NumeroDeContrainteMaxPompage[pays] = builder.data.nombreDeContraintes; + + const int NombreDePasDeTempsPourUneOptimisation + = builder.data.NombreDePasDeTempsPourUneOptimisation; + + for (int pdt = 0; pdt < NombreDePasDeTempsPourUneOptimisation; pdt++) + { + builder.updateHourWithinWeek(pdt); + builder.include(Variable::Pumping(pays), 1.0); + } + data.NumeroDeContrainteMaxPompage[pays] = builder.data.nombreDeContraintes; + ConstraintNamer namer(builder.data.NomDesContraintes, builder.data.NamedProblems); + namer.UpdateArea(builder.data.NomsDesPays[pays]); + namer.UpdateTimeStep(builder.data.weekInTheYear); + namer.MaxPumping(builder.data.nombreDeContraintes); + builder.lessThan().build(); + } + else + data.NumeroDeContrainteMaxPompage[pays] = -1; +} \ No newline at end of file diff --git a/src/solver/optimisation/MaxPumping.h b/src/solver/optimisation/MaxPumping.h new file mode 100644 index 0000000000..a796678e04 --- /dev/null +++ b/src/solver/optimisation/MaxPumping.h @@ -0,0 +1,14 @@ +#pragma once +#include "constraint_builder.h" +struct MaxPumpingData +{ + const bool& PresenceDePompageModulable; + std::vector& NumeroDeContrainteMaxPompage; +}; + +class MaxPumping : private Constraint +{ +public: + using Constraint::Constraint; + void add(int pays, MaxPumpingData& data); +}; \ No newline at end of file diff --git a/src/solver/optimisation/MinDownTime.cpp b/src/solver/optimisation/MinDownTime.cpp new file mode 100644 index 0000000000..f4fef3fdf5 --- /dev/null +++ b/src/solver/optimisation/MinDownTime.cpp @@ -0,0 +1,56 @@ +#include "MinDownTime.h" + +void MinDownTime::add(int pays, + int cluster, + int clusterIndex, + int pdt, + bool Simulation, + MinDownTimeData& data) +{ + const PALIERS_THERMIQUES& PaliersThermiquesDuPays = data.PaliersThermiquesDuPays[pays]; + const int DureeMinimaleDArretDUnGroupeDuPalierThermique + = PaliersThermiquesDuPays.DureeMinimaleDArretDUnGroupeDuPalierThermique[clusterIndex]; + + data.NumeroDeContrainteDesContraintesDeDureeMinDArret[cluster] = -1; + if (!Simulation) + { + int NombreDePasDeTempsPourUneOptimisation + = builder.data.NombreDePasDeTempsPourUneOptimisation; + + const std::vector& NombreMaxDeGroupesEnMarcheDuPalierThermique + = PaliersThermiquesDuPays.PuissanceDisponibleEtCout[clusterIndex] + .NombreMaxDeGroupesEnMarcheDuPalierThermique; + + builder.updateHourWithinWeek(pdt).include(Variable::NODU(cluster), 1.0); + + for (int k = pdt - DureeMinimaleDArretDUnGroupeDuPalierThermique + 1; k <= pdt; k++) + { + int t1 = k; + if (t1 < 0) + t1 = NombreDePasDeTempsPourUneOptimisation + t1; + + builder.updateHourWithinWeek(t1).include( + Variable::NumberStoppingDispatchableUnits(cluster), 1.0); + } + builder.lessThan(); + if (builder.NumberOfVariables() > 1) + { + data.NumeroDeContrainteDesContraintesDeDureeMinDArret[cluster] + = builder.data.nombreDeContraintes; + ConstraintNamer namer(builder.data.NomDesContraintes, builder.data.NamedProblems); + namer.UpdateArea(builder.data.NomsDesPays[pays]); + + namer.UpdateTimeStep(builder.data.weekInTheYear * 168 + pdt); + namer.MinDownTime(builder.data.nombreDeContraintes, + PaliersThermiquesDuPays.NomsDesPaliersThermiques[clusterIndex]); + + builder.build(); + } + } + else + { + nbTermesContraintesPourLesCoutsDeDemarrage + += 1 + DureeMinimaleDArretDUnGroupeDuPalierThermique; + builder.data.nombreDeContraintes++; + } +} diff --git a/src/solver/optimisation/MinDownTime.h b/src/solver/optimisation/MinDownTime.h new file mode 100644 index 0000000000..e6df2ea202 --- /dev/null +++ b/src/solver/optimisation/MinDownTime.h @@ -0,0 +1,19 @@ +#pragma once +#include "constraint_builder.h" +struct MinDownTimeData : public StartUpCostsData +{ + std::vector& NumeroDeContrainteDesContraintesDeDureeMinDArret; +}; + +class MinDownTime : private Constraint +{ +public: + using Constraint::Constraint; + void add(int pays, + int cluster, + int clusterIndex, + int pdt, + bool Simulation, + MinDownTimeData& data); + int nbTermesContraintesPourLesCoutsDeDemarrage = 0; +}; \ No newline at end of file diff --git a/src/solver/optimisation/MinHydroPower.cpp b/src/solver/optimisation/MinHydroPower.cpp new file mode 100644 index 0000000000..f557575426 --- /dev/null +++ b/src/solver/optimisation/MinHydroPower.cpp @@ -0,0 +1,29 @@ +#include "MinHydroPower.h" + +void MinHydroPower::add(int pays, MinHydroPowerData& data) +{ + bool presenceHydro = data.presenceHydro; + bool TurbEntreBornes = data.TurbEntreBornes; + if (presenceHydro && (TurbEntreBornes || data.PresenceDePompageModulable)) + { + data.NumeroDeContrainteMinEnergieHydraulique[pays] = builder.data.nombreDeContraintes; + + const int NombreDePasDeTempsPourUneOptimisation + = data.NombreDePasDeTempsPourUneOptimisation; + + ConstraintNamer namer(builder.data.NomDesContraintes, builder.data.NamedProblems); + namer.UpdateArea(builder.data.NomsDesPays[pays]); + namer.UpdateTimeStep(builder.data.weekInTheYear); + namer.MinHydroPower(builder.data.nombreDeContraintes); + for (int pdt = 0; pdt < NombreDePasDeTempsPourUneOptimisation; pdt++) + { + builder.updateHourWithinWeek(pdt); + builder.include(Variable::HydProd(pays), 1.0); + } + + data.NumeroDeContrainteMinEnergieHydraulique[pays] = builder.data.nombreDeContraintes; + builder.greaterThan().build(); + } + else + data.NumeroDeContrainteMinEnergieHydraulique[pays] = -1; +} diff --git a/src/solver/optimisation/MinHydroPower.h b/src/solver/optimisation/MinHydroPower.h new file mode 100644 index 0000000000..4d9620a48c --- /dev/null +++ b/src/solver/optimisation/MinHydroPower.h @@ -0,0 +1,18 @@ +#pragma once +#include "constraint_builder.h" + +struct MinHydroPowerData +{ + const bool& presenceHydro; + const bool& TurbEntreBornes; + const bool& PresenceDePompageModulable; + const int& NombreDePasDeTempsPourUneOptimisation; + std::vector& NumeroDeContrainteMinEnergieHydraulique; +}; + +class MinHydroPower : private Constraint +{ +public: + using Constraint::Constraint; + void add(int pays, MinHydroPowerData& data); +}; diff --git a/src/solver/optimisation/NbDispUnitsMinBoundSinceMinUpTime.cpp b/src/solver/optimisation/NbDispUnitsMinBoundSinceMinUpTime.cpp new file mode 100644 index 0000000000..2f8232613a --- /dev/null +++ b/src/solver/optimisation/NbDispUnitsMinBoundSinceMinUpTime.cpp @@ -0,0 +1,59 @@ +#include "NbDispUnitsMinBoundSinceMinUpTime.h" + +void NbDispUnitsMinBoundSinceMinUpTime::add(int pays, + int cluster, + int clusterIndex, + int pdt, + bool Simulation, + NbDispUnitsMinBoundSinceMinUpTimeData& data) +{ + const PALIERS_THERMIQUES& PaliersThermiquesDuPays = data.PaliersThermiquesDuPays[pays]; + const int DureeMinimaleDeMarcheDUnGroupeDuPalierThermique + = PaliersThermiquesDuPays.DureeMinimaleDeMarcheDUnGroupeDuPalierThermique[clusterIndex]; + + data.NumeroDeContrainteDesContraintesDeDureeMinDeMarche[cluster] = -1; + if (!Simulation) + { + int NombreDePasDeTempsPourUneOptimisation + = builder.data.NombreDePasDeTempsPourUneOptimisation; + + const std::vector& NombreMaxDeGroupesEnMarcheDuPalierThermique + = PaliersThermiquesDuPays.PuissanceDisponibleEtCout[clusterIndex] + .NombreMaxDeGroupesEnMarcheDuPalierThermique; + + builder.updateHourWithinWeek(pdt).include(Variable::NODU(cluster), 1.0); + + for (int k = pdt - DureeMinimaleDeMarcheDUnGroupeDuPalierThermique + 1; k <= pdt; k++) + { + int t1 = k; + if (t1 < 0) + t1 = NombreDePasDeTempsPourUneOptimisation + t1; + + builder.updateHourWithinWeek(t1) + .include(Variable::NumberStartingDispatchableUnits(cluster), -1.0) + .include(Variable::NumberBreakingDownDispatchableUnits(cluster), 1.0); + } + + builder.greaterThan(); + if (builder.NumberOfVariables() > 1) + { + data.NumeroDeContrainteDesContraintesDeDureeMinDeMarche[cluster] + = builder.data.nombreDeContraintes; + + ConstraintNamer namer(builder.data.NomDesContraintes, builder.data.NamedProblems); + namer.UpdateArea(builder.data.NomsDesPays[pays]); + + namer.UpdateTimeStep(builder.data.weekInTheYear * 168 + pdt); + namer.NbDispUnitsMinBoundSinceMinUpTime( + builder.data.nombreDeContraintes, + PaliersThermiquesDuPays.NomsDesPaliersThermiques[clusterIndex]); + builder.build(); + } + } + else + { + nbTermesContraintesPourLesCoutsDeDemarrage + += 1 + 2 * DureeMinimaleDeMarcheDUnGroupeDuPalierThermique; + builder.data.nombreDeContraintes++; + } +} diff --git a/src/solver/optimisation/NbDispUnitsMinBoundSinceMinUpTime.h b/src/solver/optimisation/NbDispUnitsMinBoundSinceMinUpTime.h new file mode 100644 index 0000000000..e4f85d8e17 --- /dev/null +++ b/src/solver/optimisation/NbDispUnitsMinBoundSinceMinUpTime.h @@ -0,0 +1,19 @@ +#pragma once +#include "constraint_builder.h" +struct NbDispUnitsMinBoundSinceMinUpTimeData : public StartUpCostsData +{ + std::vector& NumeroDeContrainteDesContraintesDeDureeMinDeMarche; +}; + +class NbDispUnitsMinBoundSinceMinUpTime : private Constraint +{ +public: + using Constraint::Constraint; + void add(int pays, + int cluster, + int clusterIndex, + int pdt, + bool Simulation, + NbDispUnitsMinBoundSinceMinUpTimeData& data); + int nbTermesContraintesPourLesCoutsDeDemarrage = 0; +}; \ No newline at end of file diff --git a/src/solver/optimisation/NbUnitsOutageLessThanNbUnitsStop.cpp b/src/solver/optimisation/NbUnitsOutageLessThanNbUnitsStop.cpp new file mode 100644 index 0000000000..f809731325 --- /dev/null +++ b/src/solver/optimisation/NbUnitsOutageLessThanNbUnitsStop.cpp @@ -0,0 +1,40 @@ +#include "NbUnitsOutageLessThanNbUnitsStop.h" + +void NbUnitsOutageLessThanNbUnitsStop::add(int pays, + int cluster, + int clusterIndex, + int pdt, + bool Simulation, + NbUnitsOutageLessThanNbUnitsStopData& data) +{ + if (!Simulation) + { + const PALIERS_THERMIQUES& PaliersThermiquesDuPays = data.PaliersThermiquesDuPays[pays]; + const int DureeMinimaleDArretDUnGroupeDuPalierThermique + = PaliersThermiquesDuPays.DureeMinimaleDArretDUnGroupeDuPalierThermique[clusterIndex]; + + data.NumeroDeContrainteDesContraintesDeDureeMinDeMarche[cluster] = -1; + + builder.updateHourWithinWeek(pdt) + .include(Variable::NumberBreakingDownDispatchableUnits(cluster), 1.0) + .include(Variable::NumberStoppingDispatchableUnits(cluster), -1.0) + .lessThan(); + + if (builder.NumberOfVariables() > 0) + { + ConstraintNamer namer(builder.data.NomDesContraintes, builder.data.NamedProblems); + namer.UpdateArea(builder.data.NomsDesPays[pays]); + namer.UpdateTimeStep(builder.data.weekInTheYear * 168 + pdt); + namer.NbUnitsOutageLessThanNbUnitsStop( + builder.data.nombreDeContraintes, + PaliersThermiquesDuPays.NomsDesPaliersThermiques[clusterIndex]); + + builder.build(); + } + } + else + { + nbTermesContraintesPourLesCoutsDeDemarrage += 4; + builder.data.nombreDeContraintes++; + } +} diff --git a/src/solver/optimisation/NbUnitsOutageLessThanNbUnitsStop.h b/src/solver/optimisation/NbUnitsOutageLessThanNbUnitsStop.h new file mode 100644 index 0000000000..f6f5aafe8d --- /dev/null +++ b/src/solver/optimisation/NbUnitsOutageLessThanNbUnitsStop.h @@ -0,0 +1,14 @@ +#pragma once +#include "constraint_builder.h" +struct NbUnitsOutageLessThanNbUnitsStopData : public StartUpCostsData +{ + std::vector& NumeroDeContrainteDesContraintesDeDureeMinDeMarche; +}; + +class NbUnitsOutageLessThanNbUnitsStop : private Constraint +{ +public: + using Constraint::Constraint; + void add(int pays, int cluster, int clusterIndex, int pdt, bool Simulation, NbUnitsOutageLessThanNbUnitsStopData&data); + int nbTermesContraintesPourLesCoutsDeDemarrage = 0; +}; \ No newline at end of file diff --git a/src/solver/optimisation/PMaxDispatchableGeneration.cpp b/src/solver/optimisation/PMaxDispatchableGeneration.cpp new file mode 100644 index 0000000000..155e9297f1 --- /dev/null +++ b/src/solver/optimisation/PMaxDispatchableGeneration.cpp @@ -0,0 +1,38 @@ +#include "PMaxDispatchableGeneration.h" + +void PMaxDispatchableGeneration::add(int pays, + int cluster, + int clusterIndex, + int pdt, + bool Simulation, + StartUpCostsData& data) +{ + if (!Simulation) + { + const PALIERS_THERMIQUES& PaliersThermiquesDuPays = data.PaliersThermiquesDuPays[pays]; + double pmaxDUnGroupeDuPalierThermique + = PaliersThermiquesDuPays.PmaxDUnGroupeDuPalierThermique[clusterIndex]; + + builder.updateHourWithinWeek(pdt) + .include(Variable::DispatchableProduction(cluster), 1.0) + .include(Variable::NODU(cluster), -pmaxDUnGroupeDuPalierThermique) + .lessThan(); + if (builder.NumberOfVariables() > 0) + { + ConstraintNamer namer(builder.data.NomDesContraintes, builder.data.NamedProblems); + + namer.UpdateTimeStep(builder.data.weekInTheYear * 168 + pdt); + namer.UpdateArea(builder.data.NomsDesPays[pays]); + + namer.PMaxDispatchableGeneration( + builder.data.nombreDeContraintes, + PaliersThermiquesDuPays.NomsDesPaliersThermiques[clusterIndex]); + } + builder.build(); + } + else + { + nbTermesContraintesPourLesCoutsDeDemarrage += 2; + builder.data.nombreDeContraintes++; + } +} \ No newline at end of file diff --git a/src/solver/optimisation/PMaxDispatchableGeneration.h b/src/solver/optimisation/PMaxDispatchableGeneration.h new file mode 100644 index 0000000000..fb3fb07860 --- /dev/null +++ b/src/solver/optimisation/PMaxDispatchableGeneration.h @@ -0,0 +1,15 @@ +#pragma once +#include "constraint_builder.h" + +class PMaxDispatchableGeneration : private Constraint +{ +public: + using Constraint::Constraint; + void add(int pays, + int cluster, + int clusterIndex, + int pdt, + bool Simulation, + StartUpCostsData& data); + int nbTermesContraintesPourLesCoutsDeDemarrage = 0; +}; \ No newline at end of file diff --git a/src/solver/optimisation/PMinDispatchableGeneration.cpp b/src/solver/optimisation/PMinDispatchableGeneration.cpp new file mode 100644 index 0000000000..58b35923bb --- /dev/null +++ b/src/solver/optimisation/PMinDispatchableGeneration.cpp @@ -0,0 +1,38 @@ +#include "PMinDispatchableGeneration.h" + +void PMinDispatchableGeneration::add(int pays, + int cluster, + int clusterIndex, + int pdt, + bool Simulation, + StartUpCostsData& data) +{ + if (!Simulation) + { + const PALIERS_THERMIQUES& PaliersThermiquesDuPays = data.PaliersThermiquesDuPays[pays]; + double pminDUnGroupeDuPalierThermique + = PaliersThermiquesDuPays.pminDUnGroupeDuPalierThermique[clusterIndex]; + + builder.updateHourWithinWeek(pdt) + .include(Variable::DispatchableProduction(cluster), 1.0) + .include(Variable::NODU(cluster), -pminDUnGroupeDuPalierThermique) + .greaterThan(); + /*consider Adding naming constraint inside the builder*/ + if (builder.NumberOfVariables() > 0) + { + ConstraintNamer namer(builder.data.NomDesContraintes, builder.data.NamedProblems); + namer.UpdateArea(builder.data.NomsDesPays[pays]); + + namer.UpdateTimeStep(builder.data.weekInTheYear * 168 + pdt); + namer.PMinDispatchableGeneration( + builder.data.nombreDeContraintes, + PaliersThermiquesDuPays.NomsDesPaliersThermiques[clusterIndex]); + } + builder.build(); + } + else + { + nbTermesContraintesPourLesCoutsDeDemarrage += 2; + builder.data.nombreDeContraintes++; + } +} diff --git a/src/solver/optimisation/PMinDispatchableGeneration.h b/src/solver/optimisation/PMinDispatchableGeneration.h new file mode 100644 index 0000000000..ab1499c3e4 --- /dev/null +++ b/src/solver/optimisation/PMinDispatchableGeneration.h @@ -0,0 +1,10 @@ +#pragma once +#include "constraint_builder.h" + +class PMinDispatchableGeneration : private Constraint +{ +public: + using Constraint::Constraint; + void add(int pays, int cluster, int clusterIndex, int pdt, bool Simulation, StartUpCostsData& data); + int nbTermesContraintesPourLesCoutsDeDemarrage = 0; +}; \ No newline at end of file diff --git a/src/solver/optimisation/ShortTermStorageLevel.cpp b/src/solver/optimisation/ShortTermStorageLevel.cpp new file mode 100644 index 0000000000..ededb07ff7 --- /dev/null +++ b/src/solver/optimisation/ShortTermStorageLevel.cpp @@ -0,0 +1,30 @@ +#include "ShortTermStorageLevel.h" + +void ShortTermStorageLevel::add(int pdt, int pays, ShortTermStorageLevelData& data) +{ + // TODO improve this + ConstraintNamer namer(builder.data.NomDesContraintes, builder.data.NamedProblems); + const int hourInTheYear = builder.data.weekInTheYear * 168 + pdt; + namer.UpdateTimeStep(hourInTheYear); + namer.UpdateArea(builder.data.NomsDesPays[pays]); + + builder.updateHourWithinWeek(pdt); + for (const auto& storage : data.ShortTermStorage[pays]) + { + // L[h] - L[h-1] - efficiency * injection[h] + withdrawal[h] = inflows[h] + namer.ShortTermStorageLevel(builder.data.nombreDeContraintes, storage.name); + const auto index = storage.clusterGlobalIndex; + data.ShortTermStorageLevelConstraint[index] = builder.data.nombreDeContraintes; + + builder.include(Variable::ShortTermStorageLevel(index), 1.0) + .include(Variable::ShortTermStorageLevel(index), + -1.0, + -1, + true, + builder.data.NombreDePasDeTempsPourUneOptimisation) + .include(Variable::ShortTermStorageInjection(index), -1.0 * storage.efficiency) + .include(Variable::ShortTermStorageWithdrawal(index), 1.0) + .equalTo() + .build(); + } +} diff --git a/src/solver/optimisation/ShortTermStorageLevel.h b/src/solver/optimisation/ShortTermStorageLevel.h new file mode 100644 index 0000000000..a44ddc15b2 --- /dev/null +++ b/src/solver/optimisation/ShortTermStorageLevel.h @@ -0,0 +1,15 @@ +#pragma once +#include "constraint_builder.h" + +struct ShortTermStorageLevelData +{ + std::vector& ShortTermStorageLevelConstraint; + const std::vector<::ShortTermStorage::AREA_INPUT>& ShortTermStorage; +}; + +class ShortTermStorageLevel : private Constraint +{ +public: + using Constraint::Constraint; + void add(int pdt, int pays, ShortTermStorageLevelData& data); +}; diff --git a/src/solver/optimisation/adequacy_patch_csr/csr_quadratic_problem.cpp b/src/solver/optimisation/adequacy_patch_csr/csr_quadratic_problem.cpp index 90ac4709c1..856096b24b 100644 --- a/src/solver/optimisation/adequacy_patch_csr/csr_quadratic_problem.cpp +++ b/src/solver/optimisation/adequacy_patch_csr/csr_quadratic_problem.cpp @@ -33,230 +33,275 @@ #include "csr_quadratic_problem.h" #include "hourly_csr_problem.h" #include "sim_structure_probleme_economique.h" +#include "../constraint_builder.h" +#include "../constraint_builder_utils.h" +#include "../opt_rename_problem.h" +#include "adequacy_patch_runtime_data.h" using namespace Antares::Data; namespace Antares::Solver::Optimization { -void CsrQuadraticProblem::setConstraintsOnFlows(std::vector& Pi, std::vector& Colonne) +struct CsrFlowDissociationData { - int hour = hourlyCsrProblem_.triggeredHour; - const CORRESPONDANCES_DES_VARIABLES& CorrespondanceVarNativesVarOptim - = problemeHebdo_->CorrespondanceVarNativesVarOptim[hour]; + std::map& numberOfConstraintCsrFlowDissociation; + const uint32_t NombreDInterconnexions; + + const std::vector& originAreaMode; + const std::vector& extremityAreaMode; - // constraint: Flow = Flow_direct - Flow_indirect (+ loop flow) for links between nodes of - // type 2. - for (uint32_t Interco = 0; Interco < problemeHebdo_->NombreDInterconnexions; Interco++) + const std::vector& PaysOrigineDeLInterconnexion; + const std::vector& PaysExtremiteDeLInterconnexion; +}; +class CsrFlowDissociation : private Constraint +{ +public: + using Constraint::Constraint; + void add(int hour, CsrFlowDissociationData& data) { - if (problemeHebdo_->adequacyPatchRuntimeData->originAreaMode[Interco] - == Antares::Data::AdequacyPatch::physicalAreaInsideAdqPatch - && problemeHebdo_->adequacyPatchRuntimeData->extremityAreaMode[Interco] - == Antares::Data::AdequacyPatch::physicalAreaInsideAdqPatch) + builder.updateHourWithinWeek(hour); + + ConstraintNamer namer(builder.data.NomDesContraintes, builder.data.NamedProblems); + namer.UpdateTimeStep(hour); + // constraint: Flow = Flow_direct - Flow_indirect (+ loop flow) for links between nodes + // of type 2. + for (uint32_t interco = 0; interco < data.NombreDInterconnexions; interco++) { - int NombreDeTermes = 0; - int var = CorrespondanceVarNativesVarOptim.NumeroDeVariableDeLInterconnexion[Interco]; - if (var >= 0) - { - Pi[NombreDeTermes] = 1.0; - Colonne[NombreDeTermes] = var; - NombreDeTermes++; - } - var = CorrespondanceVarNativesVarOptim - .NumeroDeVariableCoutOrigineVersExtremiteDeLInterconnexion[Interco]; - if (var >= 0) - { - Pi[NombreDeTermes] = -1.0; - Colonne[NombreDeTermes] = var; - NombreDeTermes++; - } - var = CorrespondanceVarNativesVarOptim - .NumeroDeVariableCoutExtremiteVersOrigineDeLInterconnexion[Interco]; - if (var >= 0) + if (data.originAreaMode[interco] + == Antares::Data::AdequacyPatch::physicalAreaInsideAdqPatch + && data.extremityAreaMode[interco] + == Antares::Data::AdequacyPatch::physicalAreaInsideAdqPatch) { - Pi[NombreDeTermes] = 1.0; - Colonne[NombreDeTermes] = var; - NombreDeTermes++; + builder.include(Variable::NTCDirect(interco), 1.0) + .include(Variable::IntercoDirectCost(interco), -1.0) + .include(Variable::IntercoIndirectCost(interco), 1.0); + + data.numberOfConstraintCsrFlowDissociation[interco] + = builder.data.nombreDeContraintes; + + const auto& origin + = builder.data.NomsDesPays[data.PaysOrigineDeLInterconnexion[interco]]; + const auto& destination + = builder.data.NomsDesPays[data.PaysExtremiteDeLInterconnexion[interco]]; + namer.CsrFlowDissociation(builder.data.nombreDeContraintes, origin, destination); + builder.equalTo(); + builder.build(); } - - hourlyCsrProblem_.numberOfConstraintCsrFlowDissociation[Interco] - = problemeAResoudre_.NombreDeContraintes; - - std::string NomDeLaContrainte = "flow=d-i, Interco:" + std::to_string(Interco); - logs.debug() << "C Interco: " << problemeAResoudre_.NombreDeContraintes << ": " - << NomDeLaContrainte; - - OPT_ChargerLaContrainteDansLaMatriceDesContraintes( - &problemeAResoudre_, Pi, Colonne, NombreDeTermes, '='); } } -} +}; -void CsrQuadraticProblem::setNodeBalanceConstraints(std::vector& Pi, std::vector& Colonne) +void CsrQuadraticProblem::setConstraintsOnFlows(std::vector& Pi, std::vector& Colonne) { int hour = hourlyCsrProblem_.triggeredHour; - const CORRESPONDANCES_DES_VARIABLES& CorrespondanceVarNativesVarOptim - = problemeHebdo_->CorrespondanceVarNativesVarOptim[hour]; - - // constraint: - // ENS(node A) + - // - flow (A -> 2) or (+ flow (2 -> A)) there should be only one of them, otherwise double-count - // - spillage(node A) = - // ENS_init(node A) + net_position_init(node A) – spillage_init(node A) - // for all areas inside adequacy patch - - for (uint32_t Area = 0; Area < problemeHebdo_->NombreDePays; ++Area) + //!\ TODO not associated problemHebdo && probleamAressoudre + auto builder = GetConstraintBuilderFromProblemHebdoAndProblemAResoudre(problemeHebdo_, + &problemeAResoudre_); + CsrFlowDissociation csrFlowDissociation(builder); + CsrFlowDissociationData csrFlowDissociationData + = {hourlyCsrProblem_.numberOfConstraintCsrFlowDissociation, + problemeHebdo_->NombreDInterconnexions, + problemeHebdo_->adequacyPatchRuntimeData->originAreaMode, + problemeHebdo_->adequacyPatchRuntimeData->extremityAreaMode, + problemeHebdo_->PaysOrigineDeLInterconnexion, + problemeHebdo_->PaysExtremiteDeLInterconnexion}; + + csrFlowDissociation.add(hour, csrFlowDissociationData); +} +struct CsrAreaBalanceData +{ + const adqPatchParamsMode& areaMode; + const int hour; + const std::vector& IndexDebutIntercoOrigine; + const std::vector& IndexSuivantIntercoOrigine; + const std::vector& IndexDebutIntercoExtremite; + const std::vector& IndexSuivantIntercoExtremite; + + const std::vector& originAreaMode; + const std::vector& extremityAreaMode; + const std::vector& PaysOrigineDeLInterconnexion; + const std::vector& PaysExtremiteDeLInterconnexion; + std::map numberOfConstraintCsrAreaBalance; +}; + +class CsrAreaBalance : private Constraint +{ +public: + using Constraint::Constraint; + void add(uint32_t Area, CsrAreaBalanceData& data) { - if (problemeHebdo_->adequacyPatchRuntimeData->areaMode[Area] - != Data::AdequacyPatch::physicalAreaInsideAdqPatch) - continue; + if (data.areaMode != Data::AdequacyPatch::physicalAreaInsideAdqPatch) + return; // + ENS int NombreDeTermes = 0; - int var = CorrespondanceVarNativesVarOptim.NumeroDeVariableDefaillancePositive[Area]; - if (var >= 0) - { - Pi[NombreDeTermes] = 1.0; - Colonne[NombreDeTermes] = var; - NombreDeTermes++; - } + builder.updateHourWithinWeek(data.hour).include(Variable::NegativeUnsuppliedEnergy(Area), + 1.0); // - export flows - int Interco = problemeHebdo_->IndexDebutIntercoOrigine[Area]; + int Interco = data.IndexDebutIntercoOrigine[Area]; while (Interco >= 0) { - if (problemeHebdo_->adequacyPatchRuntimeData->extremityAreaMode[Interco] - != Data::AdequacyPatch::physicalAreaInsideAdqPatch) + if (data.extremityAreaMode[Interco] != Data::AdequacyPatch::physicalAreaInsideAdqPatch) { - Interco = problemeHebdo_->IndexSuivantIntercoOrigine[Interco]; + Interco = data.IndexSuivantIntercoOrigine[Interco]; continue; } - var = CorrespondanceVarNativesVarOptim - .NumeroDeVariableDeLInterconnexion[Interco]; // flow (A->2) - if (var >= 0) - { - Pi[NombreDeTermes] = -1.0; - Colonne[NombreDeTermes] = var; - NombreDeTermes++; - logs.debug() - << "S-Interco number: [" << std::to_string(Interco) << "] between: [" - << problemeHebdo_->NomsDesPays[Area] << "]-[" - << problemeHebdo_ - ->NomsDesPays[problemeHebdo_->PaysExtremiteDeLInterconnexion[Interco]] - << "]"; - } - Interco = problemeHebdo_->IndexSuivantIntercoOrigine[Interco]; + // flow (A->2) + builder.include(Variable::NTCDirect(Interco), -1.0); + + logs.debug() << "S-Interco number: [" << std::to_string(Interco) << "] between: [" + << builder.data.NomsDesPays[Area] << "]-[" + << builder.data.NomsDesPays[data.PaysExtremiteDeLInterconnexion[Interco]] + << "]"; + + Interco = data.IndexSuivantIntercoOrigine[Interco]; } // or + import flows - Interco = problemeHebdo_->IndexDebutIntercoExtremite[Area]; + Interco = data.IndexDebutIntercoExtremite[Area]; while (Interco >= 0) { - if (problemeHebdo_->adequacyPatchRuntimeData->originAreaMode[Interco] - != Data::AdequacyPatch::physicalAreaInsideAdqPatch) + if (data.originAreaMode[Interco] != Data::AdequacyPatch::physicalAreaInsideAdqPatch) { - Interco = problemeHebdo_->IndexSuivantIntercoExtremite[Interco]; + Interco = data.IndexSuivantIntercoExtremite[Interco]; continue; } - var = CorrespondanceVarNativesVarOptim - .NumeroDeVariableDeLInterconnexion[Interco]; // flow (2 -> A) - if (var >= 0) - { - Pi[NombreDeTermes] = 1.0; - Colonne[NombreDeTermes] = var; - NombreDeTermes++; - logs.debug() - << "E-Interco number: [" << std::to_string(Interco) << "] between: [" - << problemeHebdo_->NomsDesPays[Area] << "]-[" - << problemeHebdo_ - ->NomsDesPays[problemeHebdo_->PaysOrigineDeLInterconnexion[Interco]] - << "]"; - } - Interco = problemeHebdo_->IndexSuivantIntercoExtremite[Interco]; + // flow (2 -> A) + builder.include(Variable::NTCDirect(Interco), 1.0); + + logs.debug() << "E-Interco number: [" << std::to_string(Interco) << "] between: [" + << builder.data.NomsDesPays[Area] << "]-[" + << builder.data.NomsDesPays[data.PaysOrigineDeLInterconnexion[Interco]] + << "]"; + + Interco = data.IndexSuivantIntercoExtremite[Interco]; } // - Spilled Energy - var = CorrespondanceVarNativesVarOptim.NumeroDeVariableDefaillanceNegative[Area]; - if (var >= 0) - { - Pi[NombreDeTermes] = -1.0; - Colonne[NombreDeTermes] = var; - NombreDeTermes++; - } + builder.include(Variable::NegativeUnsuppliedEnergy(Area), -1.0); - hourlyCsrProblem_.numberOfConstraintCsrAreaBalance[Area] - = problemeAResoudre_.NombreDeContraintes; + data.numberOfConstraintCsrAreaBalance[Area] = builder.data.nombreDeContraintes; std::string NomDeLaContrainte - = "Area Balance, Area:" + std::to_string(Area) + "; " + problemeHebdo_->NomsDesPays[Area]; + = "Area Balance, Area:" + std::to_string(Area) + "; " + builder.data.NomsDesPays[Area]; + + logs.debug() << "C: " << builder.data.nombreDeContraintes << ": " << NomDeLaContrainte; + builder.equalTo(); + builder.build(); + } +}; +void CsrQuadraticProblem::setNodeBalanceConstraints(std::vector& Pi, + std::vector& Colonne) +{ + int hour = hourlyCsrProblem_.triggeredHour; + const CORRESPONDANCES_DES_VARIABLES& CorrespondanceVarNativesVarOptim + = problemeHebdo_->CorrespondanceVarNativesVarOptim[hour]; - logs.debug() << "C: " << problemeAResoudre_.NombreDeContraintes << ": " - << NomDeLaContrainte; + // constraint: + // ENS(node A) + + // - flow (A -> 2) or (+ flow (2 -> A)) there should be only one of them, otherwise double-count + // - spillage(node A) = + // ENS_init(node A) + net_position_init(node A) – spillage_init(node A) + // for all areas inside adequacy patch + + ConstraintBuilder builder( + GetConstraintBuilderFromProblemHebdoAndProblemAResoudre(problemeHebdo_, &problemeAResoudre_)); + CsrAreaBalance csrAreaBalance(builder); - OPT_ChargerLaContrainteDansLaMatriceDesContraintes( - &problemeAResoudre_, Pi, Colonne, NombreDeTermes, '='); + for (uint32_t Area = 0; Area < problemeHebdo_->NombreDePays; ++Area) + { + CsrAreaBalanceData csrAreaBalanceData{ + problemeHebdo_->adequacyPatchRuntimeData->areaMode[Area], + hour, + problemeHebdo_->IndexDebutIntercoOrigine, + problemeHebdo_->IndexSuivantIntercoOrigine, + problemeHebdo_->IndexDebutIntercoExtremite, + problemeHebdo_->IndexSuivantIntercoExtremite, + problemeHebdo_->adequacyPatchRuntimeData->originAreaMode, + problemeHebdo_->adequacyPatchRuntimeData->extremityAreaMode, + problemeHebdo_->PaysOrigineDeLInterconnexion, + problemeHebdo_->PaysExtremiteDeLInterconnexion, + hourlyCsrProblem_.numberOfConstraintCsrAreaBalance}; + csrAreaBalance.add(Area, csrAreaBalanceData); } } -void CsrQuadraticProblem::setBindingConstraints(std::vector& Pi, std::vector& Colonne) +struct CsrBindingConstraintHourData { - int hour = hourlyCsrProblem_.triggeredHour; + const CONTRAINTES_COUPLANTES& MatriceDesContraintesCouplantes; - // Special case of the binding constraints - for (uint32_t CntCouplante = 0; CntCouplante < problemeHebdo_->NombreDeContraintesCouplantes; - CntCouplante++) - { - const CONTRAINTES_COUPLANTES& MatriceDesContraintesCouplantes - = problemeHebdo_->MatriceDesContraintesCouplantes[CntCouplante]; + const std::vector& originAreaMode; + const std::vector& extremityAreaMode; + const int hour; - if (MatriceDesContraintesCouplantes.TypeDeContrainteCouplante != CONTRAINTE_HORAIRE) - continue; + std::map& numberOfConstraintCsrHourlyBinding; +}; + +class CsrBindingConstraintHour : private Constraint +{ +public: + using Constraint::Constraint; + void add(int CntCouplante, CsrBindingConstraintHourData& data) + { + if (data.MatriceDesContraintesCouplantes.TypeDeContrainteCouplante != CONTRAINTE_HORAIRE) + return; int NbInterco - = MatriceDesContraintesCouplantes.NombreDInterconnexionsDansLaContrainteCouplante; - int NombreDeTermes = 0; + = data.MatriceDesContraintesCouplantes.NombreDInterconnexionsDansLaContrainteCouplante; + builder.updateHourWithinWeek(data.hour); + for (int Index = 0; Index < NbInterco; Index++) { - int Interco = MatriceDesContraintesCouplantes.NumeroDeLInterconnexion[Index]; - double Poids = MatriceDesContraintesCouplantes.PoidsDeLInterconnexion[Index]; + int Interco = data.MatriceDesContraintesCouplantes.NumeroDeLInterconnexion[Index]; + double Poids = data.MatriceDesContraintesCouplantes.PoidsDeLInterconnexion[Index]; - if (problemeHebdo_->adequacyPatchRuntimeData->originAreaMode[Interco] - == Data::AdequacyPatch::physicalAreaInsideAdqPatch - && problemeHebdo_->adequacyPatchRuntimeData->extremityAreaMode[Interco] + if (data.originAreaMode[Interco] == Data::AdequacyPatch::physicalAreaInsideAdqPatch + && data.extremityAreaMode[Interco] == Data::AdequacyPatch::physicalAreaInsideAdqPatch) { - int var = problemeHebdo_->CorrespondanceVarNativesVarOptim[hour] - .NumeroDeVariableDeLInterconnexion[Interco]; - - if (var >= 0) - { - Pi[NombreDeTermes] = Poids; - Colonne[NombreDeTermes] = var; - NombreDeTermes++; - } + builder.include(Variable::NTCDirect(Interco), Poids); } } - if (NombreDeTermes > 0) // current binding constraint contains an interco type 2<->2 + if (builder.NumberOfVariables() + > 0) // current binding constraint contains an interco type 2<->2 { - hourlyCsrProblem_.numberOfConstraintCsrHourlyBinding[CntCouplante] - = problemeAResoudre_.NombreDeContraintes; + data.numberOfConstraintCsrHourlyBinding[CntCouplante] + = builder.data.nombreDeContraintes; std::string NomDeLaContrainte - = "bc::hourly::" + std::to_string(hour) - + "::" + MatriceDesContraintesCouplantes.NomDeLaContrainteCouplante; + = "bc::hourly::" + std::to_string(data.hour) + + "::" + data.MatriceDesContraintesCouplantes.NomDeLaContrainteCouplante; - logs.debug() << "C (bc): " << problemeAResoudre_.NombreDeContraintes << ": " + logs.debug() << "C (bc): " << builder.data.nombreDeContraintes << ": " << NomDeLaContrainte; - OPT_ChargerLaContrainteDansLaMatriceDesContraintes( - &problemeAResoudre_, - Pi, - Colonne, - NombreDeTermes, - MatriceDesContraintesCouplantes.SensDeLaContrainteCouplante); + char op = data.MatriceDesContraintesCouplantes.SensDeLaContrainteCouplante; + builder.operatorRHS(op); + builder.build(); } } +}; +void CsrQuadraticProblem::setBindingConstraints(std::vector& Pi, std::vector& Colonne) +{ + int hour = hourlyCsrProblem_.triggeredHour; + ConstraintBuilder builder( + GetConstraintBuilderFromProblemHebdoAndProblemAResoudre(problemeHebdo_, &problemeAResoudre_)); + // Special case of the binding constraints + for (uint32_t CntCouplante = 0; CntCouplante < problemeHebdo_->NombreDeContraintesCouplantes; + CntCouplante++) + { + CsrBindingConstraintHourData csrBindingConstraintHourData + = {problemeHebdo_->MatriceDesContraintesCouplantes[CntCouplante], + problemeHebdo_->adequacyPatchRuntimeData->originAreaMode, + problemeHebdo_->adequacyPatchRuntimeData->extremityAreaMode, + hour, + hourlyCsrProblem_.numberOfConstraintCsrHourlyBinding}; + CsrBindingConstraintHour csrBindingConstraintHour(builder); + csrBindingConstraintHour.add(CntCouplante, csrBindingConstraintHourData); + } } void CsrQuadraticProblem::buildConstraintMatrix() @@ -265,7 +310,7 @@ void CsrQuadraticProblem::buildConstraintMatrix() std::vector Pi(problemeAResoudre_.NombreDeVariables); std::vector Colonne(problemeAResoudre_.NombreDeVariables); - + // TODO reset problemeAResoudre_.Pi and problemeAResoudre_.Colonne? problemeAResoudre_.NombreDeContraintes = 0; problemeAResoudre_.NombreDeTermesDansLaMatriceDesContraintes = 0; diff --git a/src/solver/optimisation/constraint_builder.cpp b/src/solver/optimisation/constraint_builder.cpp new file mode 100644 index 0000000000..3cc8fae217 --- /dev/null +++ b/src/solver/optimisation/constraint_builder.cpp @@ -0,0 +1,160 @@ +#include "constraint_builder.h" + +// for debug +int Variable::Visitor::operator()(const NTCDirect& v) const +{ + return nativeOptimVar.NumeroDeVariableDeLInterconnexion[v.index]; +} + +ConstraintBuilderData::ConstraintBuilderData( + std::vector& Pi, + std::vector& Colonne, + int& nombreDeContraintes, + int& nombreDeTermesDansLaMatriceDeContrainte, + std::vector& IndicesDebutDeLigne, + std::vector& CoefficientsDeLaMatriceDesContraintes, + std::vector& IndicesColonnes, + int& NombreDeTermesAllouesDansLaMatriceDesContraintes, + std::vector& NombreDeTermesDesLignes, + std::string& Sens, + int& IncrementDAllocationMatriceDesContraintes, + const std::vector& CorrespondanceVarNativesVarOptim, + const int32_t& NombreDePasDeTempsPourUneOptimisation, + const std::vector& NumeroDeVariableStockFinal, + const std::vector>& NumeroDeVariableDeTrancheDeStock, + std::vector& NomDesContraintes, + const bool& NamedProblems, + const std::vector& NomsDesPays, + const uint32_t& weekInTheYear, + const uint32_t& NombreDePasDeTemps) : + Pi(Pi), + Colonne(Colonne), + nombreDeContraintes(nombreDeContraintes), + nombreDeTermesDansLaMatriceDeContrainte(nombreDeTermesDansLaMatriceDeContrainte), + IndicesDebutDeLigne(IndicesDebutDeLigne), + CoefficientsDeLaMatriceDesContraintes(CoefficientsDeLaMatriceDesContraintes), + IndicesColonnes(IndicesColonnes), + NombreDeTermesAllouesDansLaMatriceDesContraintes(NombreDeTermesAllouesDansLaMatriceDesContraintes), + NombreDeTermesDesLignes(NombreDeTermesDesLignes), + Sens(Sens), + IncrementDAllocationMatriceDesContraintes(IncrementDAllocationMatriceDesContraintes), + CorrespondanceVarNativesVarOptim(CorrespondanceVarNativesVarOptim), + NombreDePasDeTempsPourUneOptimisation(NombreDePasDeTempsPourUneOptimisation), + NumeroDeVariableStockFinal(NumeroDeVariableStockFinal), + NumeroDeVariableDeTrancheDeStock(NumeroDeVariableDeTrancheDeStock), + NomDesContraintes(NomDesContraintes), + NamedProblems(NamedProblems), + NomsDesPays(NomsDesPays), + weekInTheYear(weekInTheYear), + NombreDePasDeTemps(NombreDePasDeTemps) +{ +} + +void ConstraintBuilder::build() +{ + // TODO check operator_ + if (nombreDeTermes_ > 0) + { + // Matrix + OPT_ChargerLaContrainteDansLaMatriceDesContraintes(); + } + nombreDeTermes_ = 0; +} + +int ConstraintBuilder::getVariableIndex(const Variable::Variant& variable, + int shift, + bool wrap, + int delta) const +{ + auto pdt = hourInWeek_ + shift; + const auto nbTimeSteps = data.NombreDePasDeTempsPourUneOptimisation; + // if (wrap) + // { + // pdt %= nbTimeSteps; + // if (pdt < 0) + // pdt += problemeHebdo->NombreDePasDeTemps; + // } + // if (pdt < 0 || pdt >= nbTimeSteps) + // { + // return -1; + // } + + if (wrap) + { + if (shift >= 0) + { + pdt = (pdt) % nbTimeSteps; + } + else + { + pdt = (pdt + delta) % nbTimeSteps; + } + } + // auto& a = data.CorrespondanceVarNativesVarOptim[pdt]; + const Variable::Visitor visitor(data.CorrespondanceVarNativesVarOptim[pdt], + data.NumeroDeVariableStockFinal, + data.NumeroDeVariableDeTrancheDeStock); + return std::visit(visitor, variable); +} + +ConstraintBuilder& ConstraintBuilder::include(Variable::Variant var, + double coeff, + int shift, + bool wrap, + int delta) +{ + int varIndex = getVariableIndex(var, shift, wrap, delta); + if (varIndex >= 0) + { + data.Pi[nombreDeTermes_] = coeff; + data.Colonne[nombreDeTermes_] = varIndex; + nombreDeTermes_++; + } + return *this; +} + +void ConstraintBuilder::OPT_ChargerLaContrainteDansLaMatriceDesContraintes() +{ + // int& nombreDeContraintes = data.nombreDeContraintes; + // int& nombreDeTermesDansLaMatriceDeContrainte = data.nombreDeTermesDansLaMatriceDeContrainte; + // std::vector& Pi = data.Pi; + // std::vector& Colonne = data.Colonne; + + data.IndicesDebutDeLigne[data.nombreDeContraintes] + = data.nombreDeTermesDansLaMatriceDeContrainte; + for (int i = 0; i < nombreDeTermes_; i++) + { + data.CoefficientsDeLaMatriceDesContraintes[data.nombreDeTermesDansLaMatriceDeContrainte] + = data.Pi[i]; + data.IndicesColonnes[data.nombreDeTermesDansLaMatriceDeContrainte] = data.Colonne[i]; + data.nombreDeTermesDansLaMatriceDeContrainte++; + if (data.nombreDeTermesDansLaMatriceDeContrainte + == data.NombreDeTermesAllouesDansLaMatriceDesContraintes) + { + OPT_AugmenterLaTailleDeLaMatriceDesContraintes(); + } + } + data.NombreDeTermesDesLignes[data.nombreDeContraintes] = nombreDeTermes_; + + data.Sens[data.nombreDeContraintes] = operator_; + data.nombreDeContraintes++; + + return; +} + +void ConstraintBuilder::OPT_AugmenterLaTailleDeLaMatriceDesContraintes() +{ + int NbTermes = data.NombreDeTermesAllouesDansLaMatriceDesContraintes; + NbTermes += data.IncrementDAllocationMatriceDesContraintes; + + logs.info(); + logs.info() << " Expected Number of Non-zero terms in Problem Matrix : increased to : " + << NbTermes; + logs.info(); + + data.CoefficientsDeLaMatriceDesContraintes.resize(NbTermes); + + data.IndicesColonnes.resize(NbTermes); + + data.NombreDeTermesAllouesDansLaMatriceDesContraintes = NbTermes; +} \ No newline at end of file diff --git a/src/solver/optimisation/constraint_builder.h b/src/solver/optimisation/constraint_builder.h new file mode 100644 index 0000000000..ed4c4fc496 --- /dev/null +++ b/src/solver/optimisation/constraint_builder.h @@ -0,0 +1,496 @@ +#pragma once + +#include +#include "opt_structure_probleme_a_resoudre.h" +#include "opt_rename_problem.h" +#include "opt_fonctions.h" + +// TODO remove relative include +#include "../simulation/sim_structure_probleme_economique.h" + +#include +#include + +namespace Variable +{ +struct SingleIndex +{ + explicit SingleIndex(unsigned index) : index(index) + { + } + unsigned index; +}; + +struct DispatchableProduction : public SingleIndex +{ + using SingleIndex::SingleIndex; +}; +struct NODU : public SingleIndex +{ + using SingleIndex::SingleIndex; +}; +struct NumberStoppingDispatchableUnits : public SingleIndex +{ + using SingleIndex::SingleIndex; +}; +struct NumberStartingDispatchableUnits : public SingleIndex +{ + using SingleIndex::SingleIndex; +}; +struct NumberBreakingDownDispatchableUnits : public SingleIndex +{ + using SingleIndex::SingleIndex; +}; + +struct NTCDirect : public SingleIndex +{ + using SingleIndex::SingleIndex; +}; +struct IntercoDirectCost : public SingleIndex +{ + using SingleIndex::SingleIndex; +}; +struct IntercoIndirectCost : public SingleIndex +{ + using SingleIndex::SingleIndex; +}; + +struct ShortTermStorageInjection : public SingleIndex +{ + using SingleIndex::SingleIndex; +}; +struct ShortTermStorageWithdrawal : public SingleIndex +{ + using SingleIndex::SingleIndex; +}; +struct ShortTermStorageLevel : public SingleIndex +{ + using SingleIndex::SingleIndex; +}; + +struct HydProd : public SingleIndex +{ + using SingleIndex::SingleIndex; +}; +struct HydProdDown : public SingleIndex +{ + using SingleIndex::SingleIndex; +}; +struct HydProdUp : public SingleIndex +{ + using SingleIndex::SingleIndex; +}; +struct Pumping : public SingleIndex +{ + using SingleIndex::SingleIndex; +}; +struct HydroLevel : public SingleIndex +{ + using SingleIndex::SingleIndex; +}; +struct Overflow : public SingleIndex +{ + using SingleIndex::SingleIndex; +}; +struct FinalStorage : public SingleIndex +{ + using SingleIndex::SingleIndex; +}; +struct PositiveUnsuppliedEnergy : public SingleIndex +{ + using SingleIndex::SingleIndex; +}; +struct NegativeUnsuppliedEnergy : public SingleIndex +{ + using SingleIndex::SingleIndex; +}; + +struct LayerStorage +{ + LayerStorage(unsigned area, unsigned layer) : area(area), layer(layer) + { + } + unsigned area, layer; +}; + +using Variant = std::variant; + +class Visitor +{ +public: + Visitor(const CORRESPONDANCES_DES_VARIABLES& nativeOptimVar, + const std::vector& NumeroDeVariableStockFinal, + const std::vector>& NumeroDeVariableDeTrancheDeStock) : + nativeOptimVar(nativeOptimVar), + NumeroDeVariableStockFinal(NumeroDeVariableStockFinal), + NumeroDeVariableDeTrancheDeStock(NumeroDeVariableDeTrancheDeStock) + { + } + + int operator()(const DispatchableProduction& v) const + { + return nativeOptimVar.NumeroDeVariableDuPalierThermique[v.index]; + } + int operator()(const NODU& v) const + { + return nativeOptimVar.NumeroDeVariableDuNombreDeGroupesEnMarcheDuPalierThermique[v.index]; + } + int operator()(const NumberStoppingDispatchableUnits& v) const + { + return nativeOptimVar + .NumeroDeVariableDuNombreDeGroupesQuiSArretentDuPalierThermique[v.index]; + } + int operator()(const NumberStartingDispatchableUnits& v) const + { + return nativeOptimVar + .NumeroDeVariableDuNombreDeGroupesQuiDemarrentDuPalierThermique[v.index]; + } + int operator()(const NumberBreakingDownDispatchableUnits& v) const + { + return nativeOptimVar + .NumeroDeVariableDuNombreDeGroupesQuiTombentEnPanneDuPalierThermique[v.index]; + } + int operator()(const NTCDirect& v) const; + int operator()(const IntercoDirectCost& v) const + { + return nativeOptimVar.NumeroDeVariableCoutOrigineVersExtremiteDeLInterconnexion[v.index]; + } + int operator()(const IntercoIndirectCost& v) const + { + return nativeOptimVar.NumeroDeVariableCoutExtremiteVersOrigineDeLInterconnexion[v.index]; + } + int operator()(const ShortTermStorageInjection& v) const + { + return nativeOptimVar.SIM_ShortTermStorage.InjectionVariable[v.index]; + } + int operator()(const ShortTermStorageWithdrawal& v) const + { + return nativeOptimVar.SIM_ShortTermStorage.WithdrawalVariable[v.index]; + } + int operator()(const ShortTermStorageLevel& v) const + { + return nativeOptimVar.SIM_ShortTermStorage.LevelVariable[v.index]; + } + int operator()(const HydProd& v) const + { + return nativeOptimVar.NumeroDeVariablesDeLaProdHyd[v.index]; + } + int operator()(const HydProdDown& v) const + { + return nativeOptimVar.NumeroDeVariablesVariationHydALaBaisse[v.index]; + } + int operator()(const HydProdUp& v) const + { + return nativeOptimVar.NumeroDeVariablesVariationHydALaHausse[v.index]; + } + int operator()(const Pumping& v) const + { + return nativeOptimVar.NumeroDeVariablesDePompage[v.index]; + } + int operator()(const HydroLevel& v) const + { + return nativeOptimVar.NumeroDeVariablesDeNiveau[v.index]; + } + int operator()(const Overflow& v) const + { + return nativeOptimVar.NumeroDeVariablesDeDebordement[v.index]; + } + int operator()(const FinalStorage& v) const + { + return NumeroDeVariableStockFinal[v.index]; + } + int operator()(const LayerStorage& v) const + { + return NumeroDeVariableDeTrancheDeStock[v.area][v.layer]; + } + int operator()(const PositiveUnsuppliedEnergy& v) const + { + return nativeOptimVar.NumeroDeVariableDefaillancePositive[v.index]; + } + int operator()(const NegativeUnsuppliedEnergy& v) const + { + return nativeOptimVar.NumeroDeVariableDefaillanceNegative[v.index]; + } + +private: + const CORRESPONDANCES_DES_VARIABLES& nativeOptimVar; + const std::vector& NumeroDeVariableStockFinal; + const std::vector>& NumeroDeVariableDeTrancheDeStock; +}; +} // namespace Variable + +class ConstraintBuilderData +{ +public: + ConstraintBuilderData() = delete; + ConstraintBuilderData(const ConstraintBuilderData& other) = delete; + ConstraintBuilderData(ConstraintBuilderData&&) = delete; + + explicit ConstraintBuilderData(ConstraintBuilderData& data) : + Pi(data.Pi), + Colonne(data.Colonne), + nombreDeContraintes(data.nombreDeContraintes), + nombreDeTermesDansLaMatriceDeContrainte(data.nombreDeTermesDansLaMatriceDeContrainte), + IndicesDebutDeLigne(data.IndicesDebutDeLigne), + CoefficientsDeLaMatriceDesContraintes(data.CoefficientsDeLaMatriceDesContraintes), + IndicesColonnes(data.IndicesColonnes), + NombreDeTermesAllouesDansLaMatriceDesContraintes( + data.NombreDeTermesAllouesDansLaMatriceDesContraintes), + NombreDeTermesDesLignes(data.NombreDeTermesDesLignes), + Sens(data.Sens), + IncrementDAllocationMatriceDesContraintes(data.IncrementDAllocationMatriceDesContraintes), + CorrespondanceVarNativesVarOptim(data.CorrespondanceVarNativesVarOptim), + NombreDePasDeTempsPourUneOptimisation(data.NombreDePasDeTempsPourUneOptimisation), + NumeroDeVariableStockFinal(data.NumeroDeVariableStockFinal), + NumeroDeVariableDeTrancheDeStock(data.NumeroDeVariableDeTrancheDeStock), + NomDesContraintes(data.NomDesContraintes), + NamedProblems(data.NamedProblems), + NomsDesPays(data.NomsDesPays), + weekInTheYear(data.weekInTheYear), + NombreDePasDeTemps(data.NombreDePasDeTemps) + + { + } + + explicit ConstraintBuilderData( + std::vector& Pi, + std::vector& Colonne, + int& nombreDeContraintes, + int& nombreDeTermesDansLaMatriceDeContrainte, + std::vector& IndicesDebutDeLigne, + std::vector& CoefficientsDeLaMatriceDesContraintes, + std::vector& IndicesColonnes, + int& NombreDeTermesAllouesDansLaMatriceDesContraintes, + std::vector& NombreDeTermesDesLignes, + std::string& Sens, + int& IncrementDAllocationMatriceDesContraintes, + const std::vector& CorrespondanceVarNativesVarOptim, + const int32_t& NombreDePasDeTempsPourUneOptimisation, + const std::vector& NumeroDeVariableStockFinal, + const std::vector>& NumeroDeVariableDeTrancheDeStock, + std::vector& NomDesContraintes, + const bool& NamedProblems, + const std::vector& NomsDesPays, + const uint32_t& weekInTheYear, + const uint32_t& NombreDePasDeTemps); + + std::vector& Pi; + std::vector& Colonne; + int& nombreDeContraintes; + int& nombreDeTermesDansLaMatriceDeContrainte; + std::vector& IndicesDebutDeLigne; + std::vector& CoefficientsDeLaMatriceDesContraintes; + std::vector& IndicesColonnes; + int& NombreDeTermesAllouesDansLaMatriceDesContraintes; // TODO Check if ref is needed + std::vector& NombreDeTermesDesLignes; + std::string& Sens; + int& IncrementDAllocationMatriceDesContraintes; + const std::vector& CorrespondanceVarNativesVarOptim; + const int32_t& NombreDePasDeTempsPourUneOptimisation; + const std::vector& NumeroDeVariableStockFinal; + const std::vector>& NumeroDeVariableDeTrancheDeStock; + std::vector& NomDesContraintes; + const bool& NamedProblems; + const std::vector& NomsDesPays; + const uint32_t& weekInTheYear; + const uint32_t& NombreDePasDeTemps; +}; +class ConstraintBuilder +{ +public: + ConstraintBuilder() = delete; + ConstraintBuilder(const ConstraintBuilder& other) = delete; + ConstraintBuilder(ConstraintBuilder&&) = delete; + explicit ConstraintBuilder(ConstraintBuilder& other) : ConstraintBuilder(other.data) + { + } + explicit ConstraintBuilder(ConstraintBuilderData& data) : data(data) + { + } + + ConstraintBuilder& updateHourWithinWeek(unsigned hour) + { + hourInWeek_ = hour; + return *this; + } + +private: + int getVariableIndex(const Variable::Variant& variable, int shift, bool wrap, int delta) const; + +public: + ConstraintBuilder& include(Variable::Variant var, + double coeff, + int shift = 0, + bool wrap = false, + int delta = 0); + + ConstraintBuilder& operatorRHS(char op) + { + if (op == '<' || op == '=' || op == '>') + { + operator_ = op; + } + else + throw std::runtime_error("Invalid operator"); + + return *this; + } + + ConstraintBuilder& equalTo() + { + operator_ = '='; + return *this; + } + ConstraintBuilder& lessThan() + { + operator_ = '<'; + return *this; + } + ConstraintBuilder& greaterThan() + { + operator_ = '>'; + return *this; + } + + void build(); + int NumberOfVariables() const + { + return nombreDeTermes_; + } + +public: + ConstraintBuilderData& data; + +private: + void OPT_ChargerLaContrainteDansLaMatriceDesContraintes(); + + void OPT_AugmenterLaTailleDeLaMatriceDesContraintes(); + + unsigned int hourInWeek_ = 0; + + char operator_; + // double rhs_ = 0; + int nombreDeTermes_ = 0; + // ConstraintNamer ConstraintNameManager; +}; + +class Constraint +{ +public: + Constraint() = delete; + explicit Constraint(const Constraint& other) = delete; + explicit Constraint(ConstraintBuilder& builder) : builder(builder) + { + } + ConstraintBuilder& builder; +}; + +// #TODO move this function to a suitable place +// Helper functions +inline void exportPaliers(const PALIERS_THERMIQUES& PaliersThermiquesDuPays, + ConstraintBuilder& constraintBuilder) +{ + for (int index = 0; index < PaliersThermiquesDuPays.NombreDePaliersThermiques; index++) + { + const int palier + = PaliersThermiquesDuPays.NumeroDuPalierDansLEnsembleDesPaliersThermiques[index]; + constraintBuilder.include(Variable::DispatchableProduction(palier), -1.0); + } +} + +class BindingConstraintData +{ +public: + BindingConstraintData() = delete; + BindingConstraintData(const BindingConstraintData& other) = delete; + BindingConstraintData(BindingConstraintData&&) = delete; + BindingConstraintData(const char& TypeDeContrainteCouplante, + const int& NombreDInterconnexionsDansLaContrainteCouplante, + const std::vector& NumeroDeLInterconnexion, + const std::vector& PoidsDeLInterconnexion, + const std::vector& OffsetTemporelSurLInterco, + const int& NombreDePaliersDispatchDansLaContrainteCouplante, + const std::vector& PaysDuPalierDispatch, + const std::vector& NumeroDuPalierDispatch, + const std::vector& PoidsDuPalierDispatch, + const std::vector& OffsetTemporelSurLePalierDispatch, + const char& SensDeLaContrainteCouplante, + const char* const& NomDeLaContrainteCouplante, + const std::vector& PaliersThermiquesDuPays) : + + TypeDeContrainteCouplante(TypeDeContrainteCouplante), + NombreDInterconnexionsDansLaContrainteCouplante( + NombreDInterconnexionsDansLaContrainteCouplante), + NumeroDeLInterconnexion(NumeroDeLInterconnexion), + PoidsDeLInterconnexion(PoidsDeLInterconnexion), + OffsetTemporelSurLInterco(OffsetTemporelSurLInterco), + NombreDePaliersDispatchDansLaContrainteCouplante( + NombreDePaliersDispatchDansLaContrainteCouplante), + PaysDuPalierDispatch(PaysDuPalierDispatch), + NumeroDuPalierDispatch(NumeroDuPalierDispatch), + PoidsDuPalierDispatch(PoidsDuPalierDispatch), + OffsetTemporelSurLePalierDispatch(OffsetTemporelSurLePalierDispatch), + SensDeLaContrainteCouplante(SensDeLaContrainteCouplante), + NomDeLaContrainteCouplante(NomDeLaContrainteCouplante), + PaliersThermiquesDuPays(PaliersThermiquesDuPays) + { + } + BindingConstraintData(BindingConstraintData& data) : + + TypeDeContrainteCouplante(data.TypeDeContrainteCouplante), + NombreDInterconnexionsDansLaContrainteCouplante( + data.NombreDInterconnexionsDansLaContrainteCouplante), + NumeroDeLInterconnexion(data.NumeroDeLInterconnexion), + PoidsDeLInterconnexion(data.PoidsDeLInterconnexion), + OffsetTemporelSurLInterco(data.OffsetTemporelSurLInterco), + NombreDePaliersDispatchDansLaContrainteCouplante( + data.NombreDePaliersDispatchDansLaContrainteCouplante), + PaysDuPalierDispatch(data.PaysDuPalierDispatch), + NumeroDuPalierDispatch(data.NumeroDuPalierDispatch), + PoidsDuPalierDispatch(data.PoidsDuPalierDispatch), + OffsetTemporelSurLePalierDispatch(data.OffsetTemporelSurLePalierDispatch), + SensDeLaContrainteCouplante(data.SensDeLaContrainteCouplante), + NomDeLaContrainteCouplante(data.NomDeLaContrainteCouplante), + PaliersThermiquesDuPays(data.PaliersThermiquesDuPays) + { + } + + const char& TypeDeContrainteCouplante; + const int& NombreDInterconnexionsDansLaContrainteCouplante; + const std::vector& NumeroDeLInterconnexion; + const std::vector& PoidsDeLInterconnexion; + const std::vector& OffsetTemporelSurLInterco; + const int& NombreDePaliersDispatchDansLaContrainteCouplante; + const std::vector& PaysDuPalierDispatch; + const std::vector& NumeroDuPalierDispatch; + const std::vector& PoidsDuPalierDispatch; + const std::vector& OffsetTemporelSurLePalierDispatch; + const char& SensDeLaContrainteCouplante; + const char* const& NomDeLaContrainteCouplante; + const std::vector& PaliersThermiquesDuPays; +}; + +struct StartUpCostsData +{ + const std::vector& PaliersThermiquesDuPays; +}; diff --git a/src/solver/optimisation/constraint_builder_utils.cpp b/src/solver/optimisation/constraint_builder_utils.cpp new file mode 100644 index 0000000000..7421b45ee3 --- /dev/null +++ b/src/solver/optimisation/constraint_builder_utils.cpp @@ -0,0 +1,29 @@ +#include "constraint_builder_utils.h" + +ConstraintBuilder GetConstraintBuilderFromProblemHebdoAndProblemAResoudre( + const PROBLEME_HEBDO* problemeHebdo, + PROBLEME_ANTARES_A_RESOUDRE* ProblemeAResoudre) +{ + ConstraintBuilderData data(ProblemeAResoudre->Pi, + ProblemeAResoudre->Colonne, + ProblemeAResoudre->NombreDeContraintes, + ProblemeAResoudre->NombreDeTermesDansLaMatriceDesContraintes, + ProblemeAResoudre->IndicesDebutDeLigne, + ProblemeAResoudre->CoefficientsDeLaMatriceDesContraintes, + ProblemeAResoudre->IndicesColonnes, + ProblemeAResoudre->NombreDeTermesAllouesDansLaMatriceDesContraintes, + ProblemeAResoudre->NombreDeTermesDesLignes, + ProblemeAResoudre->Sens, + ProblemeAResoudre->IncrementDAllocationMatriceDesContraintes, + problemeHebdo->CorrespondanceVarNativesVarOptim, + problemeHebdo->NombreDePasDeTempsPourUneOptimisation, + problemeHebdo->NumeroDeVariableStockFinal, + problemeHebdo->NumeroDeVariableDeTrancheDeStock, + ProblemeAResoudre->NomDesContraintes, + problemeHebdo->NamedProblems, + problemeHebdo->NomsDesPays, + problemeHebdo->weekInTheYear, + problemeHebdo->NombreDePasDeTemps); + + return ConstraintBuilder(data); +} \ No newline at end of file diff --git a/src/solver/optimisation/constraint_builder_utils.h b/src/solver/optimisation/constraint_builder_utils.h new file mode 100644 index 0000000000..d76513a5a3 --- /dev/null +++ b/src/solver/optimisation/constraint_builder_utils.h @@ -0,0 +1,12 @@ +#pragma once +#include "constraint_builder.h" +ConstraintBuilder GetConstraintBuilderFromProblemHebdoAndProblemAResoudre( + const PROBLEME_HEBDO* problemeHebdo, + PROBLEME_ANTARES_A_RESOUDRE* ProblemeAResoudre); + +inline ConstraintBuilder GetConstraintBuilderFromProblemHebdo(PROBLEME_HEBDO* problemeHebdo) +{ + PROBLEME_ANTARES_A_RESOUDRE* ProblemeAResoudre = problemeHebdo->ProblemeAResoudre.get(); + return GetConstraintBuilderFromProblemHebdoAndProblemAResoudre(problemeHebdo, + ProblemeAResoudre); +} diff --git a/src/solver/optimisation/opt_alloc_probleme_a_optimiser.cpp b/src/solver/optimisation/opt_alloc_probleme_a_optimiser.cpp index 968dcb3f49..79a20488ac 100644 --- a/src/solver/optimisation/opt_alloc_probleme_a_optimiser.cpp +++ b/src/solver/optimisation/opt_alloc_probleme_a_optimiser.cpp @@ -158,20 +158,3 @@ void OPT_AllocDuProblemeAOptimiser(PROBLEME_HEBDO* problemeHebdo) optimisationAllocateProblem(problemeHebdo, mxPaliers); } - -void OPT_AugmenterLaTailleDeLaMatriceDesContraintes(PROBLEME_ANTARES_A_RESOUDRE* ProblemeAResoudre) -{ - int NbTermes = ProblemeAResoudre->NombreDeTermesAllouesDansLaMatriceDesContraintes; - NbTermes += ProblemeAResoudre->IncrementDAllocationMatriceDesContraintes; - - logs.info(); - logs.info() << " Expected Number of Non-zero terms in Problem Matrix : increased to : " - << NbTermes; - logs.info(); - - ProblemeAResoudre->CoefficientsDeLaMatriceDesContraintes.resize(NbTermes); - - ProblemeAResoudre->IndicesColonnes.resize(NbTermes); - - ProblemeAResoudre->NombreDeTermesAllouesDansLaMatriceDesContraintes = NbTermes; -} diff --git a/src/solver/optimisation/opt_construction_contraintes_couts_demarrage.cpp b/src/solver/optimisation/opt_construction_contraintes_couts_demarrage.cpp index 69f2f97f5d..bb88cc480c 100644 --- a/src/solver/optimisation/opt_construction_contraintes_couts_demarrage.cpp +++ b/src/solver/optimisation/opt_construction_contraintes_couts_demarrage.cpp @@ -32,6 +32,13 @@ #include "opt_fonctions.h" #include "opt_rename_problem.h" +#include "PMaxDispatchableGeneration.h" +#include "PMinDispatchableGeneration.h" +#include "ConsistenceNODU.h" +#include "NbUnitsOutageLessThanNbUnitsStop.h" +#include "NbDispUnitsMinBoundSinceMinUpTime.h" +#include "MinDownTime.h" +#include "constraint_builder_utils.h" using namespace Antares::Data; @@ -41,13 +48,17 @@ void OPT_ConstruireLaMatriceDesContraintesDuProblemeLineaireCoutsDeDemarrage( { PROBLEME_ANTARES_A_RESOUDRE* ProblemeAResoudre = problemeHebdo->ProblemeAResoudre.get(); + ConstraintBuilder builder = GetConstraintBuilderFromProblemHebdo(problemeHebdo); int nombreDePasDeTempsPourUneOptimisation = problemeHebdo->NombreDePasDeTempsPourUneOptimisation; - std::vector& Pi = ProblemeAResoudre->Pi; - std::vector& Colonne = ProblemeAResoudre->Colonne; + // std::vector& Pi = ProblemeAResoudre->Pi; + // std::vector& Colonne = ProblemeAResoudre->Colonne; ConstraintNamer constraintNamer(ProblemeAResoudre->NomDesContraintes, problemeHebdo->NamedProblems); + + StartUpCostsData startUpCostsData = {problemeHebdo->PaliersThermiquesDuPays}; + int nbTermesContraintesPourLesCoutsDeDemarrage = 0; for (uint32_t pays = 0; pays < problemeHebdo->NombreDePays; pays++) { @@ -56,109 +67,22 @@ void OPT_ConstruireLaMatriceDesContraintesDuProblemeLineaireCoutsDeDemarrage( constraintNamer.UpdateArea(problemeHebdo->NomsDesPays[pays]); for (int index = 0; index < PaliersThermiquesDuPays.NombreDePaliersThermiques; index++) { - double pminDUnGroupeDuPalierThermique - = PaliersThermiquesDuPays.pminDUnGroupeDuPalierThermique[index]; - double pmaxDUnGroupeDuPalierThermique - = PaliersThermiquesDuPays.PmaxDUnGroupeDuPalierThermique[index]; + PMaxDispatchableGeneration pMaxDispatchableGeneration(builder); + PMinDispatchableGeneration pMinDispatchableGeneration(builder); const int palier = PaliersThermiquesDuPays.NumeroDuPalierDansLEnsembleDesPaliersThermiques[index]; for (int pdt = 0; pdt < nombreDePasDeTempsPourUneOptimisation; pdt++) { - auto timeStepInYear = problemeHebdo->weekInTheYear * 168 + pdt; - constraintNamer.UpdateTimeStep(timeStepInYear); - CORRESPONDANCES_DES_VARIABLES& CorrespondanceVarNativesVarOptim - = problemeHebdo->CorrespondanceVarNativesVarOptim[pdt]; - - int nombreDeTermes = 0; - - if (!Simulation) - { - int var - = CorrespondanceVarNativesVarOptim.NumeroDeVariableDuPalierThermique[palier]; - if (var >= 0) - { - Pi[nombreDeTermes] = 1.0; - Colonne[nombreDeTermes] = var; - nombreDeTermes++; - } - } - else - nbTermesContraintesPourLesCoutsDeDemarrage++; - - if (!Simulation) - { - int var - = CorrespondanceVarNativesVarOptim - .NumeroDeVariableDuNombreDeGroupesEnMarcheDuPalierThermique[palier]; - if (var >= 0) - { - Pi[nombreDeTermes] = -pmaxDUnGroupeDuPalierThermique; - Colonne[nombreDeTermes] = var; - nombreDeTermes++; - } - } - else - nbTermesContraintesPourLesCoutsDeDemarrage++; - - if (!Simulation) - { - if (nombreDeTermes > 0) - { - constraintNamer.PMaxDispatchableGeneration( - ProblemeAResoudre->NombreDeContraintes, - PaliersThermiquesDuPays.NomsDesPaliersThermiques[index]); - OPT_ChargerLaContrainteDansLaMatriceDesContraintes( - ProblemeAResoudre, Pi, Colonne, nombreDeTermes, '<'); - } - } - else - ProblemeAResoudre->NombreDeContraintes += 1; - - nombreDeTermes = 0; - - if (!Simulation) - { - int var - = CorrespondanceVarNativesVarOptim.NumeroDeVariableDuPalierThermique[palier]; - if (var >= 0) - { - Pi[nombreDeTermes] = 1.0; - Colonne[nombreDeTermes] = var; - nombreDeTermes++; - } - } - else - nbTermesContraintesPourLesCoutsDeDemarrage++; - - if (!Simulation) - { - int var - = CorrespondanceVarNativesVarOptim - .NumeroDeVariableDuNombreDeGroupesEnMarcheDuPalierThermique[palier]; - if (var >= 0) - { - Pi[nombreDeTermes] = -pminDUnGroupeDuPalierThermique; - Colonne[nombreDeTermes] = var; - nombreDeTermes++; - } - } - else - nbTermesContraintesPourLesCoutsDeDemarrage++; - - if (!Simulation) - { - if (nombreDeTermes > 0) - { - constraintNamer.PMinDispatchableGeneration( - ProblemeAResoudre->NombreDeContraintes, - PaliersThermiquesDuPays.NomsDesPaliersThermiques[index]); - OPT_ChargerLaContrainteDansLaMatriceDesContraintes( - ProblemeAResoudre, Pi, Colonne, nombreDeTermes, '>'); - } - } - else - ProblemeAResoudre->NombreDeContraintes += 1; + pMaxDispatchableGeneration.add( + pays, palier, index, pdt, Simulation, startUpCostsData); + nbTermesContraintesPourLesCoutsDeDemarrage + += pMaxDispatchableGeneration.nbTermesContraintesPourLesCoutsDeDemarrage; + + pMinDispatchableGeneration.add( + pays, palier, index, pdt, Simulation, startUpCostsData); + nbTermesContraintesPourLesCoutsDeDemarrage + += pMinDispatchableGeneration.nbTermesContraintesPourLesCoutsDeDemarrage; } } } @@ -175,91 +99,10 @@ void OPT_ConstruireLaMatriceDesContraintesDuProblemeLineaireCoutsDeDemarrage( for (int pdt = 0; pdt < nombreDePasDeTempsPourUneOptimisation; pdt++) { - auto timeStepInYear = problemeHebdo->weekInTheYear * 168 + pdt; - constraintNamer.UpdateTimeStep(timeStepInYear); - CORRESPONDANCES_DES_VARIABLES& CorrespondanceVarNativesVarOptim - = problemeHebdo->CorrespondanceVarNativesVarOptim[pdt]; - - int Pdtmoins1 = pdt - 1; - if (Pdtmoins1 < 0) - Pdtmoins1 = nombreDePasDeTempsPourUneOptimisation + Pdtmoins1; - CORRESPONDANCES_DES_VARIABLES& CorrespondanceVarNativesVarOptimTmoins1 - = problemeHebdo->CorrespondanceVarNativesVarOptim[Pdtmoins1]; - - int nombreDeTermes = 0; - if (!Simulation) - { - int var - = CorrespondanceVarNativesVarOptim - .NumeroDeVariableDuNombreDeGroupesEnMarcheDuPalierThermique[palier]; - if (var >= 0) - { - Pi[nombreDeTermes] = 1.0; - Colonne[nombreDeTermes] = var; - nombreDeTermes++; - } - } - else - nbTermesContraintesPourLesCoutsDeDemarrage++; - - if (!Simulation) - { - int var - = CorrespondanceVarNativesVarOptimTmoins1 - .NumeroDeVariableDuNombreDeGroupesEnMarcheDuPalierThermique[palier]; - if (var >= 0) - { - Pi[nombreDeTermes] = -1; - Colonne[nombreDeTermes] = var; - nombreDeTermes++; - } - } - else - nbTermesContraintesPourLesCoutsDeDemarrage++; - - if (!Simulation) - { - int var - = CorrespondanceVarNativesVarOptim - .NumeroDeVariableDuNombreDeGroupesQuiDemarrentDuPalierThermique[palier]; - if (var >= 0) - { - Pi[nombreDeTermes] = -1; - Colonne[nombreDeTermes] = var; - nombreDeTermes++; - } - } - else - nbTermesContraintesPourLesCoutsDeDemarrage++; - - if (!Simulation) - { - int var - = CorrespondanceVarNativesVarOptim - .NumeroDeVariableDuNombreDeGroupesQuiSArretentDuPalierThermique[palier]; - if (var >= 0) - { - Pi[nombreDeTermes] = 1; - Colonne[nombreDeTermes] = var; - nombreDeTermes++; - } - } - else - nbTermesContraintesPourLesCoutsDeDemarrage++; - - if (!Simulation) - { - if (nombreDeTermes > 0) - { - constraintNamer.ConsistenceNODU( - ProblemeAResoudre->NombreDeContraintes, - PaliersThermiquesDuPays.NomsDesPaliersThermiques[index]); - OPT_ChargerLaContrainteDansLaMatriceDesContraintes( - ProblemeAResoudre, Pi, Colonne, nombreDeTermes, '='); - } - } - else - ProblemeAResoudre->NombreDeContraintes += 1; + ConsistenceNODU consistenceNODU(builder); + consistenceNODU.add(pays, palier, index, pdt, Simulation, startUpCostsData); + nbTermesContraintesPourLesCoutsDeDemarrage + += consistenceNODU.nbTermesContraintesPourLesCoutsDeDemarrage; } } } @@ -268,6 +111,7 @@ void OPT_ConstruireLaMatriceDesContraintesDuProblemeLineaireCoutsDeDemarrage( { const PALIERS_THERMIQUES& PaliersThermiquesDuPays = problemeHebdo->PaliersThermiquesDuPays[pays]; + NbUnitsOutageLessThanNbUnitsStop nbUnitsOutageLessThanNbUnitsStop(builder); constraintNamer.UpdateArea(problemeHebdo->NomsDesPays[pays]); for (int index = 0; index < PaliersThermiquesDuPays.NombreDePaliersThermiques; index++) @@ -277,59 +121,16 @@ void OPT_ConstruireLaMatriceDesContraintesDuProblemeLineaireCoutsDeDemarrage( for (int pdt = 0; pdt < nombreDePasDeTempsPourUneOptimisation; pdt++) { - auto timeStepInYear = problemeHebdo->weekInTheYear * 168 + pdt; - constraintNamer.UpdateTimeStep(timeStepInYear); - CORRESPONDANCES_DES_CONTRAINTES& CorrespondanceCntNativesCntOptim - = problemeHebdo->CorrespondanceCntNativesCntOptim[pdt]; - CorrespondanceCntNativesCntOptim - .NumeroDeContrainteDesContraintesDeDureeMinDeMarche[palier] - = -1; - - int nombreDeTermes = 0; - if (!Simulation) - { - int var - = problemeHebdo->CorrespondanceVarNativesVarOptim[pdt] - .NumeroDeVariableDuNombreDeGroupesQuiTombentEnPanneDuPalierThermique - [palier]; - if (var >= 0) - { - Pi[nombreDeTermes] = 1.0; - Colonne[nombreDeTermes] = var; - nombreDeTermes++; - } - } - else - nbTermesContraintesPourLesCoutsDeDemarrage++; - - if (!Simulation) - { - int var - = problemeHebdo->CorrespondanceVarNativesVarOptim[pdt] - .NumeroDeVariableDuNombreDeGroupesQuiSArretentDuPalierThermique[palier]; - if (var >= 0) - { - Pi[nombreDeTermes] = -1.0; - Colonne[nombreDeTermes] = var; - nombreDeTermes++; - } - } - else - nbTermesContraintesPourLesCoutsDeDemarrage++; - - if (!Simulation) - { - if (nombreDeTermes > 0) - { - constraintNamer.NbUnitsOutageLessThanNbUnitsStop( - ProblemeAResoudre->NombreDeContraintes, - PaliersThermiquesDuPays.NomsDesPaliersThermiques[index]); - OPT_ChargerLaContrainteDansLaMatriceDesContraintes( - ProblemeAResoudre, Pi, Colonne, nombreDeTermes, '<'); - } - } - else - ProblemeAResoudre->NombreDeContraintes += 1; + // CORRESPONDANCES_DES_CONTRAINTES& CorrespondanceCntNativesCntOptim + // = problemeHebdo->CorrespondanceCntNativesCntOptim[pdt]; + NbUnitsOutageLessThanNbUnitsStopData nbUnitsOutageLessThanNbUnitsStopData + = {startUpCostsData.PaliersThermiquesDuPays, + problemeHebdo->CorrespondanceCntNativesCntOptim[pdt] + .NumeroDeContrainteDesContraintesDeDureeMinDeMarche}; + nbUnitsOutageLessThanNbUnitsStop.add( + pays, palier, index, pdt, Simulation, nbUnitsOutageLessThanNbUnitsStopData); + nbTermesContraintesPourLesCoutsDeDemarrage + += nbUnitsOutageLessThanNbUnitsStop.nbTermesContraintesPourLesCoutsDeDemarrage; } } } @@ -338,7 +139,7 @@ void OPT_ConstruireLaMatriceDesContraintesDuProblemeLineaireCoutsDeDemarrage( { const PALIERS_THERMIQUES& PaliersThermiquesDuPays = problemeHebdo->PaliersThermiquesDuPays[pays]; - + NbDispUnitsMinBoundSinceMinUpTime nbDispUnitsMinBoundSinceMinUpTime(builder); constraintNamer.UpdateArea(problemeHebdo->NomsDesPays[pays]); for (int index = 0; index < PaliersThermiquesDuPays.NombreDePaliersThermiques; index++) { @@ -351,86 +152,16 @@ void OPT_ConstruireLaMatriceDesContraintesDuProblemeLineaireCoutsDeDemarrage( for (int pdt = 0; pdt < nombreDePasDeTempsPourUneOptimisation; pdt++) { - auto timeStepInYear = problemeHebdo->weekInTheYear * 168 + pdt; - constraintNamer.UpdateTimeStep(timeStepInYear); - CORRESPONDANCES_DES_CONTRAINTES& CorrespondanceCntNativesCntOptim - = problemeHebdo->CorrespondanceCntNativesCntOptim[pdt]; - CorrespondanceCntNativesCntOptim - .NumeroDeContrainteDesContraintesDeDureeMinDeMarche[palier] - = -1; - - int nombreDeTermes = 0; - if (!Simulation) - { - int var - = problemeHebdo->CorrespondanceVarNativesVarOptim[pdt] - .NumeroDeVariableDuNombreDeGroupesEnMarcheDuPalierThermique[palier]; - if (var >= 0) - { - Pi[nombreDeTermes] = 1.0; - Colonne[nombreDeTermes] = var; - nombreDeTermes++; - } - } - else - nbTermesContraintesPourLesCoutsDeDemarrage++; - - for (int k = pdt - DureeMinimaleDeMarcheDUnGroupeDuPalierThermique + 1; k <= pdt; - k++) - { - int t1 = k; - if (t1 < 0) - t1 = nombreDePasDeTempsPourUneOptimisation + t1; - - if (!Simulation) - { - int var = problemeHebdo->CorrespondanceVarNativesVarOptim[t1] - .NumeroDeVariableDuNombreDeGroupesQuiDemarrentDuPalierThermique - [palier]; - if (var >= 0) - { - Pi[nombreDeTermes] = -1.0; - Colonne[nombreDeTermes] = var; - nombreDeTermes++; - } - } - else - nbTermesContraintesPourLesCoutsDeDemarrage++; - - if (!Simulation) - { - int var - = problemeHebdo->CorrespondanceVarNativesVarOptim[t1] - .NumeroDeVariableDuNombreDeGroupesQuiTombentEnPanneDuPalierThermique - [palier]; - if (var >= 0) - { - Pi[nombreDeTermes] = 1.0; - Colonne[nombreDeTermes] = var; - nombreDeTermes++; - } - } - else - nbTermesContraintesPourLesCoutsDeDemarrage++; - } - - if (!Simulation) - { - if (nombreDeTermes > 1) - { - CorrespondanceCntNativesCntOptim - .NumeroDeContrainteDesContraintesDeDureeMinDeMarche[palier] - = ProblemeAResoudre->NombreDeContraintes; - - constraintNamer.NbDispUnitsMinBoundSinceMinUpTime( - ProblemeAResoudre->NombreDeContraintes, - PaliersThermiquesDuPays.NomsDesPaliersThermiques[index]); - OPT_ChargerLaContrainteDansLaMatriceDesContraintes( - ProblemeAResoudre, Pi, Colonne, nombreDeTermes, '>'); - } - } - else - ProblemeAResoudre->NombreDeContraintes += 1; + // CORRESPONDANCES_DES_CONTRAINTES& CorrespondanceCntNativesCntOptim + // = problemeHebdo->CorrespondanceCntNativesCntOptim[pdt]; + NbDispUnitsMinBoundSinceMinUpTimeData nbDispUnitsMinBoundSinceMinUpTimeData + = {startUpCostsData.PaliersThermiquesDuPays, + problemeHebdo->CorrespondanceCntNativesCntOptim[pdt] + .NumeroDeContrainteDesContraintesDeDureeMinDeMarche}; + nbDispUnitsMinBoundSinceMinUpTime.add( + pays, palier, index, pdt, Simulation, nbDispUnitsMinBoundSinceMinUpTimeData); + nbTermesContraintesPourLesCoutsDeDemarrage + += nbDispUnitsMinBoundSinceMinUpTime.nbTermesContraintesPourLesCoutsDeDemarrage; } } } @@ -439,84 +170,24 @@ void OPT_ConstruireLaMatriceDesContraintesDuProblemeLineaireCoutsDeDemarrage( { const PALIERS_THERMIQUES& PaliersThermiquesDuPays = problemeHebdo->PaliersThermiquesDuPays[pays]; - - constraintNamer.UpdateArea(problemeHebdo->NomsDesPays[pays]); + MinDownTime minDownTime(builder); for (int index = 0; index < PaliersThermiquesDuPays.NombreDePaliersThermiques; index++) { - int DureeMinimaleDArretDUnGroupeDuPalierThermique - = PaliersThermiquesDuPays.DureeMinimaleDArretDUnGroupeDuPalierThermique[index]; const int palier = PaliersThermiquesDuPays.NumeroDuPalierDansLEnsembleDesPaliersThermiques[index]; for (int pdt = 0; pdt < nombreDePasDeTempsPourUneOptimisation; pdt++) { - auto timeStepInYear = problemeHebdo->weekInTheYear * 168 + pdt; - constraintNamer.UpdateTimeStep(timeStepInYear); - CORRESPONDANCES_DES_CONTRAINTES& CorrespondanceCntNativesCntOptim - = problemeHebdo->CorrespondanceCntNativesCntOptim[pdt]; - CorrespondanceCntNativesCntOptim - .NumeroDeContrainteDesContraintesDeDureeMinDArret[palier] - = -1; - - CORRESPONDANCES_DES_VARIABLES& CorrespondanceVarNativesVarOptim - = problemeHebdo->CorrespondanceVarNativesVarOptim[pdt]; - - int nombreDeTermes = 0; - if (!Simulation) - { - int var - = CorrespondanceVarNativesVarOptim - .NumeroDeVariableDuNombreDeGroupesEnMarcheDuPalierThermique[palier]; - if (var >= 0) - { - Pi[nombreDeTermes] = 1.0; - Colonne[nombreDeTermes] = var; - nombreDeTermes++; - } - } - else - nbTermesContraintesPourLesCoutsDeDemarrage++; - - for (int k = pdt - DureeMinimaleDArretDUnGroupeDuPalierThermique + 1; k <= pdt; k++) - { - int t1 = k; - if (t1 < 0) - t1 = nombreDePasDeTempsPourUneOptimisation + t1; - - const auto& CorrespondanceVarNativesVarOptim_t1 - = problemeHebdo->CorrespondanceVarNativesVarOptim[t1]; - if (!Simulation) - { - int var = CorrespondanceVarNativesVarOptim_t1 - .NumeroDeVariableDuNombreDeGroupesQuiSArretentDuPalierThermique - [palier]; - if (var >= 0) - { - Pi[nombreDeTermes] = 1.0; - Colonne[nombreDeTermes] = var; - nombreDeTermes++; - } - } - else - nbTermesContraintesPourLesCoutsDeDemarrage++; - } - if (!Simulation) - { - if (nombreDeTermes > 1) - { - CorrespondanceCntNativesCntOptim - .NumeroDeContrainteDesContraintesDeDureeMinDArret[palier] - = ProblemeAResoudre->NombreDeContraintes; - - constraintNamer.MinDownTime( - ProblemeAResoudre->NombreDeContraintes, - PaliersThermiquesDuPays.NomsDesPaliersThermiques[index]); - OPT_ChargerLaContrainteDansLaMatriceDesContraintes( - ProblemeAResoudre, Pi, Colonne, nombreDeTermes, '<'); - } - } - else - ProblemeAResoudre->NombreDeContraintes += 1; + // CORRESPONDANCES_DES_CONTRAINTES& CorrespondanceCntNativesCntOptim + // = problemeHebdo->CorrespondanceCntNativesCntOptim[pdt]; + MinDownTimeData minDownTimeData + = {startUpCostsData.PaliersThermiquesDuPays, + problemeHebdo->CorrespondanceCntNativesCntOptim[pdt] + .NumeroDeContrainteDesContraintesDeDureeMinDArret}; + + minDownTime.add(pays, palier, index, pdt, Simulation, minDownTimeData); + nbTermesContraintesPourLesCoutsDeDemarrage + += minDownTime.nbTermesContraintesPourLesCoutsDeDemarrage; } } } diff --git a/src/solver/optimisation/opt_construction_matrice_des_contraintes_cas_lineaire.cpp b/src/solver/optimisation/opt_construction_matrice_des_contraintes_cas_lineaire.cpp index d52fc1dbc2..01acc670f4 100644 --- a/src/solver/optimisation/opt_construction_matrice_des_contraintes_cas_lineaire.cpp +++ b/src/solver/optimisation/opt_construction_matrice_des_contraintes_cas_lineaire.cpp @@ -30,135 +30,177 @@ #include "opt_fonctions.h" #include "opt_rename_problem.h" #include "sim_structure_probleme_economique.h" +#include "AreaBalance.h" +#include "FictitiousLoad.h" +#include "ShortTermStorageLevel.h" +#include "FlowDissociation.h" +#include "BindingConstraintHour.h" +#include "BindingConstraintDay.h" +#include "BindingConstraintWeek.h" +#include "HydroPower.h" +#include "HydroPowerSmoothingUsingVariationSum.h" +#include "HydroPowerSmoothingUsingVariationMaxDown.h" +#include "HydroPowerSmoothingUsingVariationMaxUp.h" +#include "MinHydroPower.h" +#include "MaxHydroPower.h" +#include "MaxPumping.h" +#include "AreaHydroLevel.h" +#include "FinalStockEquivalent.h" +#include "FinalStockExpression.h" +#include "constraint_builder_utils.h" #include using namespace Antares::Data; - -void exportPaliers(const PROBLEME_HEBDO& problemeHebdo, - const CORRESPONDANCES_DES_VARIABLES& CorrespondanceVarNativesVarOptim, - int pays, - int& nombreDeTermes, - std::vector& Pi, - std::vector& Colonne) +static BindingConstraintData GetBindingConstraintDataFromProblemHebdo(PROBLEME_HEBDO* problemeHebdo, + int cntCouplante) { - const PALIERS_THERMIQUES& PaliersThermiquesDuPays = problemeHebdo.PaliersThermiquesDuPays[pays]; - - for (int index = 0; index < PaliersThermiquesDuPays.NombreDePaliersThermiques; index++) - { - const int palier - = PaliersThermiquesDuPays.NumeroDuPalierDansLEnsembleDesPaliersThermiques[index]; - int var = CorrespondanceVarNativesVarOptim.NumeroDeVariableDuPalierThermique[palier]; - if (var >= 0) - { - Pi[nombreDeTermes] = -1.0; - Colonne[nombreDeTermes] = var; - nombreDeTermes++; - } - } + const CONTRAINTES_COUPLANTES& MatriceDesContraintesCouplantes + = problemeHebdo->MatriceDesContraintesCouplantes[cntCouplante]; + return {MatriceDesContraintesCouplantes.TypeDeContrainteCouplante, + MatriceDesContraintesCouplantes.NombreDInterconnexionsDansLaContrainteCouplante, + MatriceDesContraintesCouplantes.NumeroDeLInterconnexion, + MatriceDesContraintesCouplantes.PoidsDeLInterconnexion, + MatriceDesContraintesCouplantes.OffsetTemporelSurLInterco, + MatriceDesContraintesCouplantes.NombreDePaliersDispatchDansLaContrainteCouplante, + MatriceDesContraintesCouplantes.PaysDuPalierDispatch, + MatriceDesContraintesCouplantes.NumeroDuPalierDispatch, + MatriceDesContraintesCouplantes.PoidsDuPalierDispatch, + MatriceDesContraintesCouplantes.OffsetTemporelSurLePalierDispatch, + MatriceDesContraintesCouplantes.SensDeLaContrainteCouplante, + MatriceDesContraintesCouplantes.NomDeLaContrainteCouplante, + problemeHebdo->PaliersThermiquesDuPays}; } -static void shortTermStorageBalance( - const ::ShortTermStorage::AREA_INPUT& shortTermStorageInput, - const CORRESPONDANCES_DES_VARIABLES& CorrespondanceVarNativesVarOptim, - int& nombreDeTermes, - std::vector& Pi, - std::vector& Colonne) +static BindingConstraintHourData GetBindingConstraintHourDataFromProblemHebdo( + PROBLEME_HEBDO* problemeHebdo, + int cntCouplante, + int pdt) { - for (const auto& storage : shortTermStorageInput) - { - const int clusterGlobalIndex = storage.clusterGlobalIndex; - if (const int varInjection = CorrespondanceVarNativesVarOptim.SIM_ShortTermStorage - .InjectionVariable[clusterGlobalIndex]; - varInjection >= 0) - { - Pi[nombreDeTermes] = 1.0; - Colonne[nombreDeTermes] = varInjection; - nombreDeTermes++; - } - - if (const int varWithdrawal = CorrespondanceVarNativesVarOptim.SIM_ShortTermStorage - .WithdrawalVariable[clusterGlobalIndex]; - varWithdrawal >= 0) - { - Pi[nombreDeTermes] = -1.0; - Colonne[nombreDeTermes] = varWithdrawal; - nombreDeTermes++; - } - } + const CONTRAINTES_COUPLANTES& MatriceDesContraintesCouplantes + = problemeHebdo->MatriceDesContraintesCouplantes[cntCouplante]; + + // CORRESPONDANCES_DES_CONTRAINTES& CorrespondanceCntNativesCntOptim + // = problemeHebdo->CorrespondanceCntNativesCntOptim[pdt]; + // BindingConstraintData data + // = GetBindingConstraintDataFromProblemHebdo(problemeHebdo, cntCouplante); + return BindingConstraintHourData( + MatriceDesContraintesCouplantes.TypeDeContrainteCouplante, + MatriceDesContraintesCouplantes.NombreDInterconnexionsDansLaContrainteCouplante, + MatriceDesContraintesCouplantes.NumeroDeLInterconnexion, + MatriceDesContraintesCouplantes.PoidsDeLInterconnexion, + MatriceDesContraintesCouplantes.OffsetTemporelSurLInterco, + MatriceDesContraintesCouplantes.NombreDePaliersDispatchDansLaContrainteCouplante, + MatriceDesContraintesCouplantes.PaysDuPalierDispatch, + MatriceDesContraintesCouplantes.NumeroDuPalierDispatch, + MatriceDesContraintesCouplantes.PoidsDuPalierDispatch, + MatriceDesContraintesCouplantes.OffsetTemporelSurLePalierDispatch, + MatriceDesContraintesCouplantes.SensDeLaContrainteCouplante, + MatriceDesContraintesCouplantes.NomDeLaContrainteCouplante, + problemeHebdo->PaliersThermiquesDuPays, + problemeHebdo->CorrespondanceCntNativesCntOptim[pdt] + .NumeroDeContrainteDesContraintesCouplantes); } -static void shortTermStorageLevels( - const ::ShortTermStorage::AREA_INPUT& shortTermStorageInput, - PROBLEME_ANTARES_A_RESOUDRE* ProblemeAResoudre, - CORRESPONDANCES_DES_CONTRAINTES& CorrespondanceCntNativesCntOptim, - std::vector& CorrespondanceVarNativesVarOptim, - std::vector& Pi, - std::vector& Colonne, - int nombreDePasDeTempsPourUneOptimisation, - int pdt, - ConstraintNamer& constraintNamer) +static BindingConstraintDayData GetBindingConstraintDayDataFromProblemHebdo( + PROBLEME_HEBDO* problemeHebdo, + int cntCouplante) { - const auto& VarOptimCurrent = CorrespondanceVarNativesVarOptim[pdt]; - // Cycle over the simulation period - const int timestepPrevious - = (pdt - 1 + nombreDePasDeTempsPourUneOptimisation) % nombreDePasDeTempsPourUneOptimisation; - const auto& VarOptimPrevious = CorrespondanceVarNativesVarOptim[timestepPrevious]; - for (auto& storage : shortTermStorageInput) - { - int nombreDeTermes = 0; - const int clusterGlobalIndex = storage.clusterGlobalIndex; - // L[h] - L[h-1] - efficiency * injection[h] + withdrawal[h] = inflows[h] - if (const int varLevel - = VarOptimCurrent.SIM_ShortTermStorage.LevelVariable[clusterGlobalIndex]; - varLevel >= 0) - { - Pi[nombreDeTermes] = 1.0; - Colonne[nombreDeTermes] = varLevel; - nombreDeTermes++; - } - - if (const int varLevel_previous - = VarOptimPrevious.SIM_ShortTermStorage.LevelVariable[clusterGlobalIndex]; - varLevel_previous >= 0) - { - Pi[nombreDeTermes] = -1.0; - Colonne[nombreDeTermes] = varLevel_previous; - nombreDeTermes++; - } + const CONTRAINTES_COUPLANTES& MatriceDesContraintesCouplantes + = problemeHebdo->MatriceDesContraintesCouplantes[cntCouplante]; + + // BindingConstraintData data + // = GetBindingConstraintDataFromProblemHebdo(problemeHebdo, cntCouplante); + // TODO transfrom std::vector into + // std::vector&>& + // std::vector> correspondanceCntNativesCntOptimJournalieres; + // std::transform(problemeHebdo->CorrespondanceCntNativesCntOptimJournalieres.begin(), + // problemeHebdo->CorrespondanceCntNativesCntOptimJournalieres.end(), + // std::back_inserter(correspondanceCntNativesCntOptimJournalieres), + // [](CORRESPONDANCES_DES_CONTRAINTES_JOURNALIERES& corr) -> std::vector& + // { return corr.NumeroDeContrainteDesContraintesCouplantes; }); + + return BindingConstraintDayData( + MatriceDesContraintesCouplantes.TypeDeContrainteCouplante, + MatriceDesContraintesCouplantes.NombreDInterconnexionsDansLaContrainteCouplante, + MatriceDesContraintesCouplantes.NumeroDeLInterconnexion, + MatriceDesContraintesCouplantes.PoidsDeLInterconnexion, + MatriceDesContraintesCouplantes.OffsetTemporelSurLInterco, + MatriceDesContraintesCouplantes.NombreDePaliersDispatchDansLaContrainteCouplante, + MatriceDesContraintesCouplantes.PaysDuPalierDispatch, + MatriceDesContraintesCouplantes.NumeroDuPalierDispatch, + MatriceDesContraintesCouplantes.PoidsDuPalierDispatch, + MatriceDesContraintesCouplantes.OffsetTemporelSurLePalierDispatch, + MatriceDesContraintesCouplantes.SensDeLaContrainteCouplante, + MatriceDesContraintesCouplantes.NomDeLaContrainteCouplante, + problemeHebdo->PaliersThermiquesDuPays, + problemeHebdo->CorrespondanceCntNativesCntOptimJournalieres, + problemeHebdo->NombreDePasDeTempsDUneJournee, + problemeHebdo->NumeroDeJourDuPasDeTemps); +} +static BindingConstraintWeekData GetBindingConstraintWeekDataFromProblemHebdo( + PROBLEME_HEBDO* problemeHebdo, + int cntCouplante) +{ + const CONTRAINTES_COUPLANTES& MatriceDesContraintesCouplantes + = problemeHebdo->MatriceDesContraintesCouplantes[cntCouplante]; + + // BindingConstraintData data + // = GetBindingConstraintDataFromProblemHebdo(problemeHebdo, cntCouplante); + + return BindingConstraintWeekData( + MatriceDesContraintesCouplantes.TypeDeContrainteCouplante, + MatriceDesContraintesCouplantes.NombreDInterconnexionsDansLaContrainteCouplante, + MatriceDesContraintesCouplantes.NumeroDeLInterconnexion, + MatriceDesContraintesCouplantes.PoidsDeLInterconnexion, + MatriceDesContraintesCouplantes.OffsetTemporelSurLInterco, + MatriceDesContraintesCouplantes.NombreDePaliersDispatchDansLaContrainteCouplante, + MatriceDesContraintesCouplantes.PaysDuPalierDispatch, + MatriceDesContraintesCouplantes.NumeroDuPalierDispatch, + MatriceDesContraintesCouplantes.PoidsDuPalierDispatch, + MatriceDesContraintesCouplantes.OffsetTemporelSurLePalierDispatch, + MatriceDesContraintesCouplantes.SensDeLaContrainteCouplante, + MatriceDesContraintesCouplantes.NomDeLaContrainteCouplante, + problemeHebdo->PaliersThermiquesDuPays, + problemeHebdo->CorrespondanceCntNativesCntOptimHebdomadaires + .NumeroDeContrainteDesContraintesCouplantes); +} - if (const int varInjection - = VarOptimCurrent.SIM_ShortTermStorage.InjectionVariable[clusterGlobalIndex]; - varInjection >= 0) - { - Pi[nombreDeTermes] = -1.0 * storage.efficiency; - Colonne[nombreDeTermes] = varInjection; - nombreDeTermes++; - } +static HydroPowerData GetHydroPowerDataFromProblemHebdo(PROBLEME_HEBDO* problemeHebdo, + uint32_t pays) +{ + return {problemeHebdo->CaracteristiquesHydrauliques[pays].PresenceDHydrauliqueModulable, + problemeHebdo->CaracteristiquesHydrauliques[pays].TurbinageEntreBornes, + problemeHebdo->CaracteristiquesHydrauliques[pays].PresenceDePompageModulable, + problemeHebdo->NombreDePasDeTempsPourUneOptimisation, + problemeHebdo->NumeroDeContrainteEnergieHydraulique, + problemeHebdo->CaracteristiquesHydrauliques[pays].PumpingRatio}; +} - if (const int varWithdrawal - = VarOptimCurrent.SIM_ShortTermStorage.WithdrawalVariable[clusterGlobalIndex]; - varWithdrawal >= 0) - { - Pi[nombreDeTermes] = 1.0; - Colonne[nombreDeTermes] = varWithdrawal; - nombreDeTermes++; - } - CorrespondanceCntNativesCntOptim.ShortTermStorageLevelConstraint[clusterGlobalIndex] - = ProblemeAResoudre->NombreDeContraintes; +static MinHydroPowerData GetMinHydroPowerDataFromProblemHebdo(PROBLEME_HEBDO* problemeHebdo, + uint32_t pays) +{ + return {problemeHebdo->CaracteristiquesHydrauliques[pays].PresenceDHydrauliqueModulable, + problemeHebdo->CaracteristiquesHydrauliques[pays].TurbinageEntreBornes, + problemeHebdo->CaracteristiquesHydrauliques[pays].PresenceDePompageModulable, + problemeHebdo->NombreDePasDeTempsPourUneOptimisation, + problemeHebdo->NumeroDeContrainteMinEnergieHydraulique}; +} - constraintNamer.ShortTermStorageLevel(ProblemeAResoudre->NombreDeContraintes, storage.name); - OPT_ChargerLaContrainteDansLaMatriceDesContraintes( - ProblemeAResoudre, Pi, Colonne, nombreDeTermes, '='); - } +static MaxHydroPowerData GetMaxHydroPowerDataFromProblemHebdo(PROBLEME_HEBDO* problemeHebdo, + uint32_t pays) +{ + return {problemeHebdo->CaracteristiquesHydrauliques[pays].PresenceDHydrauliqueModulable, + problemeHebdo->CaracteristiquesHydrauliques[pays].TurbinageEntreBornes, + problemeHebdo->CaracteristiquesHydrauliques[pays].PresenceDePompageModulable, + problemeHebdo->NombreDePasDeTempsPourUneOptimisation, + problemeHebdo->NumeroDeContrainteMaxEnergieHydraulique}; } void OPT_ConstruireLaMatriceDesContraintesDuProblemeLineaire(PROBLEME_HEBDO* problemeHebdo, Solver::IResultWriter& writer) { int var; - const bool exportStructure = problemeHebdo->ExportStructure; - const bool firstWeekOfSimulation = problemeHebdo->firstWeekOfSimulation; PROBLEME_ANTARES_A_RESOUDRE* ProblemeAResoudre = problemeHebdo->ProblemeAResoudre.get(); @@ -166,538 +208,117 @@ void OPT_ConstruireLaMatriceDesContraintesDuProblemeLineaire(PROBLEME_HEBDO* pro int nombreDePasDeTempsPourUneOptimisation = problemeHebdo->NombreDePasDeTempsPourUneOptimisation; - std::vector& Pi = ProblemeAResoudre->Pi; - std::vector& Colonne = ProblemeAResoudre->Colonne; + // std::vector& Pi = ProblemeAResoudre->Pi; + // std::vector& Colonne = ProblemeAResoudre->Colonne; ProblemeAResoudre->NombreDeContraintes = 0; ProblemeAResoudre->NombreDeTermesDansLaMatriceDesContraintes = 0; ConstraintNamer constraintNamer(ProblemeAResoudre->NomDesContraintes, problemeHebdo->NamedProblems); + ConstraintBuilder builder = GetConstraintBuilderFromProblemHebdo(problemeHebdo); + AreaBalance areaBalance = AreaBalance(builder); + + FictitiousLoad fictitiousLoad(builder); + ShortTermStorageLevel shortTermStorageLevel(builder); + FlowDissociation flowDissociation(builder); + BindingConstraintHour bindingConstraintHour(builder); + BindingConstraintDay bindingConstraintDay(builder); + BindingConstraintWeek bindingConstraintWeek(builder); + HydroPower hydroPower(builder); + HydroPowerSmoothingUsingVariationSum hydroPowerSmoothingUsingVariationSum(builder); + HydroPowerSmoothingUsingVariationMaxDown hydroPowerSmoothingUsingVariationMaxDown(builder); + HydroPowerSmoothingUsingVariationMaxUp hydroPowerSmoothingUsingVariationMaxUp(builder); + + MinHydroPower minHydroPower(builder); + MaxHydroPower maxHydroPower(builder); + + MaxPumping maxPumping(builder); + + AreaHydroLevel areaHydroLevel(builder); + + FinalStockEquivalent finalStockEquivalent(builder); + FinalStockExpression finalStockExpression(builder); for (int pdt = 0; pdt < nombreDePasDeTempsPourUneOptimisation; pdt++) { int timeStepInYear = problemeHebdo->weekInTheYear * 168 + pdt; constraintNamer.UpdateTimeStep(timeStepInYear); - CORRESPONDANCES_DES_VARIABLES& CorrespondanceVarNativesVarOptim = problemeHebdo->CorrespondanceVarNativesVarOptim[pdt]; - CORRESPONDANCES_DES_CONTRAINTES& CorrespondanceCntNativesCntOptim - = problemeHebdo->CorrespondanceCntNativesCntOptim[pdt]; + // CORRESPONDANCES_DES_CONTRAINTES& CorrespondanceCntNativesCntOptim + // = problemeHebdo->CorrespondanceCntNativesCntOptim[pdt]; for (uint32_t pays = 0; pays < problemeHebdo->NombreDePays; pays++) { - int nombreDeTermes = 0; - - int interco = problemeHebdo->IndexDebutIntercoOrigine[pays]; - constraintNamer.UpdateArea(problemeHebdo->NomsDesPays[pays]); - - while (interco >= 0) - { - var = CorrespondanceVarNativesVarOptim.NumeroDeVariableDeLInterconnexion[interco]; - if (var >= 0) - { - Pi[nombreDeTermes] = 1.0; - Colonne[nombreDeTermes] = var; - nombreDeTermes++; - } - interco = problemeHebdo->IndexSuivantIntercoOrigine[interco]; - } - interco = problemeHebdo->IndexDebutIntercoExtremite[pays]; - while (interco >= 0) - { - var = CorrespondanceVarNativesVarOptim.NumeroDeVariableDeLInterconnexion[interco]; - if (var >= 0) - { - Pi[nombreDeTermes] = -1.0; - Colonne[nombreDeTermes] = var; - nombreDeTermes++; - } - interco = problemeHebdo->IndexSuivantIntercoExtremite[interco]; - } - - exportPaliers( - *problemeHebdo, CorrespondanceVarNativesVarOptim, pays, nombreDeTermes, Pi, Colonne); - - var = CorrespondanceVarNativesVarOptim.NumeroDeVariablesDeLaProdHyd[pays]; - if (var >= 0) - { - Pi[nombreDeTermes] = -1.0; - Colonne[nombreDeTermes] = var; - nombreDeTermes++; - } - - var = CorrespondanceVarNativesVarOptim.NumeroDeVariablesDePompage[pays]; - if (var >= 0) - { - Pi[nombreDeTermes] = 1.0; - Colonne[nombreDeTermes] = var; - nombreDeTermes++; - } - - var = CorrespondanceVarNativesVarOptim.NumeroDeVariableDefaillancePositive[pays]; - if (var >= 0) - { - Pi[nombreDeTermes] = -1.0; - Colonne[nombreDeTermes] = var; - nombreDeTermes++; - } - var = CorrespondanceVarNativesVarOptim.NumeroDeVariableDefaillanceNegative[pays]; - if (var >= 0) - { - Pi[nombreDeTermes] = 1.0; - Colonne[nombreDeTermes] = var; - nombreDeTermes++; - } - - shortTermStorageBalance(problemeHebdo->ShortTermStorage[pays], - CorrespondanceVarNativesVarOptim, - nombreDeTermes, - Pi, - Colonne); - - CorrespondanceCntNativesCntOptim.NumeroDeContrainteDesBilansPays[pays] - = ProblemeAResoudre->NombreDeContraintes; - - constraintNamer.AreaBalance(ProblemeAResoudre->NombreDeContraintes); - OPT_ChargerLaContrainteDansLaMatriceDesContraintes( - ProblemeAResoudre, Pi, Colonne, nombreDeTermes, '='); - nombreDeTermes = 0; - - exportPaliers( - *problemeHebdo, CorrespondanceVarNativesVarOptim, pays, nombreDeTermes, Pi, Colonne); - var = CorrespondanceVarNativesVarOptim.NumeroDeVariablesDeLaProdHyd[pays]; - if (var >= 0) - { - Pi[nombreDeTermes] = -problemeHebdo->DefaillanceNegativeUtiliserHydro[pays]; - Colonne[nombreDeTermes] = var; - nombreDeTermes++; - } - - var = CorrespondanceVarNativesVarOptim.NumeroDeVariableDefaillanceNegative[pays]; - if (var >= 0) - { - Pi[nombreDeTermes] = 1.0; - Colonne[nombreDeTermes] = var; - nombreDeTermes++; - } - - CorrespondanceCntNativesCntOptim.NumeroDeContraintePourEviterLesChargesFictives[pays] - = ProblemeAResoudre->NombreDeContraintes; - - constraintNamer.FictiveLoads(ProblemeAResoudre->NombreDeContraintes); - OPT_ChargerLaContrainteDansLaMatriceDesContraintes( - ProblemeAResoudre, Pi, Colonne, nombreDeTermes, '<'); - // Short term storage - shortTermStorageLevels(problemeHebdo->ShortTermStorage[pays], - ProblemeAResoudre, - CorrespondanceCntNativesCntOptim, - problemeHebdo->CorrespondanceVarNativesVarOptim, - Pi, - Colonne, - nombreDePasDeTempsPourUneOptimisation, - pdt, - constraintNamer); + AreaBalanceData areaBalanceData( + problemeHebdo->CorrespondanceCntNativesCntOptim[pdt].NumeroDeContrainteDesBilansPays, + problemeHebdo->CorrespondanceVarNativesVarOptim[pdt] + .SIM_ShortTermStorage.InjectionVariable, + problemeHebdo->CorrespondanceVarNativesVarOptim[pdt] + .SIM_ShortTermStorage.WithdrawalVariable, + problemeHebdo->IndexDebutIntercoOrigine, + problemeHebdo->IndexSuivantIntercoOrigine, + problemeHebdo->IndexDebutIntercoExtremite, + problemeHebdo->IndexSuivantIntercoExtremite, + problemeHebdo->PaliersThermiquesDuPays[pays], + problemeHebdo->ShortTermStorage); + + areaBalance.add(pdt, pays, areaBalanceData); + + FictitiousLoadData fictitiousLoadData + = {problemeHebdo->CorrespondanceCntNativesCntOptim[pdt] + .NumeroDeContraintePourEviterLesChargesFictives, + problemeHebdo->PaliersThermiquesDuPays[pays], + problemeHebdo->DefaillanceNegativeUtiliserHydro}; + + fictitiousLoad.add(pdt, pays, fictitiousLoadData); + + ShortTermStorageLevelData shortTermStorageLevelData = { + problemeHebdo->CorrespondanceCntNativesCntOptim[pdt].ShortTermStorageLevelConstraint, + problemeHebdo->ShortTermStorage, + }; + shortTermStorageLevel.add(pdt, pays, shortTermStorageLevelData); } for (uint32_t interco = 0; interco < problemeHebdo->NombreDInterconnexions; interco++) { - if (problemeHebdo->CoutDeTransport[interco].IntercoGereeAvecDesCouts) - { - int nombreDeTermes = 0; - var = CorrespondanceVarNativesVarOptim.NumeroDeVariableDeLInterconnexion[interco]; - if (var >= 0) - { - Pi[nombreDeTermes] = 1.0; - Colonne[nombreDeTermes] = var; - nombreDeTermes++; - } - var = CorrespondanceVarNativesVarOptim - .NumeroDeVariableCoutOrigineVersExtremiteDeLInterconnexion[interco]; - if (var >= 0) - { - Pi[nombreDeTermes] = -1.0; - Colonne[nombreDeTermes] = var; - nombreDeTermes++; - } - var = CorrespondanceVarNativesVarOptim - .NumeroDeVariableCoutExtremiteVersOrigineDeLInterconnexion[interco]; - if (var >= 0) - { - Pi[nombreDeTermes] = 1.0; - Colonne[nombreDeTermes] = var; - nombreDeTermes++; - } - - CorrespondanceCntNativesCntOptim.NumeroDeContrainteDeDissociationDeFlux[interco] - = ProblemeAResoudre->NombreDeContraintes; - const auto origin - = problemeHebdo - ->NomsDesPays[problemeHebdo->PaysOrigineDeLInterconnexion[interco]]; - const auto destination - = problemeHebdo - ->NomsDesPays[problemeHebdo->PaysExtremiteDeLInterconnexion[interco]]; - constraintNamer.FlowDissociation( - ProblemeAResoudre->NombreDeContraintes, origin, destination); - OPT_ChargerLaContrainteDansLaMatriceDesContraintes( - ProblemeAResoudre, Pi, Colonne, nombreDeTermes, '='); - } + FlowDissociationData flowDissociationData + = {problemeHebdo->CorrespondanceCntNativesCntOptim[pdt] + .NumeroDeContrainteDeDissociationDeFlux, + problemeHebdo->CoutDeTransport, + problemeHebdo->PaysOrigineDeLInterconnexion, + problemeHebdo->PaysExtremiteDeLInterconnexion}; + + flowDissociation.add(pdt, interco, flowDissociationData); } - for (uint32_t cntCouplante = 0; cntCouplante < problemeHebdo->NombreDeContraintesCouplantes; cntCouplante++) { - const CONTRAINTES_COUPLANTES& MatriceDesContraintesCouplantes - = problemeHebdo->MatriceDesContraintesCouplantes[cntCouplante]; - - if (MatriceDesContraintesCouplantes.TypeDeContrainteCouplante != CONTRAINTE_HORAIRE) - continue; - - int nbInterco - = MatriceDesContraintesCouplantes.NombreDInterconnexionsDansLaContrainteCouplante; - int nombreDeTermes = 0; - for (int index = 0; index < nbInterco; index++) - { - int interco = MatriceDesContraintesCouplantes.NumeroDeLInterconnexion[index]; - double poids = MatriceDesContraintesCouplantes.PoidsDeLInterconnexion[index]; - int Offset = MatriceDesContraintesCouplantes.OffsetTemporelSurLInterco[index]; - int pdt1; - - if (Offset >= 0) - { - pdt1 = (pdt + Offset) % nombreDePasDeTempsPourUneOptimisation; - } - else - { - pdt1 = (pdt + Offset + problemeHebdo->NombreDePasDeTemps) - % nombreDePasDeTempsPourUneOptimisation; - } - - var = problemeHebdo->CorrespondanceVarNativesVarOptim[pdt1] - .NumeroDeVariableDeLInterconnexion[interco]; - - if (var >= 0) - { - Pi[nombreDeTermes] = poids; - Colonne[nombreDeTermes] = var; - nombreDeTermes++; - } - } - - int nbClusters - = MatriceDesContraintesCouplantes.NombreDePaliersDispatchDansLaContrainteCouplante; - for (int index = 0; index < nbClusters; index++) - { - int pays = MatriceDesContraintesCouplantes.PaysDuPalierDispatch[index]; - const PALIERS_THERMIQUES& PaliersThermiquesDuPays - = problemeHebdo->PaliersThermiquesDuPays[pays]; - const int palier - = PaliersThermiquesDuPays.NumeroDuPalierDansLEnsembleDesPaliersThermiques - [MatriceDesContraintesCouplantes.NumeroDuPalierDispatch[index]]; - double poids = MatriceDesContraintesCouplantes.PoidsDuPalierDispatch[index]; - int Offset - = MatriceDesContraintesCouplantes.OffsetTemporelSurLePalierDispatch[index]; - int pdt1; - if (Offset >= 0) - { - pdt1 = (pdt + Offset) % nombreDePasDeTempsPourUneOptimisation; - } - else - { - pdt1 = (pdt + Offset + problemeHebdo->NombreDePasDeTemps) - % nombreDePasDeTempsPourUneOptimisation; - } - - var = problemeHebdo->CorrespondanceVarNativesVarOptim[pdt1] - .NumeroDeVariableDuPalierThermique[palier]; - - if (var >= 0) - { - Pi[nombreDeTermes] = poids; - Colonne[nombreDeTermes] = var; - nombreDeTermes++; - } - } - CorrespondanceCntNativesCntOptim - .NumeroDeContrainteDesContraintesCouplantes[cntCouplante] - = ProblemeAResoudre->NombreDeContraintes; - - constraintNamer.BindingConstraintHour( - ProblemeAResoudre->NombreDeContraintes, - MatriceDesContraintesCouplantes.NomDeLaContrainteCouplante); - OPT_ChargerLaContrainteDansLaMatriceDesContraintes( - ProblemeAResoudre, - Pi, - Colonne, - nombreDeTermes, - MatriceDesContraintesCouplantes.SensDeLaContrainteCouplante); + auto data + = GetBindingConstraintHourDataFromProblemHebdo(problemeHebdo, cntCouplante, pdt); + bindingConstraintHour.add(pdt, cntCouplante, data); } } for (uint32_t cntCouplante = 0; cntCouplante < problemeHebdo->NombreDeContraintesCouplantes; cntCouplante++) { - const CONTRAINTES_COUPLANTES& MatriceDesContraintesCouplantes - = problemeHebdo->MatriceDesContraintesCouplantes[cntCouplante]; - if (MatriceDesContraintesCouplantes.TypeDeContrainteCouplante != CONTRAINTE_JOURNALIERE) - continue; - - int nbInterco - = MatriceDesContraintesCouplantes.NombreDInterconnexionsDansLaContrainteCouplante; - int nbClusters - = MatriceDesContraintesCouplantes.NombreDePaliersDispatchDansLaContrainteCouplante; - int pdtDebut = 0; - while (pdtDebut < nombreDePasDeTempsPourUneOptimisation) - { - int jour = problemeHebdo->NumeroDeJourDuPasDeTemps[pdtDebut]; - CORRESPONDANCES_DES_CONTRAINTES_JOURNALIERES& - CorrespondanceCntNativesCntOptimJournalieres - = problemeHebdo->CorrespondanceCntNativesCntOptimJournalieres[jour]; - int nombreDeTermes = 0; - - for (int index = 0; index < nbInterco; index++) - { - int interco = MatriceDesContraintesCouplantes.NumeroDeLInterconnexion[index]; - double poids = MatriceDesContraintesCouplantes.PoidsDeLInterconnexion[index]; - int Offset = MatriceDesContraintesCouplantes.OffsetTemporelSurLInterco[index]; - - for (int pdt = pdtDebut; pdt < pdtDebut + nombreDePasDeTempsDUneJournee; pdt++) - { - int pdt1; - if (Offset >= 0) - { - pdt1 = (pdt + Offset) % nombreDePasDeTempsPourUneOptimisation; - } - else - { - pdt1 = (pdt + Offset + problemeHebdo->NombreDePasDeTemps) - % nombreDePasDeTempsPourUneOptimisation; - } - - var = problemeHebdo->CorrespondanceVarNativesVarOptim[pdt1] - .NumeroDeVariableDeLInterconnexion[interco]; - if (var >= 0) - { - Pi[nombreDeTermes] = poids; - Colonne[nombreDeTermes] = var; - nombreDeTermes++; - } - } - } - - for (int index = 0; index < nbClusters; index++) - { - int pays = MatriceDesContraintesCouplantes.PaysDuPalierDispatch[index]; - const PALIERS_THERMIQUES& PaliersThermiquesDuPays - = problemeHebdo->PaliersThermiquesDuPays[pays]; - const int palier - = PaliersThermiquesDuPays.NumeroDuPalierDansLEnsembleDesPaliersThermiques - [MatriceDesContraintesCouplantes.NumeroDuPalierDispatch[index]]; - double poids = MatriceDesContraintesCouplantes.PoidsDuPalierDispatch[index]; - int Offset - = MatriceDesContraintesCouplantes.OffsetTemporelSurLePalierDispatch[index]; - - for (int pdt = pdtDebut; pdt < pdtDebut + nombreDePasDeTempsDUneJournee; pdt++) - { - int pdt1; - if (Offset >= 0) - { - pdt1 = (pdt + Offset) % nombreDePasDeTempsPourUneOptimisation; - } - else - { - pdt1 = (pdt + Offset + problemeHebdo->NombreDePasDeTemps) - % nombreDePasDeTempsPourUneOptimisation; - } - - var = problemeHebdo->CorrespondanceVarNativesVarOptim[pdt1] - .NumeroDeVariableDuPalierThermique[palier]; - if (var >= 0) - { - Pi[nombreDeTermes] = poids; - Colonne[nombreDeTermes] = var; - nombreDeTermes++; - } - } - } - - CorrespondanceCntNativesCntOptimJournalieres - .NumeroDeContrainteDesContraintesCouplantes[cntCouplante] - = ProblemeAResoudre->NombreDeContraintes; - - constraintNamer.UpdateTimeStep(jour); - constraintNamer.BindingConstraintDay( - ProblemeAResoudre->NombreDeContraintes, - MatriceDesContraintesCouplantes.NomDeLaContrainteCouplante); - OPT_ChargerLaContrainteDansLaMatriceDesContraintes( - ProblemeAResoudre, - Pi, - Colonne, - nombreDeTermes, - MatriceDesContraintesCouplantes.SensDeLaContrainteCouplante); - pdtDebut += nombreDePasDeTempsDUneJournee; - } + auto data = GetBindingConstraintDayDataFromProblemHebdo(problemeHebdo, cntCouplante); + bindingConstraintDay.add(cntCouplante, data); } if (nombreDePasDeTempsPourUneOptimisation > nombreDePasDeTempsDUneJournee) { - int semaine = problemeHebdo->weekInTheYear; - CORRESPONDANCES_DES_CONTRAINTES_HEBDOMADAIRES& CorrespondanceCntNativesCntOptimHebdomadaires - = problemeHebdo->CorrespondanceCntNativesCntOptimHebdomadaires; for (uint32_t cntCouplante = 0; cntCouplante < problemeHebdo->NombreDeContraintesCouplantes; cntCouplante++) { - const CONTRAINTES_COUPLANTES& MatriceDesContraintesCouplantes - = problemeHebdo->MatriceDesContraintesCouplantes[cntCouplante]; - if (MatriceDesContraintesCouplantes.TypeDeContrainteCouplante - != CONTRAINTE_HEBDOMADAIRE) - continue; - - int nbInterco - = MatriceDesContraintesCouplantes.NombreDInterconnexionsDansLaContrainteCouplante; - int nombreDeTermes = 0; - for (int index = 0; index < nbInterco; index++) - { - int interco = MatriceDesContraintesCouplantes.NumeroDeLInterconnexion[index]; - double poids = MatriceDesContraintesCouplantes.PoidsDeLInterconnexion[index]; - int Offset = MatriceDesContraintesCouplantes.OffsetTemporelSurLInterco[index]; - for (int pdt = 0; pdt < nombreDePasDeTempsPourUneOptimisation; pdt++) - { - int pdt1; - if (Offset >= 0) - { - pdt1 = (pdt + Offset) % nombreDePasDeTempsPourUneOptimisation; - } - else - { - pdt1 = (pdt + Offset + problemeHebdo->NombreDePasDeTemps) - % nombreDePasDeTempsPourUneOptimisation; - } - - var = problemeHebdo->CorrespondanceVarNativesVarOptim[pdt1] - .NumeroDeVariableDeLInterconnexion[interco]; - if (var >= 0) - { - Pi[nombreDeTermes] = poids; - Colonne[nombreDeTermes] = var; - nombreDeTermes++; - } - } - } - - int nbClusters - = MatriceDesContraintesCouplantes.NombreDePaliersDispatchDansLaContrainteCouplante; - for (int index = 0; index < nbClusters; index++) - { - int pays = MatriceDesContraintesCouplantes.PaysDuPalierDispatch[index]; - const PALIERS_THERMIQUES& PaliersThermiquesDuPays - = problemeHebdo->PaliersThermiquesDuPays[pays]; - const int palier - = PaliersThermiquesDuPays.NumeroDuPalierDansLEnsembleDesPaliersThermiques - [MatriceDesContraintesCouplantes.NumeroDuPalierDispatch[index]]; - double poids = MatriceDesContraintesCouplantes.PoidsDuPalierDispatch[index]; - int Offset - = MatriceDesContraintesCouplantes.OffsetTemporelSurLePalierDispatch[index]; - for (int pdt = 0; pdt < nombreDePasDeTempsPourUneOptimisation; pdt++) - { - int pdt1; - if (Offset >= 0) - { - pdt1 = (pdt + Offset) % nombreDePasDeTempsPourUneOptimisation; - } - else - { - pdt1 = (pdt + Offset + problemeHebdo->NombreDePasDeTemps) - % nombreDePasDeTempsPourUneOptimisation; - } - - var = problemeHebdo->CorrespondanceVarNativesVarOptim[pdt1] - .NumeroDeVariableDuPalierThermique[palier]; - if (var >= 0) - { - Pi[nombreDeTermes] = poids; - Colonne[nombreDeTermes] = var; - nombreDeTermes++; - } - } - } - - CorrespondanceCntNativesCntOptimHebdomadaires - .NumeroDeContrainteDesContraintesCouplantes[cntCouplante] - = ProblemeAResoudre->NombreDeContraintes; - - constraintNamer.UpdateTimeStep(semaine); - constraintNamer.BindingConstraintWeek( - ProblemeAResoudre->NombreDeContraintes, - MatriceDesContraintesCouplantes.NomDeLaContrainteCouplante); - OPT_ChargerLaContrainteDansLaMatriceDesContraintes( - ProblemeAResoudre, - Pi, - Colonne, - nombreDeTermes, - MatriceDesContraintesCouplantes.SensDeLaContrainteCouplante); + auto data = GetBindingConstraintWeekDataFromProblemHebdo(problemeHebdo, cntCouplante); + bindingConstraintWeek.add(cntCouplante, data); } } for (uint32_t pays = 0; pays < problemeHebdo->NombreDePays; pays++) { - constraintNamer.UpdateArea(problemeHebdo->NomsDesPays[pays]); - bool presenceHydro - = problemeHebdo->CaracteristiquesHydrauliques[pays].PresenceDHydrauliqueModulable; - bool TurbEntreBornes - = problemeHebdo->CaracteristiquesHydrauliques[pays].TurbinageEntreBornes; - bool presencePompage - = problemeHebdo->CaracteristiquesHydrauliques[pays].PresenceDePompageModulable; - - int nombreDeTermes = 0; - if (presenceHydro && !TurbEntreBornes) - { - if (presencePompage) - { - for (int pdt = 0; pdt < nombreDePasDeTempsPourUneOptimisation; pdt++) - { - var = problemeHebdo->CorrespondanceVarNativesVarOptim[pdt] - .NumeroDeVariablesDeLaProdHyd[pays]; - - if (var >= 0) - { - Pi[nombreDeTermes] = 1.0; - Colonne[nombreDeTermes] = var; - nombreDeTermes++; - } - var = problemeHebdo->CorrespondanceVarNativesVarOptim[pdt] - .NumeroDeVariablesDePompage[pays]; - if (var >= 0) - { - Pi[nombreDeTermes] - = problemeHebdo->CaracteristiquesHydrauliques[pays].PumpingRatio; - Pi[nombreDeTermes] *= -1.0; - Colonne[nombreDeTermes] = var; - nombreDeTermes++; - } - } - } - else - { - for (int pdt = 0; pdt < nombreDePasDeTempsPourUneOptimisation; pdt++) - { - var = problemeHebdo->CorrespondanceVarNativesVarOptim[pdt] - .NumeroDeVariablesDeLaProdHyd[pays]; - if (var >= 0) - { - Pi[nombreDeTermes] = 1.0; - Colonne[nombreDeTermes] = var; - nombreDeTermes++; - } - } - } - - problemeHebdo->NumeroDeContrainteEnergieHydraulique[pays] - = ProblemeAResoudre->NombreDeContraintes; - constraintNamer.UpdateTimeStep(problemeHebdo->weekInTheYear); - constraintNamer.HydroPower(ProblemeAResoudre->NombreDeContraintes); - OPT_ChargerLaContrainteDansLaMatriceDesContraintes( - ProblemeAResoudre, Pi, Colonne, nombreDeTermes, '='); - } - else - problemeHebdo->NumeroDeContrainteEnergieHydraulique[pays] = -1; + auto data = GetHydroPowerDataFromProblemHebdo(problemeHebdo, pays); + hydroPower.add(pays, data); } if (problemeHebdo->TypeDeLissageHydraulique == LISSAGE_HYDRAULIQUE_SUR_SOMME_DES_VARIATIONS) @@ -707,57 +328,8 @@ void OPT_ConstruireLaMatriceDesContraintesDuProblemeLineaire(PROBLEME_HEBDO* pro if (!problemeHebdo->CaracteristiquesHydrauliques[pays].PresenceDHydrauliqueModulable) continue; - constraintNamer.UpdateArea(problemeHebdo->NomsDesPays[pays]); - for (int pdt = 0; pdt < nombreDePasDeTempsPourUneOptimisation; pdt++) - { - int timeStepInYear = problemeHebdo->weekInTheYear * 168 + pdt; - constraintNamer.UpdateTimeStep(timeStepInYear); - const auto& CorrespondanceVarNativesVarOptim - = problemeHebdo->CorrespondanceVarNativesVarOptim[pdt]; - int nombreDeTermes = 0; - var = CorrespondanceVarNativesVarOptim.NumeroDeVariablesDeLaProdHyd[pays]; - if (var >= 0) - { - Pi[nombreDeTermes] = 1.0; - Colonne[nombreDeTermes] = var; - nombreDeTermes++; - } - int pdt1 = pdt + 1; - if (pdt1 >= nombreDePasDeTempsPourUneOptimisation) - pdt1 = 0; - - if (int var1 = problemeHebdo->CorrespondanceVarNativesVarOptim[pdt1] - .NumeroDeVariablesDeLaProdHyd[pays]; - var1 >= 0) - { - Pi[nombreDeTermes] = -1.0; - Colonne[nombreDeTermes] = var1; - nombreDeTermes++; - } - - if (int var2 = CorrespondanceVarNativesVarOptim - .NumeroDeVariablesVariationHydALaBaisse[pays]; - var2 >= 0) - { - Pi[nombreDeTermes] = -1.0; - Colonne[nombreDeTermes] = var2; - nombreDeTermes++; - } - - if (int var3 = CorrespondanceVarNativesVarOptim - .NumeroDeVariablesVariationHydALaHausse[pays]; - var3 >= 0) - { - Pi[nombreDeTermes] = 1.0; - Colonne[nombreDeTermes] = var3; - nombreDeTermes++; - } - - constraintNamer.HydroPowerSmoothingUsingVariationSum( - ProblemeAResoudre->NombreDeContraintes); - OPT_ChargerLaContrainteDansLaMatriceDesContraintes( - ProblemeAResoudre, Pi, Colonne, nombreDeTermes, '='); - } + hydroPowerSmoothingUsingVariationSum.add( + pays, problemeHebdo->NombreDePasDeTempsPourUneOptimisation); } } else if (problemeHebdo->TypeDeLissageHydraulique == LISSAGE_HYDRAULIQUE_SUR_VARIATION_MAX) @@ -770,287 +342,62 @@ void OPT_ConstruireLaMatriceDesContraintesDuProblemeLineaire(PROBLEME_HEBDO* pro constraintNamer.UpdateArea(problemeHebdo->NomsDesPays[pays]); for (int pdt = 0; pdt < nombreDePasDeTempsPourUneOptimisation; pdt++) { - int timeStepInYear = problemeHebdo->weekInTheYear * 168 + pdt; - constraintNamer.UpdateTimeStep(timeStepInYear); - const auto& CorrespondanceVarNativesVarOptim - = problemeHebdo->CorrespondanceVarNativesVarOptim[pdt]; - int nombreDeTermes = 0; - var = CorrespondanceVarNativesVarOptim.NumeroDeVariablesDeLaProdHyd[pays]; - if (var >= 0) - { - Pi[nombreDeTermes] = 1.0; - Colonne[nombreDeTermes] = var; - nombreDeTermes++; - } - int var1 = problemeHebdo->CorrespondanceVarNativesVarOptim[0] - .NumeroDeVariablesVariationHydALaBaisse[pays]; - if (var1 >= 0) - { - Pi[nombreDeTermes] = -1.0; - Colonne[nombreDeTermes] = var1; - nombreDeTermes++; - } - - constraintNamer.HydroPowerSmoothingUsingVariationMaxDown( - ProblemeAResoudre->NombreDeContraintes); - OPT_ChargerLaContrainteDansLaMatriceDesContraintes( - ProblemeAResoudre, Pi, Colonne, nombreDeTermes, '<'); - - nombreDeTermes = 0; - if (var >= 0) - { - Pi[nombreDeTermes] = 1.0; - Colonne[nombreDeTermes] = var; - nombreDeTermes++; - } - var1 = problemeHebdo->CorrespondanceVarNativesVarOptim[0] - .NumeroDeVariablesVariationHydALaHausse[pays]; - if (var1 >= 0) - { - Pi[nombreDeTermes] = -1.0; - Colonne[nombreDeTermes] = var1; - nombreDeTermes++; - } - - constraintNamer.HydroPowerSmoothingUsingVariationMaxUp( - ProblemeAResoudre->NombreDeContraintes); - OPT_ChargerLaContrainteDansLaMatriceDesContraintes( - ProblemeAResoudre, Pi, Colonne, nombreDeTermes, '>'); + hydroPowerSmoothingUsingVariationMaxDown.add(pays, pdt); + hydroPowerSmoothingUsingVariationMaxUp.add(pays, pdt); } } } for (uint32_t pays = 0; pays < problemeHebdo->NombreDePays; pays++) { - const bool presenceHydro - = problemeHebdo->CaracteristiquesHydrauliques[pays].PresenceDHydrauliqueModulable; - const bool presencePompage - = problemeHebdo->CaracteristiquesHydrauliques[pays].PresenceDePompageModulable; - const bool TurbEntreBornes - = problemeHebdo->CaracteristiquesHydrauliques[pays].TurbinageEntreBornes; - constraintNamer.UpdateArea(problemeHebdo->NomsDesPays[pays]); - if (presenceHydro && (TurbEntreBornes || presencePompage)) - { - int nombreDeTermes = 0; - for (int pdt = 0; pdt < nombreDePasDeTempsPourUneOptimisation; pdt++) - { - var = problemeHebdo->CorrespondanceVarNativesVarOptim[pdt] - .NumeroDeVariablesDeLaProdHyd[pays]; - if (var >= 0) - { - Pi[nombreDeTermes] = 1.0; - Colonne[nombreDeTermes] = var; - nombreDeTermes++; - } - } - - problemeHebdo->NumeroDeContrainteMinEnergieHydraulique[pays] - = ProblemeAResoudre->NombreDeContraintes; - constraintNamer.UpdateTimeStep(problemeHebdo->weekInTheYear); - constraintNamer.MinHydroPower(ProblemeAResoudre->NombreDeContraintes); - OPT_ChargerLaContrainteDansLaMatriceDesContraintes( - ProblemeAResoudre, Pi, Colonne, nombreDeTermes, '>'); - } - else - problemeHebdo->NumeroDeContrainteMinEnergieHydraulique[pays] = -1; + auto minHydroPowerData = GetMinHydroPowerDataFromProblemHebdo(problemeHebdo, pays); + minHydroPower.add(pays, minHydroPowerData); - if (presenceHydro - && (TurbEntreBornes - || problemeHebdo->CaracteristiquesHydrauliques[pays].PresenceDePompageModulable)) - { - int nombreDeTermes = 0; - for (int pdt = 0; pdt < nombreDePasDeTempsPourUneOptimisation; pdt++) - { - constraintNamer.UpdateTimeStep(problemeHebdo->weekInTheYear * 168 + pdt); - var = problemeHebdo->CorrespondanceVarNativesVarOptim[pdt] - .NumeroDeVariablesDeLaProdHyd[pays]; - if (var >= 0) - { - Pi[nombreDeTermes] = 1.0; - Colonne[nombreDeTermes] = var; - nombreDeTermes++; - } - } - - problemeHebdo->NumeroDeContrainteMaxEnergieHydraulique[pays] - = ProblemeAResoudre->NombreDeContraintes; - constraintNamer.UpdateTimeStep(problemeHebdo->weekInTheYear); - constraintNamer.MaxHydroPower(ProblemeAResoudre->NombreDeContraintes); - OPT_ChargerLaContrainteDansLaMatriceDesContraintes( - ProblemeAResoudre, Pi, Colonne, nombreDeTermes, '<'); - } - else - problemeHebdo->NumeroDeContrainteMaxEnergieHydraulique[pays] = -1; + auto maxHydroPowerData = GetMaxHydroPowerDataFromProblemHebdo(problemeHebdo, pays); + maxHydroPower.add(pays, maxHydroPowerData); } for (uint32_t pays = 0; pays < problemeHebdo->NombreDePays; pays++) { - constraintNamer.UpdateArea(problemeHebdo->NomsDesPays[pays]); - if (problemeHebdo->CaracteristiquesHydrauliques[pays].PresenceDePompageModulable) - { - int nombreDeTermes = 0; - for (int pdt = 0; pdt < nombreDePasDeTempsPourUneOptimisation; pdt++) - { - var = problemeHebdo->CorrespondanceVarNativesVarOptim[pdt] - .NumeroDeVariablesDePompage[pays]; - if (var >= 0) - { - Pi[nombreDeTermes] = 1.0; - Colonne[nombreDeTermes] = var; - nombreDeTermes++; - } - } - - problemeHebdo->NumeroDeContrainteMaxPompage[pays] - = ProblemeAResoudre->NombreDeContraintes; - - constraintNamer.UpdateTimeStep(problemeHebdo->weekInTheYear); - constraintNamer.MaxPumping(ProblemeAResoudre->NombreDeContraintes); - OPT_ChargerLaContrainteDansLaMatriceDesContraintes( - ProblemeAResoudre, Pi, Colonne, nombreDeTermes, '<'); - } - else - problemeHebdo->NumeroDeContrainteMaxPompage[pays] = -1; + MaxPumpingData data + = {problemeHebdo->CaracteristiquesHydrauliques[pays].PresenceDePompageModulable, + problemeHebdo->NumeroDeContrainteMaxPompage}; + maxPumping.add(pays, data); } for (int pdt = 0; pdt < nombreDePasDeTempsPourUneOptimisation; pdt++) { - const auto& CorrespondanceVarNativesVarOptim = problemeHebdo->CorrespondanceVarNativesVarOptim[pdt]; - CORRESPONDANCES_DES_CONTRAINTES& CorrespondanceCntNativesCntOptim - = problemeHebdo->CorrespondanceCntNativesCntOptim[pdt]; + // CORRESPONDANCES_DES_CONTRAINTES& CorrespondanceCntNativesCntOptim + // = problemeHebdo->CorrespondanceCntNativesCntOptim[pdt]; int timeStepInYear = problemeHebdo->weekInTheYear * 168 + pdt; constraintNamer.UpdateTimeStep(timeStepInYear); + for (uint32_t pays = 0; pays < problemeHebdo->NombreDePays; pays++) { - constraintNamer.UpdateArea(problemeHebdo->NomsDesPays[pays]); - if (problemeHebdo->CaracteristiquesHydrauliques[pays].SuiviNiveauHoraire) - { - int nombreDeTermes = 0; - - var = CorrespondanceVarNativesVarOptim.NumeroDeVariablesDeNiveau[pays]; - if (var >= 0) - { - Pi[nombreDeTermes] = 1.0; - Colonne[nombreDeTermes] = var; - nombreDeTermes++; - } - - if (pdt > 0) - { - int var1 = problemeHebdo->CorrespondanceVarNativesVarOptim[pdt - 1] - .NumeroDeVariablesDeNiveau[pays]; - if (var1 >= 0) - { - Pi[nombreDeTermes] = -1.0; - Colonne[nombreDeTermes] = var1; - nombreDeTermes++; - } - } - - var = CorrespondanceVarNativesVarOptim.NumeroDeVariablesDeLaProdHyd[pays]; - if (var >= 0) - { - Pi[nombreDeTermes] = 1.0; - Colonne[nombreDeTermes] = var; - nombreDeTermes++; - } - - var = CorrespondanceVarNativesVarOptim.NumeroDeVariablesDePompage[pays]; - if (var >= 0) - { - Pi[nombreDeTermes] - = problemeHebdo->CaracteristiquesHydrauliques[pays].PumpingRatio; - Pi[nombreDeTermes] *= -1; - Colonne[nombreDeTermes] = var; - nombreDeTermes++; - } - - var = CorrespondanceVarNativesVarOptim.NumeroDeVariablesDeDebordement[pays]; - if (var >= 0) - { - Pi[nombreDeTermes] = 1.; - Colonne[nombreDeTermes] = var; - nombreDeTermes++; - } - - CorrespondanceCntNativesCntOptim.NumeroDeContrainteDesNiveauxPays[pays] - = ProblemeAResoudre->NombreDeContraintes; - - constraintNamer.AreaHydroLevel(ProblemeAResoudre->NombreDeContraintes); - OPT_ChargerLaContrainteDansLaMatriceDesContraintes( - ProblemeAResoudre, Pi, Colonne, nombreDeTermes, '='); - } - else - CorrespondanceCntNativesCntOptim.NumeroDeContrainteDesNiveauxPays[pays] = -1; + AreaHydroLevelData data = { + problemeHebdo->CorrespondanceCntNativesCntOptim[pdt].NumeroDeContrainteDesNiveauxPays, + problemeHebdo->CaracteristiquesHydrauliques[pays].SuiviNiveauHoraire, + problemeHebdo->CaracteristiquesHydrauliques[pays].PumpingRatio}; + areaHydroLevel.add(pays, pdt, data); } } /* For each area with ad hoc properties, two possible sets of two additional constraints */ for (uint32_t pays = 0; pays < problemeHebdo->NombreDePays; pays++) { - const auto& week = problemeHebdo->weekInTheYear; - constraintNamer.UpdateArea(problemeHebdo->NomsDesPays[pays]); - constraintNamer.UpdateTimeStep(week * 168 + nombreDePasDeTempsPourUneOptimisation - 1); - - if (problemeHebdo->CaracteristiquesHydrauliques[pays].AccurateWaterValue - && problemeHebdo->CaracteristiquesHydrauliques[pays].DirectLevelAccess) - /* equivalence constraint : StockFinal- Niveau[T]= 0*/ - { - int nombreDeTermes = 0; - var = problemeHebdo->NumeroDeVariableStockFinal[pays]; - if (var >= 0) - { - Pi[nombreDeTermes] = 1.0; - Colonne[nombreDeTermes] = var; - nombreDeTermes++; - } - var = problemeHebdo - ->CorrespondanceVarNativesVarOptim[nombreDePasDeTempsPourUneOptimisation - 1] - .NumeroDeVariablesDeNiveau[pays]; - if (var >= 0) - { - Pi[nombreDeTermes] = -1.0; - Colonne[nombreDeTermes] = var; - nombreDeTermes++; - } - problemeHebdo->NumeroDeContrainteEquivalenceStockFinal[pays] - = ProblemeAResoudre->NombreDeContraintes; - - constraintNamer.FinalStockEquivalent(ProblemeAResoudre->NombreDeContraintes); - OPT_ChargerLaContrainteDansLaMatriceDesContraintes( - ProblemeAResoudre, Pi, Colonne, nombreDeTermes, '='); - } - if (problemeHebdo->CaracteristiquesHydrauliques[pays].AccurateWaterValue) - /* expression constraint : - StockFinal +sum (stocklayers) = 0*/ - { - int nombreDeTermes = 0; - var = problemeHebdo->NumeroDeVariableStockFinal[pays]; - if (var >= 0) - { - Pi[nombreDeTermes] = -1.0; - Colonne[nombreDeTermes] = var; - nombreDeTermes++; - } - for (int layerindex = 0; layerindex < 100; layerindex++) - { - var = problemeHebdo->NumeroDeVariableDeTrancheDeStock[pays][layerindex]; - - if (var >= 0) - { - Pi[nombreDeTermes] = 1.0; - Colonne[nombreDeTermes] = var; - nombreDeTermes++; - } - } - - problemeHebdo->NumeroDeContrainteExpressionStockFinal[pays] - = ProblemeAResoudre->NombreDeContraintes; - - constraintNamer.FinalStockExpression(ProblemeAResoudre->NombreDeContraintes); - OPT_ChargerLaContrainteDansLaMatriceDesContraintes( - ProblemeAResoudre, Pi, Colonne, nombreDeTermes, '='); - } + FinalStockEquivalentData finalStockEquivalentData + = {problemeHebdo->NombreDePasDeTempsPourUneOptimisation - 1, + problemeHebdo->CaracteristiquesHydrauliques[pays].AccurateWaterValue, + problemeHebdo->CaracteristiquesHydrauliques[pays].DirectLevelAccess, + problemeHebdo->NumeroDeContrainteEquivalenceStockFinal}; + finalStockEquivalent.add(pays, finalStockEquivalentData); + FinalStockExpressionData finalStockExpressionData + = {problemeHebdo->NombreDePasDeTempsPourUneOptimisation - 1, + problemeHebdo->CaracteristiquesHydrauliques[pays].AccurateWaterValue, + problemeHebdo->NumeroDeContrainteExpressionStockFinal}; + + finalStockExpression.add(pays, finalStockExpressionData); } if (problemeHebdo->OptimisationAvecCoutsDeDemarrage) @@ -1060,7 +407,7 @@ void OPT_ConstruireLaMatriceDesContraintesDuProblemeLineaire(PROBLEME_HEBDO* pro } // Export structure - if (exportStructure && firstWeekOfSimulation) + if (problemeHebdo->ExportStructure && problemeHebdo->firstWeekOfSimulation) { OPT_ExportInterco(writer, problemeHebdo); OPT_ExportAreaName(writer, problemeHebdo->NomsDesPays); diff --git a/src/solver/optimisation/opt_construction_matrice_des_contraintes_cas_quadratique.cpp b/src/solver/optimisation/opt_construction_matrice_des_contraintes_cas_quadratique.cpp index b3d7399045..5d6a35bceb 100644 --- a/src/solver/optimisation/opt_construction_matrice_des_contraintes_cas_quadratique.cpp +++ b/src/solver/optimisation/opt_construction_matrice_des_contraintes_cas_quadratique.cpp @@ -31,11 +31,48 @@ #include "../simulation/sim_structure_donnees.h" #include "../simulation/sim_extern_variables_globales.h" #include "opt_fonctions.h" +#include "constraint_builder.h" +#include "constraint_builder_utils.h" + +struct ExchangeBalanceData +{ + const std::vector& IndexDebutIntercoOrigine; + const std::vector& IndexSuivantIntercoOrigine; + const std::vector& IndexDebutIntercoExtremite; + const std::vector& IndexSuivantIntercoExtremite; + std::vector& NumeroDeContrainteDeSoldeDEchange; +}; + +class ExchangeBalance : private Constraint +{ +public: + using Constraint::Constraint; + void add(uint32_t pays, ExchangeBalanceData& data) + { + builder.updateHourWithinWeek(0); + + int interco = data.IndexDebutIntercoOrigine[pays]; + while (interco >= 0) + { + builder.include(Variable::IntercoDirectCost(interco), 1.0); + interco = data.IndexSuivantIntercoOrigine[interco]; + } + interco = data.IndexDebutIntercoExtremite[pays]; + while (interco >= 0) + { + builder.include(Variable::IntercoDirectCost(interco), -1.0); + + interco = data.IndexSuivantIntercoExtremite[interco]; + } + + data.NumeroDeContrainteDeSoldeDEchange[pays] = builder.data.nombreDeContraintes; + builder.build(); + } +}; void OPT_ConstruireLaMatriceDesContraintesDuProblemeQuadratique(PROBLEME_HEBDO* problemeHebdo) { PROBLEME_ANTARES_A_RESOUDRE* ProblemeAResoudre = problemeHebdo->ProblemeAResoudre.get(); - std::vector Pi(ProblemeAResoudre->NombreDeVariables, 0.); std::vector Colonne(ProblemeAResoudre->NombreDeVariables, 0); @@ -44,41 +81,17 @@ void OPT_ConstruireLaMatriceDesContraintesDuProblemeQuadratique(PROBLEME_HEBDO* const CORRESPONDANCES_DES_VARIABLES& correspondanceVarNativesVarOptim = problemeHebdo->CorrespondanceVarNativesVarOptim[0]; - for (uint32_t pays = 0; pays < problemeHebdo->NombreDePays - 1; pays++) - { - int nombreDeTermes = 0; + ConstraintBuilder builder(GetConstraintBuilderFromProblemHebdo(problemeHebdo)); - int interco = problemeHebdo->IndexDebutIntercoOrigine[pays]; - while (interco >= 0) - { - if (int var - = correspondanceVarNativesVarOptim.NumeroDeVariableDeLInterconnexion[interco]; - var >= 0) - { - Pi[nombreDeTermes] = 1.0; - Colonne[nombreDeTermes] = var; - nombreDeTermes++; - } - interco = problemeHebdo->IndexSuivantIntercoOrigine[interco]; - } - interco = problemeHebdo->IndexDebutIntercoExtremite[pays]; - while (interco >= 0) - { - if (int var - = correspondanceVarNativesVarOptim.NumeroDeVariableDeLInterconnexion[interco]; - var >= 0) - { - Pi[nombreDeTermes] = -1.0; - Colonne[nombreDeTermes] = var; - nombreDeTermes++; - } - interco = problemeHebdo->IndexSuivantIntercoExtremite[interco]; - } + ExchangeBalance exchangeBalance(builder); - problemeHebdo->NumeroDeContrainteDeSoldeDEchange[pays] - = ProblemeAResoudre->NombreDeContraintes; - - OPT_ChargerLaContrainteDansLaMatriceDesContraintes( - ProblemeAResoudre, Pi, Colonne, nombreDeTermes, '='); + ExchangeBalanceData data = {problemeHebdo->IndexDebutIntercoOrigine, + problemeHebdo->IndexSuivantIntercoOrigine, + problemeHebdo->IndexDebutIntercoExtremite, + problemeHebdo->IndexSuivantIntercoExtremite, + problemeHebdo->NumeroDeContrainteDeSoldeDEchange}; + for (uint32_t pays = 0; pays < problemeHebdo->NombreDePays - 1; pays++) + { + exchangeBalance.add(pays, data); } } diff --git a/src/solver/optimisation/opt_construction_matrice_des_contraintes_outils.cpp b/src/solver/optimisation/opt_construction_matrice_des_contraintes_outils.cpp index ecbb26cdf5..bd6d0c686f 100644 --- a/src/solver/optimisation/opt_construction_matrice_des_contraintes_outils.cpp +++ b/src/solver/optimisation/opt_construction_matrice_des_contraintes_outils.cpp @@ -30,32 +30,3 @@ #include "../simulation/sim_structure_donnees.h" #include "opt_fonctions.h" - -void OPT_ChargerLaContrainteDansLaMatriceDesContraintes( - PROBLEME_ANTARES_A_RESOUDRE* ProblemeAResoudre, - std::vector& Pi, - std::vector& Colonne, - int NombreDeTermesDeLaContrainte, - char SensContrainte) -{ - int& nombreDeTermes = ProblemeAResoudre->NombreDeTermesDansLaMatriceDesContraintes; - int& nombreDeContraintes = ProblemeAResoudre->NombreDeContraintes; - - ProblemeAResoudre->IndicesDebutDeLigne[nombreDeContraintes] = nombreDeTermes; - for (int i = 0; i < NombreDeTermesDeLaContrainte; i++) - { - ProblemeAResoudre->CoefficientsDeLaMatriceDesContraintes[nombreDeTermes] = Pi[i]; - ProblemeAResoudre->IndicesColonnes[nombreDeTermes] = Colonne[i]; - nombreDeTermes++; - if (nombreDeTermes == ProblemeAResoudre->NombreDeTermesAllouesDansLaMatriceDesContraintes) - { - OPT_AugmenterLaTailleDeLaMatriceDesContraintes(ProblemeAResoudre); - } - } - ProblemeAResoudre->NombreDeTermesDesLignes[nombreDeContraintes] = NombreDeTermesDeLaContrainte; - - ProblemeAResoudre->Sens[nombreDeContraintes] = SensContrainte; - nombreDeContraintes++; - - return; -} diff --git a/src/solver/optimisation/opt_fonctions.h b/src/solver/optimisation/opt_fonctions.h index e2807f0c8d..e097e4d0ae 100644 --- a/src/solver/optimisation/opt_fonctions.h +++ b/src/solver/optimisation/opt_fonctions.h @@ -34,6 +34,7 @@ #include "antares/study/parameters/adq-patch-params.h" #include "opt_structure_probleme_a_resoudre.h" #include +#include "constraint_builder.h" using AdqPatchParams = Antares::Data::AdequacyPatch::AdqPatchParams; using OptimizationOptions = Antares::Solver::Optimization::OptimizationOptions; @@ -102,11 +103,6 @@ void OPT_RestaurerLesDonnees(const PROBLEME_HEBDO*); void OPT_CalculerLesPminThermiquesEnFonctionDeMUTetMDT(PROBLEME_HEBDO*); double OPT_CalculerAireMaxPminJour(int, int, int, int, std::vector&, std::vector&); -void OPT_ChargerLaContrainteDansLaMatriceDesContraintes(PROBLEME_ANTARES_A_RESOUDRE*, - std::vector&, - std::vector&, - int, - char); void OPT_ChainagesDesIntercoPartantDUnNoeud(PROBLEME_HEBDO*); void OPT_AllocateFromNumberOfVariableConstraints(PROBLEME_ANTARES_A_RESOUDRE* ProblemeAResoudre, @@ -114,7 +110,6 @@ void OPT_AllocateFromNumberOfVariableConstraints(PROBLEME_ANTARES_A_RESOUDRE* Pr void OPT_FreeOptimizationData(PROBLEME_ANTARES_A_RESOUDRE* ProblemeAResoudre); void OPT_AllocDuProblemeAOptimiser(PROBLEME_HEBDO*); int OPT_DecompteDesVariablesEtDesContraintesDuProblemeAOptimiser(PROBLEME_HEBDO*); -void OPT_AugmenterLaTailleDeLaMatriceDesContraintes(PROBLEME_ANTARES_A_RESOUDRE*); /*------------------------------*/ diff --git a/src/solver/optimisation/opt_rename_problem.cpp b/src/solver/optimisation/opt_rename_problem.cpp index 0d90030460..54f774f085 100644 --- a/src/solver/optimisation/opt_rename_problem.cpp +++ b/src/solver/optimisation/opt_rename_problem.cpp @@ -215,6 +215,15 @@ void ConstraintNamer::FlowDissociation(unsigned int constraint, SetLinkElementName(constraint, "FlowDissociation"); } +void ConstraintNamer::CsrFlowDissociation(unsigned int constraint, + const std::string& origin, + const std::string& destination) +{ + origin_ = origin; + destination_ = destination; + SetLinkElementName(constraint, "CsrFlowDissociation"); +} + void ConstraintNamer::AreaBalance(unsigned int constraint) { SetAreaElementNameHour(constraint, "AreaBalance"); diff --git a/src/solver/optimisation/opt_rename_problem.h b/src/solver/optimisation/opt_rename_problem.h index 6c19a3e415..5cd8eeb6ad 100644 --- a/src/solver/optimisation/opt_rename_problem.h +++ b/src/solver/optimisation/opt_rename_problem.h @@ -110,6 +110,10 @@ class ConstraintNamer : public Namer void FlowDissociation(unsigned int constraint, const std::string& origin, const std::string& destination); + + void CsrFlowDissociation(unsigned int constraint, + const std::string& origin, + const std::string& destination); void AreaBalance(unsigned int constraint); void FictiveLoads(unsigned int constraint); void HydroPower(unsigned int constraint); diff --git a/src/solver/simulation/adequacy_patch_runtime_data.h b/src/solver/simulation/adequacy_patch_runtime_data.h index 62971f28a3..573e8b6e47 100644 --- a/src/solver/simulation/adequacy_patch_runtime_data.h +++ b/src/solver/simulation/adequacy_patch_runtime_data.h @@ -31,10 +31,11 @@ #include #include +using adqPatchParamsMode = Antares::Data::AdequacyPatch::AdequacyPatchMode; + class AdequacyPatchRuntimeData { private: - using adqPatchParamsMode = Antares::Data::AdequacyPatch::AdequacyPatchMode; std::vector> csrTriggeredHoursPerArea_; public: