diff --git a/src/format-code.sh b/src/format-code.sh
index e69de29bb2..abac85a423 100755
--- a/src/format-code.sh
+++ b/src/format-code.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+
+if [ $# -eq 0 ]
+then
+    # No arguments: format all
+    SOURCE_DIRS="analyzer/ libs/ solver/ tools/ config/ tests/ packaging/"
+    SOURCE_FILES=$(find $SOURCE_DIRS -regextype egrep -regex ".*/*\.(c|cxx|cpp|cc|h|hxx|hpp)$" ! -path '*/antlr-interface/*')
+else
+    # Format files provided as arguments
+    SOURCE_FILES="$@"
+fi
+
+# Remove ^M, etc.
+if ! [ -x "$(command -v dos2unix)" ]; then
+    echo 'Warning: dos2unix is not installed. Skipping' >&2
+else
+    echo "$SOURCE_FILES" | xargs dos2unix
+fi
+
+if ! [ -x "$(command -v clang-format)" ]; then
+    echo 'Warning: clang-format is not installed. Skipping' >&2
+else
+    echo "$SOURCE_FILES" | xargs clang-format -i --verbose
+fi
diff --git a/src/libs/antares/study/include/antares/study/area/area.h b/src/libs/antares/study/include/antares/study/area/area.h
index 59eaf54ecf..3496289b9a 100644
--- a/src/libs/antares/study/include/antares/study/area/area.h
+++ b/src/libs/antares/study/include/antares/study/area/area.h
@@ -43,10 +43,9 @@
 template<typename T>
 class BiMap
 {
-private:
     // Maps for both directions: key-to-value and value-to-key
-    std::map<int, T> key_to_value; // Map from key (int) to value (T)
-    std::map<T, int> value_to_key; // Map from value (T) to key (int)
+    std::map<int, T> key_to_value; //!< Map from key (int) to value (T)
+    std::map<T, int> value_to_key; //!< Map from value (T) to key (int)
 
 public:
     // Function to insert a key-value pair
@@ -65,12 +64,11 @@ class BiMap
     }
 
     // Function to get the value from the key
-    T get(int key) const
+    const T& get(int key) const
     {
-        auto it = key_to_value.find(key);
-        if (it != key_to_value.end())
+        if (key_to_value.count(key))
         {
-            return it->second; // Return the associated value if the key exists
+            return key_to_value.at(key); // Return the associated value if the key exists
         }
         throw std::out_of_range("This index is not in the BiMap");
     }
diff --git a/src/libs/antares/study/include/antares/study/parts/hydro/container.h b/src/libs/antares/study/include/antares/study/parts/hydro/container.h
index 9e2b299c08..1cfdcb86f3 100644
--- a/src/libs/antares/study/include/antares/study/parts/hydro/container.h
+++ b/src/libs/antares/study/include/antares/study/parts/hydro/container.h
@@ -172,13 +172,13 @@ class PartHydro
 
     std::optional<Data::ReserveName> reserveParticipationAt(const Area* area, unsigned int index) const;
 
-    //! \brief Returns max turbining power for a reserve if participating, -1 otherwise
+    //! Returns max turbining power for a reserve if participating, -1 otherwise
     float reserveMaxTurbining(Data::ReserveName name);
 
-    //! \brief Returns max pumping power for a reserve if participating, -1 otherwise
+    //! Returns max pumping power for a reserve if participating, -1 otherwise
     float reserveMaxPumping(Data::ReserveName name);
 
-    //! \brief Returns participating cost for a reserve if participating, -1 otherwise
+    //! Returns participating cost for a reserve if participating, -1 otherwise
     float reserveCost(Data::ReserveName name);
 
 
diff --git a/src/libs/antares/study/include/antares/study/parts/short-term-storage/properties.h b/src/libs/antares/study/include/antares/study/parts/short-term-storage/properties.h
index 6e11541e30..51b0568fc8 100644
--- a/src/libs/antares/study/include/antares/study/parts/short-term-storage/properties.h
+++ b/src/libs/antares/study/include/antares/study/parts/short-term-storage/properties.h
@@ -77,6 +77,9 @@ class Properties
     /// cluster name
     std::string name;
 
+    /// Cluster gloval index (across areas)
+    int clusterGlobalIndex;
+
     /// Enabled ?
     bool enabled = true;
 
diff --git a/src/libs/antares/study/parts/short-term-storage/container.cpp b/src/libs/antares/study/parts/short-term-storage/container.cpp
index 181f38cab9..a25befa86b 100644
--- a/src/libs/antares/study/parts/short-term-storage/container.cpp
+++ b/src/libs/antares/study/parts/short-term-storage/container.cpp
@@ -62,7 +62,7 @@ bool STStorageInput::createSTStorageClustersFromIniFile(const fs::path& path)
         {
             return false;
         }
-
+        cluster.properties.clusterGlobalIndex = storagesByIndex.size();
         storagesByIndex.push_back(cluster);
     }
 
diff --git a/src/solver/optimisation/CMakeLists.txt b/src/solver/optimisation/CMakeLists.txt
index cc44045e9d..8f53cc6b02 100644
--- a/src/solver/optimisation/CMakeLists.txt
+++ b/src/solver/optimisation/CMakeLists.txt
@@ -30,7 +30,7 @@ set(RTESOLVER_OPT
 		opt_gestion_des_couts_cas_quadratique.cpp
         opt_construction_variables_couts_demarrages.cpp
         opt_gestion_des_bornes_couts_demarrage.cpp
-        opt_gestion_des_bornes_reserves_thermiques.cpp
+        opt_gestion_des_bornes_reserves.cpp
         opt_gestion_des_couts_couts_demarrage.cpp
         opt_gestion_des_couts_reserves.cpp
         opt_gestion_second_membre_couts_demarrage.cpp
diff --git a/src/solver/optimisation/constraints/POutBounds.cpp b/src/solver/optimisation/constraints/POutBounds.cpp
index ab57356a83..63612d899e 100644
--- a/src/solver/optimisation/constraints/POutBounds.cpp
+++ b/src/solver/optimisation/constraints/POutBounds.cpp
@@ -24,13 +24,13 @@ void POutBounds::add(int pays, int cluster, int pdt)
             for (const auto& capacityReservation :
                  data.areaReserves[pays].areaCapacityReservationsDown)
             {
-                for (const auto& [clusterId, reserveParticipations] :
-                     capacityReservation.AllThermalReservesParticipation)
+                if (capacityReservation.AllThermalReservesParticipation.contains(cluster))
                 {
-                    if (cluster == clusterId)
-                        builder.RunningThermalClusterReserveParticipation(
-                          reserveParticipations.globalIndexClusterParticipation,
-                          1);
+                    auto& reserveParticipation = capacityReservation.AllThermalReservesParticipation
+                                                   .at(cluster);
+                    builder.RunningThermalClusterReserveParticipation(
+                      reserveParticipation.globalIndexClusterParticipation,
+                      1);
                 }
             }
 
@@ -60,13 +60,13 @@ void POutBounds::add(int pays, int cluster, int pdt)
             for (const auto& capacityReservation :
                  data.areaReserves[pays].areaCapacityReservationsUp)
             {
-                for (const auto& [clusterId, reserveParticipations] :
-                     capacityReservation.AllThermalReservesParticipation)
+                if (capacityReservation.AllThermalReservesParticipation.contains(cluster))
                 {
-                    if (cluster == clusterId)
-                        builder.RunningThermalClusterReserveParticipation(
-                          reserveParticipations.globalIndexClusterParticipation,
-                          1);
+                    auto& reserveParticipation = capacityReservation.AllThermalReservesParticipation
+                                                   .at(cluster);
+                    builder.RunningThermalClusterReserveParticipation(
+                      reserveParticipation.globalIndexClusterParticipation,
+                      1);
                 }
             }
 
diff --git a/src/solver/optimisation/constraints/POutCapacityThreasholds.cpp b/src/solver/optimisation/constraints/POutCapacityThreasholds.cpp
index c1c801f204..a72f5559d5 100644
--- a/src/solver/optimisation/constraints/POutCapacityThreasholds.cpp
+++ b/src/solver/optimisation/constraints/POutCapacityThreasholds.cpp
@@ -24,12 +24,13 @@ void POutCapacityThreasholds::add(int pays, int cluster, int pdt)
             for (const auto& capacityReservation :
                  data.areaReserves[pays].areaCapacityReservationsDown)
             {
-                for (const auto& [clusterId, reserveParticipations] :
-                     capacityReservation.AllThermalReservesParticipation)
+                if (capacityReservation.AllThermalReservesParticipation.contains(cluster))
                 {
-                    if (cluster == clusterId)
-                        builder.RunningThermalClusterReserveParticipation(
-                          reserveParticipations.globalIndexClusterParticipation, 1);
+                    auto& reserveParticipation = capacityReservation.AllThermalReservesParticipation
+                                                   .at(cluster);
+                    builder.RunningThermalClusterReserveParticipation(
+                      reserveParticipation.globalIndexClusterParticipation,
+                      1);
                 }
             }
 
@@ -59,13 +60,13 @@ void POutCapacityThreasholds::add(int pays, int cluster, int pdt)
             for (const auto& capacityReservation :
                  data.areaReserves[pays].areaCapacityReservationsUp)
             {
-                for (const auto& [clusterId, reserveParticipations] :
-                     capacityReservation.AllThermalReservesParticipation)
+                if (capacityReservation.AllThermalReservesParticipation.contains(cluster))
                 {
-                    if (cluster == clusterId)
-                        builder.RunningThermalClusterReserveParticipation(
-                          reserveParticipations.globalIndexClusterParticipation,
-                          1);
+                    auto& reserveParticipation = capacityReservation.AllThermalReservesParticipation
+                                                   .at(cluster);
+                    builder.RunningThermalClusterReserveParticipation(
+                      reserveParticipation.globalIndexClusterParticipation,
+                      1);
                 }
             }
 
diff --git a/src/solver/optimisation/constraints/STPumpingCapacityThreasholds.cpp b/src/solver/optimisation/constraints/STPumpingCapacityThreasholds.cpp
index 3fa9c27015..8d68410440 100644
--- a/src/solver/optimisation/constraints/STPumpingCapacityThreasholds.cpp
+++ b/src/solver/optimisation/constraints/STPumpingCapacityThreasholds.cpp
@@ -21,12 +21,13 @@ void STPumpingCapacityThreasholds::add(int pays, int cluster, int pdt)
             for (const auto& capacityReservation :
                  data.areaReserves[pays].areaCapacityReservationsUp)
             {
-                for (const auto& [clusterId, reserveParticipations] :
-                     capacityReservation.AllSTStorageReservesParticipation)
+                if (capacityReservation.AllThermalReservesParticipation.contains(cluster))
                 {
-                    if (cluster == clusterId)
-                        builder.STStoragePumpingClusterReserveParticipation(
-                          reserveParticipations.globalIndexClusterParticipation, 1);
+                    auto& reserveParticipation = capacityReservation
+                                                   .AllSTStorageReservesParticipation.at(cluster);
+                    builder.STStoragePumpingClusterReserveParticipation(
+                      reserveParticipation.globalIndexClusterParticipation,
+                      1);
                 }
             }
 
@@ -50,12 +51,13 @@ void STPumpingCapacityThreasholds::add(int pays, int cluster, int pdt)
             for (const auto& capacityReservation :
                  data.areaReserves[pays].areaCapacityReservationsDown)
             {
-                for (const auto& [clusterId, reserveParticipations] :
-                     capacityReservation.AllSTStorageReservesParticipation)
+                if (capacityReservation.AllThermalReservesParticipation.contains(cluster))
                 {
-                    if (cluster == clusterId)
-                        builder.STStoragePumpingClusterReserveParticipation(
-                          reserveParticipations.globalIndexClusterParticipation, 1);
+                    auto& reserveParticipation = capacityReservation
+                                                   .AllSTStorageReservesParticipation.at(cluster);
+                    builder.STStoragePumpingClusterReserveParticipation(
+                      reserveParticipation.globalIndexClusterParticipation,
+                      1);
                 }
             }
 
diff --git a/src/solver/optimisation/constraints/STTurbiningCapacityThreasholds.cpp b/src/solver/optimisation/constraints/STTurbiningCapacityThreasholds.cpp
index 48227fa1b4..50c861a60b 100644
--- a/src/solver/optimisation/constraints/STTurbiningCapacityThreasholds.cpp
+++ b/src/solver/optimisation/constraints/STTurbiningCapacityThreasholds.cpp
@@ -21,12 +21,13 @@ void STTurbiningCapacityThreasholds::add(int pays, int cluster, int pdt)
             for (const auto& capacityReservation :
                  data.areaReserves[pays].areaCapacityReservationsDown)
             {
-                for (const auto& [clusterId, reserveParticipations] :
-                     capacityReservation.AllSTStorageReservesParticipation)
+                if (capacityReservation.AllThermalReservesParticipation.contains(cluster))
                 {
-                    if (cluster == clusterId)
-                        builder.STStorageTurbiningClusterReserveParticipation(
-                          reserveParticipations.globalIndexClusterParticipation, -1);
+                    auto& reserveParticipation = capacityReservation
+                                                   .AllSTStorageReservesParticipation.at(cluster);
+                    builder.STStorageTurbiningClusterReserveParticipation(
+                      reserveParticipation.globalIndexClusterParticipation,
+                      -1);
                 }
             }
 
@@ -55,12 +56,13 @@ void STTurbiningCapacityThreasholds::add(int pays, int cluster, int pdt)
             for (const auto& capacityReservation :
                  data.areaReserves[pays].areaCapacityReservationsUp)
             {
-                for (const auto& [clusterId, reserveParticipations] :
-                     capacityReservation.AllSTStorageReservesParticipation)
+                if (capacityReservation.AllThermalReservesParticipation.contains(cluster))
                 {
-                    if (cluster == clusterId)
-                        builder.STStorageTurbiningClusterReserveParticipation(
-                          reserveParticipations.globalIndexClusterParticipation, 1);
+                    auto& reserveParticipation = capacityReservation
+                                                   .AllSTStorageReservesParticipation.at(cluster);
+                    builder.STStorageTurbiningClusterReserveParticipation(
+                      reserveParticipation.globalIndexClusterParticipation,
+                      1);
                 }
             }
 
diff --git a/src/solver/optimisation/opt_construction_variables_reserves.cpp b/src/solver/optimisation/opt_construction_variables_reserves.cpp
index 4bb183d9a8..763e69fde9 100644
--- a/src/solver/optimisation/opt_construction_variables_reserves.cpp
+++ b/src/solver/optimisation/opt_construction_variables_reserves.cpp
@@ -19,30 +19,380 @@
 ** along with Antares_Simulator. If not, see <https://opensource.org/license/mpl-2-0/>.
 */
 
-#include "antares/solver/optimisation/opt_structure_probleme_a_resoudre.h"
+#include <spx_constantes_externes.h>
 
 #include "antares/solver/optimisation/opt_fonctions.h"
 #include "antares/solver/optimisation/opt_rename_problem.h"
-
-#include <spx_constantes_externes.h>
+#include "antares/solver/optimisation/opt_structure_probleme_a_resoudre.h"
 
 void OPT_ConstruireLaListeDesVariablesOptimiseesDuProblemeLineaireReserves(
   PROBLEME_HEBDO* problemeHebdo,
   bool Simulation)
 {
-    const auto& ProblemeAResoudre = problemeHebdo->ProblemeAResoudre;
+    VariableNamer variableNamer(problemeHebdo->ProblemeAResoudre->NomDesVariables);
+    int NombreDePasDeTempsPourUneOptimisation = problemeHebdo
+                                                  ->NombreDePasDeTempsPourUneOptimisation;
+
+    struct ReserveVariablesInitializer
+    {
+        PROBLEME_HEBDO* problemeHebdo;
+        bool Simulation;
+        const std::unique_ptr<PROBLEME_ANTARES_A_RESOUDRE>& ProblemeAResoudre;
+        int& NombreDeVariables;
+        VariableNamer& variableNamer;
+        VariableManagement::VariableManager variableManager;
+
+        ReserveVariablesInitializer(PROBLEME_HEBDO* hebdo, bool sim, VariableNamer& namer):
+            problemeHebdo(hebdo),
+            Simulation(sim),
+            ProblemeAResoudre(hebdo->ProblemeAResoudre),
+            NombreDeVariables(ProblemeAResoudre->NombreDeVariables),
+            variableNamer(namer),
+            variableManager(VariableManagerFromProblemHebdo(hebdo))
+        {
+        }
+
+        // Init variables for a reserve
+        void initReserve(int pdt, const int reserveIndex, const std::string& reserveName)
+        {
+            if (Simulation)
+            {
+                NombreDeVariables += 2;
+            }
+            else
+            {
+                // For Unsatisfied Reserves
+                variableManager.InternalUnsatisfiedReserve(reserveIndex, pdt) = NombreDeVariables;
+                ProblemeAResoudre->TypeDeVariable[NombreDeVariables]
+                  = VARIABLE_BORNEE_DES_DEUX_COTES;
+                variableNamer.InternalUnsatisfiedReserve(NombreDeVariables, reserveName);
+                NombreDeVariables++;
+
+                // For Excess Reserves
+                variableManager.InternalExcessReserve(reserveIndex, pdt) = NombreDeVariables;
+                ProblemeAResoudre->TypeDeVariable[NombreDeVariables]
+                  = VARIABLE_BORNEE_DES_DEUX_COTES;
+                variableNamer.InternalExcessReserve(NombreDeVariables, reserveName);
+                NombreDeVariables++;
+            }
+        }
+
+        // Init variables for a Thermal cluster participation to a reserve up
+        void initThermalReserveUpParticipation(
+          int pdt,
+          const RESERVE_PARTICIPATION_THERMAL& clusterReserveParticipation,
+          const std::string& reserveName)
+        {
+            const auto& clusterName = clusterReserveParticipation.clusterName;
+            if (Simulation)
+            {
+                NombreDeVariables += 4;
+            }
+            else
+            {
+                // For running units in cluster
+                variableManager.RunningThermalClusterReserveParticipation(
+                  clusterReserveParticipation.globalIndexClusterParticipation,
+                  pdt)
+                  = NombreDeVariables;
+                ProblemeAResoudre->TypeDeVariable[NombreDeVariables]
+                  = VARIABLE_BORNEE_DES_DEUX_COTES;
+                variableNamer.ParticipationOfRunningUnitsToReserve(NombreDeVariables,
+                                                                   clusterName,
+                                                                   reserveName);
+                NombreDeVariables++;
 
-    int NombreDePasDeTempsPourUneOptimisation
-      = problemeHebdo->NombreDePasDeTempsPourUneOptimisation;
-    int& NombreDeVariables = ProblemeAResoudre->NombreDeVariables;
-    VariableNamer variableNamer(ProblemeAResoudre->NomDesVariables);
-    auto variableManager = VariableManagerFromProblemHebdo(problemeHebdo);
+                // For off units in cluster
+                variableManager.OffThermalClusterReserveParticipation(
+                  clusterReserveParticipation.globalIndexClusterParticipation,
+                  pdt)
+                  = NombreDeVariables;
+                ProblemeAResoudre->TypeDeVariable[NombreDeVariables]
+                  = VARIABLE_BORNEE_DES_DEUX_COTES;
+                variableNamer.ParticipationOfOffUnitsToReserve(NombreDeVariables,
+                                                               clusterName,
+                                                               reserveName);
+                NombreDeVariables++;
+
+                variableManager.NumberOfOffUnitsParticipatingToReserve(
+                  clusterReserveParticipation.globalIndexClusterParticipation,
+                  pdt)
+                  = NombreDeVariables;
+                ProblemeAResoudre->TypeDeVariable[NombreDeVariables]
+                  = VARIABLE_BORNEE_DES_DEUX_COTES;
+                ProblemeAResoudre->VariablesEntieres[NombreDeVariables]
+                  = problemeHebdo->OptimisationAvecVariablesEntieres;
+                variableNamer.NumberOfOffUnitsParticipatingToReserve(NombreDeVariables,
+                                                                     clusterName,
+                                                                     reserveName);
+                NombreDeVariables++;
+
+                // For all units in cluster
+                variableManager.ThermalClusterReserveParticipation(
+                  clusterReserveParticipation.globalIndexClusterParticipation,
+                  pdt)
+                  = NombreDeVariables;
+                ProblemeAResoudre->TypeDeVariable[NombreDeVariables]
+                  = VARIABLE_BORNEE_DES_DEUX_COTES;
+                variableNamer.ThermalClusterReserveParticipation(NombreDeVariables,
+                                                                 clusterName,
+                                                                 reserveName);
+                NombreDeVariables++;
+            }
+        }
+
+        // Init variables for a Thermal cluster participation to a reserve down
+        void initThermalReserveDownParticipation(
+          int pdt,
+          const RESERVE_PARTICIPATION_THERMAL& clusterReserveParticipation,
+          const std::string& reserveName)
+        {
+            const auto& clusterName = clusterReserveParticipation.clusterName;
+            if (Simulation)
+            {
+                NombreDeVariables += 2;
+            }
+            else
+            {
+                // For running units in cluster
+                variableManager.RunningThermalClusterReserveParticipation(
+                  clusterReserveParticipation.globalIndexClusterParticipation,
+                  pdt)
+                  = NombreDeVariables;
+                ProblemeAResoudre->TypeDeVariable[NombreDeVariables]
+                  = VARIABLE_BORNEE_DES_DEUX_COTES;
+                variableNamer.ParticipationOfRunningUnitsToReserve(NombreDeVariables,
+                                                                   clusterName,
+                                                                   reserveName);
+                NombreDeVariables++;
+
+                // For all units in cluster (off units can not participate to down reserves)
+                variableManager.ThermalClusterReserveParticipation(
+                  clusterReserveParticipation.globalIndexClusterParticipation,
+                  pdt)
+                  = NombreDeVariables;
+                ProblemeAResoudre->TypeDeVariable[NombreDeVariables]
+                  = VARIABLE_BORNEE_DES_DEUX_COTES;
+                variableNamer.ThermalClusterReserveParticipation(NombreDeVariables,
+                                                                 clusterName,
+                                                                 reserveName);
+                NombreDeVariables++;
+            }
+        }
+
+        // Init variables for a ShortTerm cluster participation to a reserve up
+        void initSTStorageReserveUpParticipation(
+          int pdt,
+          const RESERVE_PARTICIPATION_STSTORAGE& clusterReserveParticipation,
+          const std::string& reserveName)
+        {
+            const auto& clusterName = clusterReserveParticipation.clusterName;
+            if (Simulation)
+            {
+                NombreDeVariables += 3;
+            }
+            else
+            {
+                // For Turbining participation to the reserves
+                variableManager.STStorageTurbiningClusterReserveParticipation(
+                  clusterReserveParticipation.globalIndexClusterParticipation,
+                  pdt)
+                  = NombreDeVariables;
+                ProblemeAResoudre->TypeDeVariable[NombreDeVariables]
+                  = VARIABLE_BORNEE_DES_DEUX_COTES;
+                variableNamer.ParticipationOfSTStorageTurbiningToReserve(NombreDeVariables,
+                                                                         clusterName,
+                                                                         reserveName);
+                NombreDeVariables++;
+
+                // For Pumping participation to the reserves
+                variableManager.STStoragePumpingClusterReserveParticipation(
+                  clusterReserveParticipation.globalIndexClusterParticipation,
+                  pdt)
+                  = NombreDeVariables;
+                ProblemeAResoudre->TypeDeVariable[NombreDeVariables]
+                  = VARIABLE_BORNEE_DES_DEUX_COTES;
+                variableNamer.ParticipationOfSTStoragePumpingToReserve(NombreDeVariables,
+                                                                       clusterName,
+                                                                       reserveName);
+                NombreDeVariables++;
+
+                // For Short Term Storage participation to the up reserves
+                variableManager.STStorageClusterReserveUpParticipation(
+                  clusterReserveParticipation.globalIndexClusterParticipation,
+                  pdt)
+                  = NombreDeVariables;
+                ProblemeAResoudre->TypeDeVariable[NombreDeVariables]
+                  = VARIABLE_BORNEE_DES_DEUX_COTES;
+                variableNamer.ParticipationOfSTStorageToUpReserve(NombreDeVariables,
+                                                                  clusterName,
+                                                                  reserveName);
+                NombreDeVariables++;
+            }
+        }
 
+        // Init variables for a ShortTerm cluster participation to a reserve down
+        void initSTStorageReserveDownParticipation(
+          int pdt,
+          const RESERVE_PARTICIPATION_STSTORAGE& clusterReserveParticipation,
+          const std::string& reserveName)
+        {
+            const auto& clusterName = clusterReserveParticipation.clusterName;
+            if (Simulation)
+            {
+                NombreDeVariables += 3;
+            }
+            else
+            {
+                // For Turbining participation to the reserves
+                variableManager.STStorageTurbiningClusterReserveParticipation(
+                  clusterReserveParticipation.globalIndexClusterParticipation,
+                  pdt)
+                  = NombreDeVariables;
+                ProblemeAResoudre->TypeDeVariable[NombreDeVariables]
+                  = VARIABLE_BORNEE_DES_DEUX_COTES;
+                variableNamer.ParticipationOfSTStorageTurbiningToReserve(NombreDeVariables,
+                                                                         clusterName,
+                                                                         reserveName);
+                NombreDeVariables++;
+
+                // For Pumping participation to the reserves
+                variableManager.STStoragePumpingClusterReserveParticipation(
+                  clusterReserveParticipation.globalIndexClusterParticipation,
+                  pdt)
+                  = NombreDeVariables;
+                ProblemeAResoudre->TypeDeVariable[NombreDeVariables]
+                  = VARIABLE_BORNEE_DES_DEUX_COTES;
+                variableNamer.ParticipationOfSTStoragePumpingToReserve(NombreDeVariables,
+                                                                       clusterName,
+                                                                       reserveName);
+                NombreDeVariables++;
+
+                // For Short Term Storage participation to the Down reserves
+                variableManager.STStorageClusterReserveDownParticipation(
+                  clusterReserveParticipation.globalIndexClusterParticipation,
+                  pdt)
+                  = NombreDeVariables;
+                ProblemeAResoudre->TypeDeVariable[NombreDeVariables]
+                  = VARIABLE_BORNEE_DES_DEUX_COTES;
+                variableNamer.ParticipationOfSTStorageToDownReserve(NombreDeVariables,
+                                                                    clusterName,
+                                                                    reserveName);
+                NombreDeVariables++;
+            }
+        }
+
+        // Init variables for a LongTerm cluster participation to a reserve up
+        void initLTStorageReserveUpParticipation(
+          int pdt,
+          const RESERVE_PARTICIPATION_LTSTORAGE& clusterReserveParticipation,
+          const std::string& reserveName)
+        {
+            const auto& clusterName = clusterReserveParticipation.clusterName;
+            if (Simulation)
+            {
+                NombreDeVariables += 3;
+            }
+            else
+            {
+                // For Turbining participation to the reserves
+                variableManager.LTStorageTurbiningClusterReserveParticipation(
+                  clusterReserveParticipation.globalIndexClusterParticipation,
+                  pdt)
+                  = NombreDeVariables;
+                ProblemeAResoudre->TypeDeVariable[NombreDeVariables]
+                  = VARIABLE_BORNEE_DES_DEUX_COTES;
+                variableNamer.ParticipationOfLTStorageTurbiningToReserve(NombreDeVariables,
+                                                                         clusterName,
+                                                                         reserveName);
+                NombreDeVariables++;
+
+                // For Pumping participation to the reserves
+                variableManager.LTStoragePumpingClusterReserveParticipation(
+                  clusterReserveParticipation.globalIndexClusterParticipation,
+                  pdt)
+                  = NombreDeVariables;
+                ProblemeAResoudre->TypeDeVariable[NombreDeVariables]
+                  = VARIABLE_BORNEE_DES_DEUX_COTES;
+                variableNamer.ParticipationOfLTStoragePumpingToReserve(NombreDeVariables,
+                                                                       clusterName,
+                                                                       reserveName);
+                NombreDeVariables++;
+
+                // For Long Term Storage participation to the up reserves
+                variableManager.LTStorageClusterReserveUpParticipation(
+                  clusterReserveParticipation.globalIndexClusterParticipation,
+                  pdt)
+                  = NombreDeVariables;
+                ProblemeAResoudre->TypeDeVariable[NombreDeVariables]
+                  = VARIABLE_BORNEE_DES_DEUX_COTES;
+                variableNamer.ParticipationOfLTStorageToUpReserve(NombreDeVariables,
+                                                                  clusterName,
+                                                                  reserveName);
+                NombreDeVariables++;
+            }
+        }
+
+        // Init variables for a LongTerm cluster participation to a reserve down
+        void initLTStorageReserveDownParticipation(
+          int pdt,
+          const RESERVE_PARTICIPATION_LTSTORAGE& clusterReserveParticipation,
+          const std::string& reserveName)
+        {
+            const auto& clusterName = clusterReserveParticipation.clusterName;
+            if (Simulation)
+            {
+                NombreDeVariables += 3;
+            }
+            else
+            {
+                // For Turbining participation to the reserves
+                variableManager.LTStorageTurbiningClusterReserveParticipation(
+                  clusterReserveParticipation.globalIndexClusterParticipation,
+                  pdt)
+                  = NombreDeVariables;
+                ProblemeAResoudre->TypeDeVariable[NombreDeVariables]
+                  = VARIABLE_BORNEE_DES_DEUX_COTES;
+                variableNamer.ParticipationOfLTStorageTurbiningToReserve(NombreDeVariables,
+                                                                         clusterName,
+                                                                         reserveName);
+                NombreDeVariables++;
+
+                // For Pumping participation to the reserves
+                variableManager.LTStoragePumpingClusterReserveParticipation(
+                  clusterReserveParticipation.globalIndexClusterParticipation,
+                  pdt)
+                  = NombreDeVariables;
+                ProblemeAResoudre->TypeDeVariable[NombreDeVariables]
+                  = VARIABLE_BORNEE_DES_DEUX_COTES;
+                variableNamer.ParticipationOfLTStoragePumpingToReserve(NombreDeVariables,
+                                                                       clusterName,
+                                                                       reserveName);
+                NombreDeVariables++;
+
+                // For Long Term Storage participation to the Down reserves
+                variableManager.LTStorageClusterReserveDownParticipation(
+                  clusterReserveParticipation.globalIndexClusterParticipation,
+                  pdt)
+                  = NombreDeVariables;
+                ProblemeAResoudre->TypeDeVariable[NombreDeVariables]
+                  = VARIABLE_BORNEE_DES_DEUX_COTES;
+                variableNamer.ParticipationOfLTStorageToDownReserve(NombreDeVariables,
+                                                                    clusterName,
+                                                                    reserveName);
+                NombreDeVariables++;
+            }
+        }
+    };
+
+    ReserveVariablesInitializer reserveVariablesInitializer(problemeHebdo,
+                                                            Simulation,
+                                                            variableNamer);
     for (int pdt = 0; pdt < NombreDePasDeTempsPourUneOptimisation; pdt++)
     {
         variableNamer.UpdateTimeStep(problemeHebdo->weekInTheYear * 168 + pdt);
-        auto& CorrespondanceVarNativesVarOptim
-          = problemeHebdo->CorrespondanceVarNativesVarOptim[pdt];
+        auto& CorrespondanceVarNativesVarOptim = problemeHebdo
+                                                   ->CorrespondanceVarNativesVarOptim[pdt];
 
         for (uint32_t pays = 0; pays < problemeHebdo->NombreDePays; pays++)
         {
@@ -52,439 +402,78 @@ void OPT_ConstruireLaListeDesVariablesOptimiseesDuProblemeLineaireReserves(
             int reserveIndex = 0;
 
             // For Up Reserves
-            for (auto& areaReserveUp : areaReserves.areaCapacityReservationsUp)
+            for (auto& areaReserveUp: areaReserves.areaCapacityReservationsUp)
             {
-                reserveIndex = areaReserveUp.globalReserveIndex;
-                if (Simulation)
-                {
-                    NombreDeVariables += 2;
-                }
-                else
-                {
-                    // For Unsatisfied Reserves
-                    variableManager.InternalUnsatisfiedReserve(reserveIndex, pdt)
-                      = NombreDeVariables;
-                    ProblemeAResoudre->TypeDeVariable[NombreDeVariables]
-                      = VARIABLE_BORNEE_DES_DEUX_COTES;
-                    variableNamer.InternalUnsatisfiedReserve(NombreDeVariables,
-                                                             areaReserveUp.reserveName);
-                    NombreDeVariables++;
-
-                    // For Excess Reserves
-                    variableManager.InternalExcessReserve(reserveIndex, pdt) = NombreDeVariables;
-                    ProblemeAResoudre->TypeDeVariable[NombreDeVariables]
-                      = VARIABLE_BORNEE_DES_DEUX_COTES;
-                    variableNamer.InternalExcessReserve(NombreDeVariables,
+                reserveVariablesInitializer.initReserve(pdt,
+                                                        areaReserveUp.globalReserveIndex,
                                                         areaReserveUp.reserveName);
-                    NombreDeVariables++;
-                }
 
                 // Thermal Clusters
-                for (auto& [clusterId, clusterReserveParticipation] :
+                for (auto& [clusterId, clusterReserveParticipation]:
                      areaReserveUp.AllThermalReservesParticipation)
                 {
-                    const auto& clusterName = clusterReserveParticipation.clusterName;
-                    if (Simulation)
-                    {
-                        NombreDeVariables++;
-                    }
-                    else
-                    {
-                        // For running units in cluster
-                        variableManager.RunningThermalClusterReserveParticipation(
-                          clusterReserveParticipation.globalIndexClusterParticipation,
-                          pdt)
-                          = NombreDeVariables;
-                        ProblemeAResoudre->TypeDeVariable[NombreDeVariables]
-                          = VARIABLE_BORNEE_DES_DEUX_COTES;
-                        variableNamer.ParticipationOfRunningUnitsToReserve(
-                          NombreDeVariables,
-                          clusterName,
-                          areaReserveUp.reserveName);
-                        NombreDeVariables++;
-                    }
-                    if (Simulation)
-                    {
-                        NombreDeVariables += 2;
-                    }
-                    else
-                    {
-                        // For off units in cluster
-                        variableManager.OffThermalClusterReserveParticipation(
-                          clusterReserveParticipation.globalIndexClusterParticipation,
-                          pdt)
-                          = NombreDeVariables;
-                        ProblemeAResoudre->TypeDeVariable[NombreDeVariables]
-                          = VARIABLE_BORNEE_DES_DEUX_COTES;
-                        variableNamer.ParticipationOfOffUnitsToReserve(NombreDeVariables,
-                                                                       clusterName,
-                                                                       areaReserveUp.reserveName);
-                        NombreDeVariables++;
-
-                        variableManager.NumberOfOffUnitsParticipatingToReserve(
-                          clusterReserveParticipation.globalIndexClusterParticipation,
-                          pdt)
-                          = NombreDeVariables;
-                        ProblemeAResoudre->TypeDeVariable[NombreDeVariables]
-                          = VARIABLE_BORNEE_DES_DEUX_COTES;
-                        ProblemeAResoudre->VariablesEntieres[NombreDeVariables]
-                          = problemeHebdo->OptimisationAvecVariablesEntieres;
-                        variableNamer.NumberOfOffUnitsParticipatingToReserve(
-                          NombreDeVariables,
-                          clusterName,
-                          areaReserveUp.reserveName);
-                        NombreDeVariables++;
-                    }
-                    if (Simulation)
-                    {
-                        NombreDeVariables++;
-                    }
-                    else
-                    {
-                        // For all units in cluster
-                        variableManager.ThermalClusterReserveParticipation(
-                          clusterReserveParticipation.globalIndexClusterParticipation,
-                          pdt)
-                          = NombreDeVariables;
-                        ProblemeAResoudre->TypeDeVariable[NombreDeVariables]
-                          = VARIABLE_BORNEE_DES_DEUX_COTES;
-                        variableNamer.ThermalClusterReserveParticipation(NombreDeVariables,
-                                                                    clusterName,
-                                                                    areaReserveUp.reserveName);
-                        NombreDeVariables++;
-                    }
+                    reserveVariablesInitializer.initThermalReserveUpParticipation(
+                      pdt,
+                      clusterReserveParticipation,
+                      areaReserveUp.reserveName);
                 }
 
                 // Short Term Storage Clusters
-                for (auto& [clusterId, clusterReserveParticipation] :
-                    areaReserveUp.AllSTStorageReservesParticipation)
+                for (auto& [clusterId, clusterReserveParticipation]:
+                     areaReserveUp.AllSTStorageReservesParticipation)
                 {
-                    const auto& clusterName = clusterReserveParticipation.clusterName;
-                    if (Simulation)
-                    {
-                        NombreDeVariables++;
-                    }
-                    else
-                    {
-                        // For Turbining participation to the reserves
-                        variableManager.STStorageTurbiningClusterReserveParticipation(
-                          clusterReserveParticipation.globalIndexClusterParticipation,
-                          pdt)
-                          = NombreDeVariables;
-                        ProblemeAResoudre->TypeDeVariable[NombreDeVariables]
-                          = VARIABLE_BORNEE_DES_DEUX_COTES;
-                        variableNamer.ParticipationOfSTStorageTurbiningToReserve(
-                          NombreDeVariables,
-                          clusterName,
-                          areaReserveUp.reserveName);
-                        NombreDeVariables++;
-                    }
-
-                    if (Simulation)
-                    {
-                        NombreDeVariables++;
-                    }
-                    else
-                    {
-                        // For Pumping participation to the reserves
-                        variableManager.STStoragePumpingClusterReserveParticipation(
-                          clusterReserveParticipation.globalIndexClusterParticipation,
-                          pdt)
-                          = NombreDeVariables;
-                        ProblemeAResoudre->TypeDeVariable[NombreDeVariables]
-                          = VARIABLE_BORNEE_DES_DEUX_COTES;
-                        variableNamer.ParticipationOfSTStoragePumpingToReserve(
-                          NombreDeVariables,
-                          clusterName,
-                          areaReserveUp.reserveName);
-                        NombreDeVariables++;
-                    }
-
-                    if (Simulation)
-                    {
-                        NombreDeVariables++;
-                    }
-                    else
-                    {
-                        // For Short Term Storage participation to the up reserves
-                        variableManager.STStorageClusterReserveUpParticipation(
-                          clusterReserveParticipation.globalIndexClusterParticipation,
-                          pdt)
-                          = NombreDeVariables;
-                        ProblemeAResoudre->TypeDeVariable[NombreDeVariables]
-                          = VARIABLE_BORNEE_DES_DEUX_COTES;
-                        variableNamer.ParticipationOfSTStorageToUpReserve(
-                          NombreDeVariables,
-                          clusterName,
-                          areaReserveUp.reserveName);
-                        NombreDeVariables++;
-                    }
+                    reserveVariablesInitializer.initSTStorageReserveUpParticipation(
+                      pdt,
+                      clusterReserveParticipation,
+                      areaReserveUp.reserveName);
                 }
 
-                //Long Term Storage Clusters
-                for (auto& clusterReserveParticipation :
-                        areaReserveUp.AllLTStorageReservesParticipation)
+                // Long Term Storage Clusters
+                for (auto& clusterReserveParticipation:
+                     areaReserveUp.AllLTStorageReservesParticipation)
                 {
-                    const auto& clusterName = clusterReserveParticipation.clusterName;
-                    if (Simulation)
-                    {
-                        NombreDeVariables++;
-                    }
-                    else
-                    {
-                        // For Turbining participation to the reserves
-                        variableManager.LTStorageTurbiningClusterReserveParticipation(
-                          clusterReserveParticipation.globalIndexClusterParticipation,
-                          pdt)
-                          = NombreDeVariables;
-                        ProblemeAResoudre->TypeDeVariable[NombreDeVariables]
-                          = VARIABLE_BORNEE_DES_DEUX_COTES;
-                        variableNamer.ParticipationOfLTStorageTurbiningToReserve(
-                          NombreDeVariables,
-                          clusterName,
-                          areaReserveUp.reserveName);
-                        NombreDeVariables++;
-                    }
-
-                    if (Simulation)
-                    {
-                        NombreDeVariables++;
-                    }
-                    else
-                    {
-                        // For Pumping participation to the reserves
-                        variableManager.LTStoragePumpingClusterReserveParticipation(
-                          clusterReserveParticipation.globalIndexClusterParticipation,
-                          pdt)
-                          = NombreDeVariables;
-                        ProblemeAResoudre->TypeDeVariable[NombreDeVariables]
-                          = VARIABLE_BORNEE_DES_DEUX_COTES;
-                        variableNamer.ParticipationOfLTStoragePumpingToReserve(
-                          NombreDeVariables,
-                          clusterName,
-                          areaReserveUp.reserveName);
-                        NombreDeVariables++;
-                    }
-
-                    if (Simulation)
-                    {
-                        NombreDeVariables++;
-                    }
-                    else
-                    {
-                        // For Long Term Storage participation to the up reserves
-                        variableManager.LTStorageClusterReserveUpParticipation(
-                          clusterReserveParticipation.globalIndexClusterParticipation,
-                          pdt)
-                          = NombreDeVariables;
-                        ProblemeAResoudre->TypeDeVariable[NombreDeVariables]
-                          = VARIABLE_BORNEE_DES_DEUX_COTES;
-                        variableNamer.ParticipationOfLTStorageToUpReserve(
-                          NombreDeVariables,
-                          clusterName,
-                          areaReserveUp.reserveName);
-                        NombreDeVariables++;
-                    }
+                    reserveVariablesInitializer.initLTStorageReserveUpParticipation(
+                      pdt,
+                      clusterReserveParticipation,
+                      areaReserveUp.reserveName);
                 }
             }
 
             // For Down Reserves
-            for (auto& areaReserveDown : areaReserves.areaCapacityReservationsDown)
+            for (auto& areaReserveDown: areaReserves.areaCapacityReservationsDown)
             {
-                reserveIndex = areaReserveDown.globalReserveIndex;
-                if (Simulation)
-                {
-                    NombreDeVariables += 2;
-                }
-                else
-                {
-                    // For Unsatisfied Reserves
-                    variableManager.InternalUnsatisfiedReserve(reserveIndex, pdt)
-                      = NombreDeVariables;
-                    ProblemeAResoudre->TypeDeVariable[NombreDeVariables]
-                      = VARIABLE_BORNEE_DES_DEUX_COTES;
-                    variableNamer.InternalUnsatisfiedReserve(NombreDeVariables,
-                                                             areaReserveDown.reserveName);
-                    NombreDeVariables++;
-
-                    // For Excess Reserves
-                    variableManager.InternalExcessReserve(reserveIndex, pdt) = NombreDeVariables;
-                    ProblemeAResoudre->TypeDeVariable[NombreDeVariables]
-                      = VARIABLE_BORNEE_DES_DEUX_COTES;
-                    variableNamer.InternalExcessReserve(NombreDeVariables,
+                reserveVariablesInitializer.initReserve(pdt,
+                                                        areaReserveDown.globalReserveIndex,
                                                         areaReserveDown.reserveName);
-                    NombreDeVariables++;
-                }
 
                 // Thermal Clusters
-                for (auto& [clusterId, clusterReserveParticipation] :
+                for (auto& [clusterId, clusterReserveParticipation]:
                      areaReserveDown.AllThermalReservesParticipation)
                 {
-                    const auto& clusterName = clusterReserveParticipation.clusterName;
-                    if (Simulation)
-                    {
-                        NombreDeVariables += 2;
-                    }
-                    else
-                    {
-                        // For running units in cluster
-                        variableManager.RunningThermalClusterReserveParticipation(
-                          clusterReserveParticipation.globalIndexClusterParticipation,
-                          pdt)
-                          = NombreDeVariables;
-                        ProblemeAResoudre->TypeDeVariable[NombreDeVariables]
-                          = VARIABLE_BORNEE_DES_DEUX_COTES;
-                        variableNamer.ParticipationOfRunningUnitsToReserve(
-                          NombreDeVariables,
-                          clusterName,
-                          areaReserveDown.reserveName);
-                        NombreDeVariables++;
-
-                        // For all units in cluster (off units can not participate to down
-                        // reserves)
-                        variableManager.ThermalClusterReserveParticipation(
-                          clusterReserveParticipation.globalIndexClusterParticipation,
-                          pdt)
-                          = NombreDeVariables;
-                        ProblemeAResoudre->TypeDeVariable[NombreDeVariables]
-                          = VARIABLE_BORNEE_DES_DEUX_COTES;
-                        variableNamer.ThermalClusterReserveParticipation(NombreDeVariables,
-                                                                    clusterName,
-                                                                    areaReserveDown.reserveName);
-                        NombreDeVariables++;
-                    }
+                    reserveVariablesInitializer.initThermalReserveDownParticipation(
+                      pdt,
+                      clusterReserveParticipation,
+                      areaReserveDown.reserveName);
                 }
 
                 // Short Term Storage Clusters
-                for (auto& [clusterId, clusterReserveParticipation] :
+                for (auto& [clusterId, clusterReserveParticipation]:
                      areaReserveDown.AllSTStorageReservesParticipation)
                 {
-                    const auto& clusterName = clusterReserveParticipation.clusterName;
-                    if (Simulation)
-                    {
-                        NombreDeVariables++;
-                    }
-                    else
-                    {
-                        // For Turbining participation to the reserves
-                        variableManager.STStorageTurbiningClusterReserveParticipation(
-                          clusterReserveParticipation.globalIndexClusterParticipation,
-                          pdt)
-                          = NombreDeVariables;
-                        ProblemeAResoudre->TypeDeVariable[NombreDeVariables]
-                          = VARIABLE_BORNEE_DES_DEUX_COTES;
-                        variableNamer.ParticipationOfSTStorageTurbiningToReserve(
-                          NombreDeVariables,
-                          clusterName,
-                          areaReserveDown.reserveName);
-                        NombreDeVariables++;
-                    }
-
-                    if (Simulation)
-                    {
-                        NombreDeVariables++;
-                    }
-                    else
-                    {
-                        // For Pumping participation to the reserves
-                        variableManager.STStoragePumpingClusterReserveParticipation(
-                          clusterReserveParticipation.globalIndexClusterParticipation,
-                          pdt)
-                          = NombreDeVariables;
-                        ProblemeAResoudre->TypeDeVariable[NombreDeVariables]
-                          = VARIABLE_BORNEE_DES_DEUX_COTES;
-                        variableNamer.ParticipationOfSTStoragePumpingToReserve(
-                          NombreDeVariables,
-                          clusterName,
-                          areaReserveDown.reserveName);
-                        NombreDeVariables++;
-                    }
-
-                    if (Simulation)
-                    {
-                        NombreDeVariables++;
-                    }
-                    else
-                    {
-                        // For Short Term Storage participation to the Down reserves
-                        variableManager.STStorageClusterReserveDownParticipation(
-                          clusterReserveParticipation.globalIndexClusterParticipation,
-                          pdt)
-                          = NombreDeVariables;
-                        ProblemeAResoudre->TypeDeVariable[NombreDeVariables]
-                          = VARIABLE_BORNEE_DES_DEUX_COTES;
-                        variableNamer.ParticipationOfSTStorageToDownReserve(
-                          NombreDeVariables,
-                          clusterName,
-                          areaReserveDown.reserveName);
-                        NombreDeVariables++;
-                    }
+                    reserveVariablesInitializer.initSTStorageReserveDownParticipation(
+                      pdt,
+                      clusterReserveParticipation,
+                      areaReserveDown.reserveName);
                 }
 
                 // Long Term Storage Clusters
-                for (auto& clusterReserveParticipation :
+                for (auto& clusterReserveParticipation:
                      areaReserveDown.AllLTStorageReservesParticipation)
                 {
-                    const auto& clusterName = clusterReserveParticipation.clusterName;
-                    if (Simulation)
-                    {
-                        NombreDeVariables++;
-                    }
-                    else
-                    {
-                        // For Turbining participation to the reserves
-                        variableManager.LTStorageTurbiningClusterReserveParticipation(
-                          clusterReserveParticipation.globalIndexClusterParticipation,
-                          pdt)
-                          = NombreDeVariables;
-                        ProblemeAResoudre->TypeDeVariable[NombreDeVariables]
-                          = VARIABLE_BORNEE_DES_DEUX_COTES;
-                        variableNamer.ParticipationOfLTStorageTurbiningToReserve(
-                          NombreDeVariables,
-                          clusterName,
-                          areaReserveDown.reserveName);
-                        NombreDeVariables++;
-                    }
-
-                    if (Simulation)
-                    {
-                        NombreDeVariables++;
-                    }
-                    else
-                    {
-                        // For Pumping participation to the reserves
-                        variableManager.LTStoragePumpingClusterReserveParticipation(
-                          clusterReserveParticipation.globalIndexClusterParticipation,
-                          pdt)
-                          = NombreDeVariables;
-                        ProblemeAResoudre->TypeDeVariable[NombreDeVariables]
-                          = VARIABLE_BORNEE_DES_DEUX_COTES;
-                        variableNamer.ParticipationOfLTStoragePumpingToReserve(
-                          NombreDeVariables,
-                          clusterName,
-                          areaReserveDown.reserveName);
-                        NombreDeVariables++;
-                    }
-
-                    if (Simulation)
-                    {
-                        NombreDeVariables++;
-                    }
-                    else
-                    {
-                        // For Long Term Storage participation to the Down reserves
-                        variableManager.LTStorageClusterReserveDownParticipation(
-                          clusterReserveParticipation.globalIndexClusterParticipation,
-                          pdt)
-                          = NombreDeVariables;
-                        ProblemeAResoudre->TypeDeVariable[NombreDeVariables]
-                          = VARIABLE_BORNEE_DES_DEUX_COTES;
-                        variableNamer.ParticipationOfLTStorageToDownReserve(
-                          NombreDeVariables,
-                          clusterName,
-                          areaReserveDown.reserveName);
-                        NombreDeVariables++;
-                    }
+                    reserveVariablesInitializer.initLTStorageReserveDownParticipation(
+                      pdt,
+                      clusterReserveParticipation,
+                      areaReserveDown.reserveName);
                 }
             }
         }
diff --git a/src/solver/optimisation/opt_gestion_des_bornes_reserves.cpp b/src/solver/optimisation/opt_gestion_des_bornes_reserves.cpp
new file mode 100644
index 0000000000..00b3bf1569
--- /dev/null
+++ b/src/solver/optimisation/opt_gestion_des_bornes_reserves.cpp
@@ -0,0 +1,402 @@
+/*
+** Copyright 2007-2024, RTE (https://www.rte-france.com)
+** See AUTHORS.txt
+** SPDX-License-Identifier: MPL-2.0
+** This file is part of Antares-Simulator,
+** Adequacy and Performance assessment for interconnected energy networks.
+**
+** Antares_Simulator is free software: you can redistribute it and/or modify
+** it under the terms of the Mozilla Public Licence 2.0 as published by
+** the Mozilla Foundation, either version 2 of the License, or
+** (at your option) any later version.
+**
+** Antares_Simulator is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** Mozilla Public Licence 2.0 for more details.
+**
+** You should have received a copy of the Mozilla Public Licence 2.0
+** along with Antares_Simulator. If not, see <https://opensource.org/license/mpl-2-0/>.
+*/
+
+#include "antares/solver/optimisation/opt_fonctions.h"
+#include "antares/solver/optimisation/opt_structure_probleme_a_resoudre.h"
+#include "antares/solver/simulation/sim_structure_donnees.h"
+#include "antares/solver/simulation/sim_structure_probleme_economique.h"
+#include "antares/solver/simulation/simulation.h"
+
+#include "variables/VariableManagement.h"
+#include "variables/VariableManagerUtils.h"
+
+using namespace Yuni;
+
+void OPT_InitialiserLesBornesDesVariablesDuProblemeLineaireReservesThermiques(
+  PROBLEME_HEBDO* problemeHebdo,
+  const int PremierPdtDeLIntervalle,
+  const int DernierPdtDeLIntervalle)
+{
+    struct ReserveVariablesBoundsSetter
+    {
+        PROBLEME_HEBDO* problemeHebdo;
+        const std::unique_ptr<PROBLEME_ANTARES_A_RESOUDRE>& ProblemeAResoudre;
+        std::vector<double>& Xmin;
+        std::vector<double>& Xmax;
+        std::vector<double*>& AdresseOuPlacerLaValeurDesVariablesOptimisees;
+        int pdtJour, pdtHebdo, pays;
+
+        ReserveVariablesBoundsSetter(PROBLEME_HEBDO* hebdo):
+            problemeHebdo(hebdo),
+            ProblemeAResoudre(hebdo->ProblemeAResoudre),
+            Xmin(ProblemeAResoudre->Xmin),
+            Xmax(ProblemeAResoudre->Xmax),
+            AdresseOuPlacerLaValeurDesVariablesOptimisees(
+              ProblemeAResoudre->AdresseOuPlacerLaValeurDesVariablesOptimisees),
+            pdtJour(0),
+            pdtHebdo(0),
+            pays(0)
+        {
+        }
+
+        void setPdtJour(int pdt)
+        {
+            pdtJour = pdt;
+        }
+
+        void setPdtHebdo(int pdt)
+        {
+            pdtHebdo = pdt;
+        }
+
+        void setPays(int p)
+        {
+            pays = p;
+        }
+
+        // Set variables bounds for a reserve
+        void setReserveBounds(int reserveIdInArea, int reserveId)
+        {
+            const auto& CorrespondanceVarNativesVarOptim = problemeHebdo
+                                                             ->CorrespondanceVarNativesVarOptim
+                                                               [pdtJour];
+            int var = CorrespondanceVarNativesVarOptim.internalUnsatisfiedReserveIndex[reserveId];
+            Xmin[var] = 0;
+            Xmax[var] = LINFINI_ANTARES;
+            double* adresseDuResultat = &(problemeHebdo->ResultatsHoraires[pays]
+                                            .Reserves[pdtHebdo]
+                                            .ValeursHorairesInternalUnsatisfied[reserveIdInArea]);
+            AdresseOuPlacerLaValeurDesVariablesOptimisees[var] = adresseDuResultat;
+
+            var = CorrespondanceVarNativesVarOptim.internalExcessReserveIndex[reserveId];
+            Xmin[var] = 0;
+            Xmax[var] = LINFINI_ANTARES;
+            adresseDuResultat = &(problemeHebdo->ResultatsHoraires[pays]
+                                    .Reserves[pdtHebdo]
+                                    .ValeursHorairesInternalExcessReserve[reserveIdInArea]);
+            AdresseOuPlacerLaValeurDesVariablesOptimisees[var] = adresseDuResultat;
+        }
+
+        // Set variables bounds for a Thermal cluster participation to a reserve up
+        void setThermalReserveUpParticipationBounds(int clusterParticipationIdInArea,
+                                                    int clusterParticipationId,
+                                                    int clusterIdInArea,
+                                                    int clusterId)
+        {
+            const auto& CorrespondanceVarNativesVarOptim = problemeHebdo
+                                                             ->CorrespondanceVarNativesVarOptim
+                                                               [pdtJour];
+            int var = CorrespondanceVarNativesVarOptim
+                        .runningThermalClusterReserveParticipationIndex[clusterParticipationId];
+            Xmin[var] = 0;
+            Xmax[var] = LINFINI_ANTARES;
+            double* adresseDuResultat = &(
+              problemeHebdo->ResultatsHoraires[pays]
+                .ProductionThermique[pdtHebdo]
+                .ParticipationReservesDuPalierOn[clusterParticipationIdInArea]);
+            AdresseOuPlacerLaValeurDesVariablesOptimisees[var] = adresseDuResultat;
+
+            var = CorrespondanceVarNativesVarOptim
+                    .offThermalClusterReserveParticipationIndex[clusterParticipationId];
+            Xmin[var] = 0;
+            Xmax[var] = LINFINI_ANTARES;
+            adresseDuResultat = &(
+              problemeHebdo->ResultatsHoraires[pays]
+                .ProductionThermique[pdtHebdo]
+                .ParticipationReservesDuPalierOff[clusterParticipationIdInArea]);
+            AdresseOuPlacerLaValeurDesVariablesOptimisees[var] = adresseDuResultat;
+
+            var = CorrespondanceVarNativesVarOptim
+                    .nbOffGroupUnitsParticipatingToReservesInThermalClusterIndex
+                      [clusterParticipationId];
+            Xmin[var] = 0;
+            Xmax[var] = problemeHebdo->PaliersThermiquesDuPays[pays]
+                          .TailleUnitaireDUnGroupeDuPalierThermique[clusterId];
+            adresseDuResultat = &(
+              problemeHebdo->ResultatsHoraires[pays]
+                .ProductionThermique[pdtHebdo]
+                .NombreDeGroupesEteintDuPalierQuiParticipentAuxReserves[clusterIdInArea]);
+            AdresseOuPlacerLaValeurDesVariablesOptimisees[var] = adresseDuResultat;
+
+            var = CorrespondanceVarNativesVarOptim
+                    .thermalClusterReserveParticipationIndex[clusterParticipationId];
+            Xmin[var] = 0;
+            Xmax[var] = LINFINI_ANTARES;
+            adresseDuResultat = &(problemeHebdo->ResultatsHoraires[pays]
+                                    .ProductionThermique[pdtHebdo]
+                                    .ParticipationReservesDuPalier[clusterParticipationIdInArea]);
+            AdresseOuPlacerLaValeurDesVariablesOptimisees[var] = adresseDuResultat;
+        }
+
+        // Set variables bounds for a Thermal cluster participation to a reserve down
+        void setThermalReserveDownParticipationBounds(int clusterParticipationIdInArea,
+                                                      int clusterParticipationId)
+        {
+            const auto& CorrespondanceVarNativesVarOptim = problemeHebdo
+                                                             ->CorrespondanceVarNativesVarOptim
+                                                               [pdtJour];
+            int var = CorrespondanceVarNativesVarOptim
+                        .runningThermalClusterReserveParticipationIndex[clusterParticipationId];
+            Xmin[var] = 0;
+            Xmax[var] = LINFINI_ANTARES;
+            double* adresseDuResultat = &(
+              problemeHebdo->ResultatsHoraires[pays]
+                .ProductionThermique[pdtHebdo]
+                .ParticipationReservesDuPalierOn[clusterParticipationIdInArea]);
+            AdresseOuPlacerLaValeurDesVariablesOptimisees[var] = adresseDuResultat;
+
+            var = CorrespondanceVarNativesVarOptim
+                    .thermalClusterReserveParticipationIndex[clusterParticipationId];
+            Xmin[var] = 0;
+            Xmax[var] = LINFINI_ANTARES;
+            adresseDuResultat = &(problemeHebdo->ResultatsHoraires[pays]
+                                    .ProductionThermique[pdtHebdo]
+                                    .ParticipationReservesDuPalier[clusterParticipationIdInArea]);
+            AdresseOuPlacerLaValeurDesVariablesOptimisees[var] = adresseDuResultat;
+        }
+
+        // Set variables bounds for a ShortTerm cluster participation to a reserve up
+        void setSTStorageReserveUpParticipationBounds(int clusterParticipationIdInArea,
+                                                      int clusterParticipationId)
+        {
+            const auto& CorrespondanceVarNativesVarOptim = problemeHebdo
+                                                             ->CorrespondanceVarNativesVarOptim
+                                                               [pdtJour];
+            int var = CorrespondanceVarNativesVarOptim
+                        .STStorageTurbiningClusterReserveParticipationIndex[clusterParticipationId];
+            Xmin[var] = 0;
+            Xmax[var] = LINFINI_ANTARES;
+            double* adresseDuResultat = &(
+              problemeHebdo->ResultatsHoraires[pays]
+                .ShortTermStorage[pdtHebdo]
+                .reserveParticipationOfCluster[clusterParticipationIdInArea]);
+            AdresseOuPlacerLaValeurDesVariablesOptimisees[var] = nullptr;
+
+            var = CorrespondanceVarNativesVarOptim
+                    .STStoragePumpingClusterReserveParticipationIndex[clusterParticipationId];
+            Xmin[var] = 0;
+            Xmax[var] = LINFINI_ANTARES;
+            adresseDuResultat = &(problemeHebdo->ResultatsHoraires[pays]
+                                    .ShortTermStorage[pdtHebdo]
+                                    .reserveParticipationOfCluster[clusterParticipationIdInArea]);
+            AdresseOuPlacerLaValeurDesVariablesOptimisees[var] = nullptr;
+
+            var = CorrespondanceVarNativesVarOptim
+                    .STStorageClusterReserveUpParticipationIndex[clusterParticipationId];
+            Xmin[var] = 0;
+            Xmax[var] = LINFINI_ANTARES;
+            adresseDuResultat = &(problemeHebdo->ResultatsHoraires[pays]
+                                    .ShortTermStorage[pdtHebdo]
+                                    .reserveParticipationOfCluster[clusterParticipationIdInArea]);
+            AdresseOuPlacerLaValeurDesVariablesOptimisees[var] = adresseDuResultat;
+        }
+
+        // Set variables bounds for a ShortTerm cluster participation to a reserve down
+        void setSTStorageReserveDownParticipationBounds(int clusterParticipationIdInArea,
+                                                        int clusterParticipationId)
+        {
+            const auto& CorrespondanceVarNativesVarOptim = problemeHebdo
+                                                             ->CorrespondanceVarNativesVarOptim
+                                                               [pdtJour];
+            int var = CorrespondanceVarNativesVarOptim
+                        .STStorageTurbiningClusterReserveParticipationIndex[clusterParticipationId];
+            Xmin[var] = 0;
+            Xmax[var] = LINFINI_ANTARES;
+            double* adresseDuResultat = &(
+              problemeHebdo->ResultatsHoraires[pays]
+                .ShortTermStorage[pdtHebdo]
+                .reserveParticipationOfCluster[clusterParticipationIdInArea]);
+            AdresseOuPlacerLaValeurDesVariablesOptimisees[var] = nullptr;
+
+            var = CorrespondanceVarNativesVarOptim
+                    .STStoragePumpingClusterReserveParticipationIndex[clusterParticipationId];
+            Xmin[var] = 0;
+            Xmax[var] = LINFINI_ANTARES;
+            adresseDuResultat = &(problemeHebdo->ResultatsHoraires[pays]
+                                    .ShortTermStorage[pdtHebdo]
+                                    .reserveParticipationOfCluster[clusterParticipationIdInArea]);
+            AdresseOuPlacerLaValeurDesVariablesOptimisees[var] = nullptr;
+
+            var = CorrespondanceVarNativesVarOptim
+                    .STStorageClusterReserveDownParticipationIndex[clusterParticipationId];
+            Xmin[var] = 0;
+            Xmax[var] = LINFINI_ANTARES;
+            adresseDuResultat = &(problemeHebdo->ResultatsHoraires[pays]
+                                    .ShortTermStorage[pdtHebdo]
+                                    .reserveParticipationOfCluster[clusterParticipationIdInArea]);
+            AdresseOuPlacerLaValeurDesVariablesOptimisees[var] = adresseDuResultat;
+        }
+
+        // Set variables bounds for a LongTerm cluster participation to a reserve up
+        void setLTStorageReserveUpParticipationBounds(int clusterParticipationIdInArea,
+                                                      int clusterParticipationId)
+        {
+            const auto& CorrespondanceVarNativesVarOptim = problemeHebdo
+                                                             ->CorrespondanceVarNativesVarOptim
+                                                               [pdtJour];
+            int var = CorrespondanceVarNativesVarOptim
+                        .LTStorageTurbiningClusterReserveParticipationIndex[clusterParticipationId];
+            Xmin[var] = 0;
+            Xmax[var] = LINFINI_ANTARES;
+            double* adresseDuResultat = &(
+              problemeHebdo->ResultatsHoraires[pays]
+                .HydroUsage[pdtHebdo]
+                .reserveParticipationOfCluster[clusterParticipationIdInArea]);
+            AdresseOuPlacerLaValeurDesVariablesOptimisees[var] = nullptr;
+
+            var = CorrespondanceVarNativesVarOptim
+                    .LTStoragePumpingClusterReserveParticipationIndex[clusterParticipationId];
+            Xmin[var] = 0;
+            Xmax[var] = LINFINI_ANTARES;
+            adresseDuResultat = &(problemeHebdo->ResultatsHoraires[pays]
+                                    .HydroUsage[pdtHebdo]
+                                    .reserveParticipationOfCluster[clusterParticipationIdInArea]);
+            AdresseOuPlacerLaValeurDesVariablesOptimisees[var] = nullptr;
+
+            var = CorrespondanceVarNativesVarOptim
+                    .LTStorageClusterReserveUpParticipationIndex[clusterParticipationId];
+            Xmin[var] = 0;
+            Xmax[var] = LINFINI_ANTARES;
+            adresseDuResultat = &(problemeHebdo->ResultatsHoraires[pays]
+                                    .HydroUsage[pdtHebdo]
+                                    .reserveParticipationOfCluster[clusterParticipationIdInArea]);
+            AdresseOuPlacerLaValeurDesVariablesOptimisees[var] = adresseDuResultat;
+        }
+
+        // Set variables bounds for a LongTerm cluster participation to a reserve down
+        void setLTStorageReserveDownParticipationBounds(int clusterParticipationIdInArea,
+                                                        int clusterParticipationId)
+        {
+            const auto& CorrespondanceVarNativesVarOptim = problemeHebdo
+                                                             ->CorrespondanceVarNativesVarOptim
+                                                               [pdtJour];
+            int var = CorrespondanceVarNativesVarOptim
+                        .LTStorageTurbiningClusterReserveParticipationIndex[clusterParticipationId];
+            Xmin[var] = 0;
+            Xmax[var] = LINFINI_ANTARES;
+            double* adresseDuResultat = &(
+              problemeHebdo->ResultatsHoraires[pays]
+                .HydroUsage[pdtHebdo]
+                .reserveParticipationOfCluster[clusterParticipationIdInArea]);
+            AdresseOuPlacerLaValeurDesVariablesOptimisees[var] = nullptr;
+
+            var = CorrespondanceVarNativesVarOptim
+                    .LTStoragePumpingClusterReserveParticipationIndex[clusterParticipationId];
+            Xmin[var] = 0;
+            Xmax[var] = LINFINI_ANTARES;
+            adresseDuResultat = &(problemeHebdo->ResultatsHoraires[pays]
+                                    .HydroUsage[pdtHebdo]
+                                    .reserveParticipationOfCluster[clusterParticipationIdInArea]);
+            AdresseOuPlacerLaValeurDesVariablesOptimisees[var] = nullptr;
+
+            var = CorrespondanceVarNativesVarOptim
+                    .LTStorageClusterReserveDownParticipationIndex[clusterParticipationId];
+            Xmin[var] = 0;
+            Xmax[var] = LINFINI_ANTARES;
+            adresseDuResultat = &(problemeHebdo->ResultatsHoraires[pays]
+                                    .HydroUsage[pdtHebdo]
+                                    .reserveParticipationOfCluster[clusterParticipationIdInArea]);
+            AdresseOuPlacerLaValeurDesVariablesOptimisees[var] = adresseDuResultat;
+        }
+    };
+
+    ReserveVariablesBoundsSetter reserveVariablesBoundsSetter(problemeHebdo);
+
+    for (int pdtHebdo = PremierPdtDeLIntervalle, pdtJour = 0; pdtHebdo < DernierPdtDeLIntervalle;
+         pdtHebdo++, pdtJour++)
+    {
+        reserveVariablesBoundsSetter.setPdtJour(pdtJour);
+        reserveVariablesBoundsSetter.setPdtHebdo(pdtHebdo);
+
+        for (uint32_t pays = 0; pays < problemeHebdo->NombreDePays; pays++)
+        {
+            reserveVariablesBoundsSetter.setPays(pays);
+            const auto& areaReserves = problemeHebdo->allReserves[pays];
+
+            for (const auto& areaReserveUp: areaReserves.areaCapacityReservationsUp)
+            {
+                reserveVariablesBoundsSetter.setReserveBounds(areaReserveUp.areaReserveIndex,
+                                                              areaReserveUp.globalReserveIndex);
+
+                // Thermal Cluster
+                for (const auto& [clusterId, clusterReserveParticipation]:
+                     areaReserveUp.AllThermalReservesParticipation)
+                {
+                    reserveVariablesBoundsSetter.setThermalReserveUpParticipationBounds(
+                      clusterReserveParticipation.areaIndexClusterParticipation,
+                      clusterReserveParticipation.globalIndexClusterParticipation,
+                      clusterReserveParticipation.clusterIdInArea,
+                      clusterId);
+                }
+
+                // Short Term Storage Cluster
+                for (const auto& [clusterId, clusterReserveParticipation]:
+                     areaReserveUp.AllSTStorageReservesParticipation)
+                {
+                    reserveVariablesBoundsSetter.setSTStorageReserveUpParticipationBounds(
+                      clusterReserveParticipation.areaIndexClusterParticipation,
+                      clusterReserveParticipation.globalIndexClusterParticipation);
+                }
+
+                // Long Term Storage Cluster
+                for (const auto& clusterReserveParticipation:
+                     areaReserveUp.AllLTStorageReservesParticipation)
+                {
+                    reserveVariablesBoundsSetter.setLTStorageReserveUpParticipationBounds(
+                      clusterReserveParticipation.areaIndexClusterParticipation,
+                      clusterReserveParticipation.globalIndexClusterParticipation);
+                }
+            }
+            for (const auto& areaReserveDown: areaReserves.areaCapacityReservationsDown)
+            {
+                reserveVariablesBoundsSetter.setReserveBounds(areaReserveDown.areaReserveIndex,
+                                                              areaReserveDown.globalReserveIndex);
+
+                // Thermal Clusters
+                for (const auto& [clusterId, clusterReserveParticipation]:
+                     areaReserveDown.AllThermalReservesParticipation)
+                {
+                    reserveVariablesBoundsSetter.setThermalReserveDownParticipationBounds(
+                      clusterReserveParticipation.areaIndexClusterParticipation,
+                      clusterReserveParticipation.globalIndexClusterParticipation);
+                }
+
+                // Short Term Storage Cluster
+                for (const auto& [clusterId, clusterReserveParticipation]:
+                     areaReserveDown.AllSTStorageReservesParticipation)
+                {
+                    reserveVariablesBoundsSetter.setSTStorageReserveDownParticipationBounds(
+                      clusterReserveParticipation.areaIndexClusterParticipation,
+                      clusterReserveParticipation.globalIndexClusterParticipation);
+                }
+
+                // Long Term Storage Cluster
+                for (const auto& clusterReserveParticipation:
+                     areaReserveDown.AllLTStorageReservesParticipation)
+                {
+                    reserveVariablesBoundsSetter.setLTStorageReserveDownParticipationBounds(
+                      clusterReserveParticipation.areaIndexClusterParticipation,
+                      clusterReserveParticipation.globalIndexClusterParticipation);
+                }
+            }
+        }
+    }
+}
diff --git a/src/solver/optimisation/opt_gestion_des_bornes_reserves_thermiques.cpp b/src/solver/optimisation/opt_gestion_des_bornes_reserves_thermiques.cpp
deleted file mode 100644
index e13f0ceb94..0000000000
--- a/src/solver/optimisation/opt_gestion_des_bornes_reserves_thermiques.cpp
+++ /dev/null
@@ -1,345 +0,0 @@
-/*
-** Copyright 2007-2024, RTE (https://www.rte-france.com)
-** See AUTHORS.txt
-** SPDX-License-Identifier: MPL-2.0
-** This file is part of Antares-Simulator,
-** Adequacy and Performance assessment for interconnected energy networks.
-**
-** Antares_Simulator is free software: you can redistribute it and/or modify
-** it under the terms of the Mozilla Public Licence 2.0 as published by
-** the Mozilla Foundation, either version 2 of the License, or
-** (at your option) any later version.
-**
-** Antares_Simulator is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** Mozilla Public Licence 2.0 for more details.
-**
-** You should have received a copy of the Mozilla Public Licence 2.0
-** along with Antares_Simulator. If not, see <https://opensource.org/license/mpl-2-0/>.
-*/
-
-#include "antares/solver/optimisation/opt_structure_probleme_a_resoudre.h"
-
-#include "variables/VariableManagement.h"
-#include "variables/VariableManagerUtils.h"
-#include "antares/solver/simulation/simulation.h"
-#include "antares/solver/simulation/sim_structure_donnees.h"
-#include "antares/solver/simulation/sim_structure_probleme_economique.h"
-#include "antares/solver/optimisation/opt_fonctions.h"
-
-using namespace Yuni;
-
-void OPT_InitialiserLesBornesDesVariablesDuProblemeLineaireReservesThermiques(
-  PROBLEME_HEBDO* problemeHebdo,
-  const int PremierPdtDeLIntervalle,
-  const int DernierPdtDeLIntervalle)
-{
-    const auto& ProblemeAResoudre = problemeHebdo->ProblemeAResoudre;
-    std::vector<double>& Xmin = ProblemeAResoudre->Xmin;
-    std::vector<double>& Xmax = ProblemeAResoudre->Xmax;
-
-    std::vector<double*>& AdresseOuPlacerLaValeurDesVariablesOptimisees
-      = ProblemeAResoudre->AdresseOuPlacerLaValeurDesVariablesOptimisees;
-
-    for (int pdtHebdo = PremierPdtDeLIntervalle, pdtJour = 0; pdtHebdo < DernierPdtDeLIntervalle;
-         pdtHebdo++, pdtJour++)
-    {
-        const CORRESPONDANCES_DES_VARIABLES& CorrespondanceVarNativesVarOptim
-          = problemeHebdo->CorrespondanceVarNativesVarOptim[pdtJour];
-
-        for (uint32_t pays = 0; pays < problemeHebdo->NombreDePays; pays++)
-        {
-            auto areaReserves = problemeHebdo->allReserves[pays];
-
-            for (const auto& areaReserveUp : areaReserves.areaCapacityReservationsUp)
-            {
-                int var = CorrespondanceVarNativesVarOptim
-                            .internalUnsatisfiedReserveIndex[areaReserveUp.globalReserveIndex];
-                Xmin[var] = 0;
-                Xmax[var] = LINFINI_ANTARES;
-                double* adresseDuResultat1
-                  = &(problemeHebdo->ResultatsHoraires[pays]
-                        .Reserves[pdtHebdo]
-                        .ValeursHorairesInternalUnsatisfied[areaReserveUp.areaReserveIndex]);
-                AdresseOuPlacerLaValeurDesVariablesOptimisees[var] = adresseDuResultat1;
-
-                var = CorrespondanceVarNativesVarOptim
-                        .internalExcessReserveIndex[areaReserveUp.globalReserveIndex];
-                Xmin[var] = 0;
-                Xmax[var] = LINFINI_ANTARES;
-                double* adresseDuResultat2
-                  = &(problemeHebdo->ResultatsHoraires[pays]
-                        .Reserves[pdtHebdo]
-                        .ValeursHorairesInternalExcessReserve[areaReserveUp.areaReserveIndex]);
-                AdresseOuPlacerLaValeurDesVariablesOptimisees[var] = adresseDuResultat2;
-
-                // Thermal Cluster
-                for (const auto& [clusterId, clusterReserveParticipation] :
-                     areaReserveUp.AllThermalReservesParticipation)
-                {
-                    var = CorrespondanceVarNativesVarOptim
-                            .runningThermalClusterReserveParticipationIndex
-                              [clusterReserveParticipation.globalIndexClusterParticipation];
-                    Xmin[var] = 0;
-                    Xmax[var] = LINFINI_ANTARES;
-                    double* adresseDuResultat = &(
-                      problemeHebdo->ResultatsHoraires[pays]
-                        .ProductionThermique[pdtHebdo]
-                        .ParticipationReservesDuPalierOn[clusterReserveParticipation
-                                                           .areaIndexClusterParticipation]);
-                    AdresseOuPlacerLaValeurDesVariablesOptimisees[var] = adresseDuResultat;
-
-                    var = CorrespondanceVarNativesVarOptim
-                            .offThermalClusterReserveParticipationIndex
-                              [clusterReserveParticipation.globalIndexClusterParticipation];
-                    Xmin[var] = 0;
-                    Xmax[var] = LINFINI_ANTARES;
-                    adresseDuResultat = &(
-                      problemeHebdo->ResultatsHoraires[pays]
-                        .ProductionThermique[pdtHebdo]
-                        .ParticipationReservesDuPalierOff[clusterReserveParticipation
-                                                            .areaIndexClusterParticipation]);
-                    AdresseOuPlacerLaValeurDesVariablesOptimisees[var] = adresseDuResultat;
-
-                    var = CorrespondanceVarNativesVarOptim
-                            .nbOffGroupUnitsParticipatingToReservesInThermalClusterIndex
-                              [clusterReserveParticipation.globalIndexClusterParticipation];
-                    Xmin[var] = 0;
-                     Xmax[var] = problemeHebdo->PaliersThermiquesDuPays[pays].TailleUnitaireDUnGroupeDuPalierThermique[clusterId];
-                    adresseDuResultat = &(
-                      problemeHebdo->ResultatsHoraires[pays]
-                        .ProductionThermique[pdtHebdo]
-                        .NombreDeGroupesEteintDuPalierQuiParticipentAuxReserves
-                          [clusterReserveParticipation.clusterIdInArea]);
-                    AdresseOuPlacerLaValeurDesVariablesOptimisees[var] = adresseDuResultat;
-
-                    var = CorrespondanceVarNativesVarOptim.thermalClusterReserveParticipationIndex
-                            [clusterReserveParticipation.globalIndexClusterParticipation];
-                    Xmin[var] = 0;
-                    Xmax[var] = LINFINI_ANTARES;
-                    adresseDuResultat = &(
-                      problemeHebdo->ResultatsHoraires[pays]
-                        .ProductionThermique[pdtHebdo]
-                        .ParticipationReservesDuPalier[clusterReserveParticipation
-                                                         .areaIndexClusterParticipation]);
-                    AdresseOuPlacerLaValeurDesVariablesOptimisees[var] = adresseDuResultat;
-                }
-
-                // Short Term Storage Cluster
-                for (const auto& [clusterId, clusterReserveParticipation] :
-                     areaReserveUp.AllSTStorageReservesParticipation)
-                {
-                    var = CorrespondanceVarNativesVarOptim
-                            .STStorageTurbiningClusterReserveParticipationIndex
-                              [clusterReserveParticipation.globalIndexClusterParticipation];
-                    Xmin[var] = 0;
-                    Xmax[var] = LINFINI_ANTARES;
-                    double* adresseDuResultat = &(
-                      problemeHebdo->ResultatsHoraires[pays]
-                        .ShortTermStorage[pdtHebdo]
-                        .reserveParticipationOfCluster[clusterReserveParticipation
-                                                         .areaIndexClusterParticipation]);
-                    AdresseOuPlacerLaValeurDesVariablesOptimisees[var] = nullptr;
-
-                    var = CorrespondanceVarNativesVarOptim
-                            .STStoragePumpingClusterReserveParticipationIndex
-                              [clusterReserveParticipation.globalIndexClusterParticipation];
-                    Xmin[var] = 0;
-                    Xmax[var] = LINFINI_ANTARES;
-                    adresseDuResultat = &(
-                      problemeHebdo->ResultatsHoraires[pays]
-                        .ShortTermStorage[pdtHebdo]
-                        .reserveParticipationOfCluster[clusterReserveParticipation
-                                                         .areaIndexClusterParticipation]);
-                    AdresseOuPlacerLaValeurDesVariablesOptimisees[var] = nullptr;
-
-                    var = CorrespondanceVarNativesVarOptim
-                            .STStorageClusterReserveUpParticipationIndex
-                              [clusterReserveParticipation.globalIndexClusterParticipation];
-                    Xmin[var] = 0;
-                    Xmax[var] = LINFINI_ANTARES;
-                    adresseDuResultat = &(
-                      problemeHebdo->ResultatsHoraires[pays]
-                        .ShortTermStorage[pdtHebdo]
-                        .reserveParticipationOfCluster[clusterReserveParticipation
-                                                         .areaIndexClusterParticipation]);
-                    AdresseOuPlacerLaValeurDesVariablesOptimisees[var] = adresseDuResultat;
-                }
-
-                // Long Term Storage Cluster
-                for (const auto& clusterReserveParticipation:
-                     areaReserveUp.AllLTStorageReservesParticipation)
-                {
-                    var = CorrespondanceVarNativesVarOptim
-                            .LTStorageTurbiningClusterReserveParticipationIndex
-                              [clusterReserveParticipation.globalIndexClusterParticipation];
-                    Xmin[var] = 0;
-                    Xmax[var] = LINFINI_ANTARES;
-                    double* adresseDuResultat = &(
-                      problemeHebdo->ResultatsHoraires[pays]
-                        .HydroUsage[pdtHebdo]
-                        .reserveParticipationOfCluster[clusterReserveParticipation
-                                                         .areaIndexClusterParticipation]);
-                    AdresseOuPlacerLaValeurDesVariablesOptimisees[var] = nullptr;
-
-                    var = CorrespondanceVarNativesVarOptim
-                            .LTStoragePumpingClusterReserveParticipationIndex
-                              [clusterReserveParticipation.globalIndexClusterParticipation];
-                    Xmin[var] = 0;
-                    Xmax[var] = LINFINI_ANTARES;
-                    adresseDuResultat = &(
-                      problemeHebdo->ResultatsHoraires[pays]
-                        .HydroUsage[pdtHebdo]
-                        .reserveParticipationOfCluster[clusterReserveParticipation
-                                                         .areaIndexClusterParticipation]);
-                    AdresseOuPlacerLaValeurDesVariablesOptimisees[var] = nullptr;
-
-                    var = CorrespondanceVarNativesVarOptim
-                            .LTStorageClusterReserveUpParticipationIndex
-                              [clusterReserveParticipation.globalIndexClusterParticipation];
-                    Xmin[var] = 0;
-                    Xmax[var] = LINFINI_ANTARES;
-                    adresseDuResultat = &(
-                      problemeHebdo->ResultatsHoraires[pays]
-                        .HydroUsage[pdtHebdo]
-                        .reserveParticipationOfCluster[clusterReserveParticipation
-                                                         .areaIndexClusterParticipation]);
-                    AdresseOuPlacerLaValeurDesVariablesOptimisees[var] = adresseDuResultat;
-                }
-            }
-            for (const auto& areaReserveDown : areaReserves.areaCapacityReservationsDown)
-            {
-                int var = CorrespondanceVarNativesVarOptim
-                            .internalUnsatisfiedReserveIndex[areaReserveDown.globalReserveIndex];
-                Xmin[var] = 0;
-                Xmax[var] = LINFINI_ANTARES;
-                double* adresseDuResultat1
-                  = &(problemeHebdo->ResultatsHoraires[pays]
-                        .Reserves[pdtHebdo]
-                        .ValeursHorairesInternalUnsatisfied[areaReserveDown.areaReserveIndex]);
-                AdresseOuPlacerLaValeurDesVariablesOptimisees[var] = adresseDuResultat1;
-
-                var = CorrespondanceVarNativesVarOptim
-                        .internalExcessReserveIndex[areaReserveDown.globalReserveIndex];
-                Xmin[var] = 0;
-                Xmax[var] = LINFINI_ANTARES;
-                double* adresseDuResultat2
-                  = &(problemeHebdo->ResultatsHoraires[pays]
-                        .Reserves[pdtHebdo]
-                        .ValeursHorairesInternalExcessReserve[areaReserveDown.areaReserveIndex]);
-                AdresseOuPlacerLaValeurDesVariablesOptimisees[var] = adresseDuResultat2;
-
-                // Thermal Clusters
-                for (const auto& [clusterId, clusterReserveParticipation] :
-                     areaReserveDown.AllThermalReservesParticipation)
-                {
-                    var = CorrespondanceVarNativesVarOptim
-                            .runningThermalClusterReserveParticipationIndex
-                              [clusterReserveParticipation.globalIndexClusterParticipation];
-                    Xmin[var] = 0;
-                    Xmax[var] = LINFINI_ANTARES;
-                    double* adresseDuResultat3 = &(
-                      problemeHebdo->ResultatsHoraires[pays]
-                        .ProductionThermique[pdtHebdo]
-                        .ParticipationReservesDuPalierOn[clusterReserveParticipation
-                                                           .areaIndexClusterParticipation]);
-                    AdresseOuPlacerLaValeurDesVariablesOptimisees[var] = adresseDuResultat3;
-
-                    var = CorrespondanceVarNativesVarOptim.thermalClusterReserveParticipationIndex
-                            [clusterReserveParticipation.globalIndexClusterParticipation];
-                    Xmin[var] = 0;
-                    Xmax[var] = LINFINI_ANTARES;
-                    double* adresseDuResultat4 = &(
-                      problemeHebdo->ResultatsHoraires[pays]
-                        .ProductionThermique[pdtHebdo]
-                        .ParticipationReservesDuPalier[clusterReserveParticipation
-                                                         .areaIndexClusterParticipation]);
-                    AdresseOuPlacerLaValeurDesVariablesOptimisees[var] = adresseDuResultat4;
-                }
-
-                // Short Term Storage Cluster
-                for (const auto& [clusterId, clusterReserveParticipation] :
-                     areaReserveDown.AllSTStorageReservesParticipation)
-                {
-                    var = CorrespondanceVarNativesVarOptim
-                            .STStorageTurbiningClusterReserveParticipationIndex
-                              [clusterReserveParticipation.globalIndexClusterParticipation];
-                    Xmin[var] = 0;
-                    Xmax[var] = LINFINI_ANTARES;
-                    double* adresseDuResultat = &(
-                      problemeHebdo->ResultatsHoraires[pays]
-                        .ShortTermStorage[pdtHebdo]
-                        .reserveParticipationOfCluster[clusterReserveParticipation
-                                                         .areaIndexClusterParticipation]);
-                    AdresseOuPlacerLaValeurDesVariablesOptimisees[var] = nullptr;
-
-                    var = CorrespondanceVarNativesVarOptim
-                            .STStoragePumpingClusterReserveParticipationIndex
-                              [clusterReserveParticipation.globalIndexClusterParticipation];
-                    Xmin[var] = 0;
-                    Xmax[var] = LINFINI_ANTARES;
-                    adresseDuResultat = &(
-                      problemeHebdo->ResultatsHoraires[pays]
-                        .ShortTermStorage[pdtHebdo]
-                        .reserveParticipationOfCluster[clusterReserveParticipation
-                                                         .areaIndexClusterParticipation]);
-                    AdresseOuPlacerLaValeurDesVariablesOptimisees[var] = nullptr;
-
-                    var = CorrespondanceVarNativesVarOptim
-                            .STStorageClusterReserveDownParticipationIndex
-                              [clusterReserveParticipation.globalIndexClusterParticipation];
-                    Xmin[var] = 0;
-                    Xmax[var] = LINFINI_ANTARES;
-                    adresseDuResultat = &(
-                      problemeHebdo->ResultatsHoraires[pays]
-                        .ShortTermStorage[pdtHebdo]
-                        .reserveParticipationOfCluster[clusterReserveParticipation
-                                                         .areaIndexClusterParticipation]);
-                    AdresseOuPlacerLaValeurDesVariablesOptimisees[var] = adresseDuResultat;
-                }
-
-                // Long Term Storage Cluster
-                for (const auto& clusterReserveParticipation:
-                     areaReserveDown.AllLTStorageReservesParticipation)
-                {
-                    var = CorrespondanceVarNativesVarOptim
-                            .LTStorageTurbiningClusterReserveParticipationIndex
-                              [clusterReserveParticipation.globalIndexClusterParticipation];
-                    Xmin[var] = 0;
-                    Xmax[var] = LINFINI_ANTARES;
-                    double* adresseDuResultat = &(
-                      problemeHebdo->ResultatsHoraires[pays]
-                        .HydroUsage[pdtHebdo]
-                        .reserveParticipationOfCluster[clusterReserveParticipation
-                                                         .areaIndexClusterParticipation]);
-                    AdresseOuPlacerLaValeurDesVariablesOptimisees[var] = nullptr;
-
-                    var = CorrespondanceVarNativesVarOptim
-                            .LTStoragePumpingClusterReserveParticipationIndex
-                              [clusterReserveParticipation.globalIndexClusterParticipation];
-                    Xmin[var] = 0;
-                    Xmax[var] = LINFINI_ANTARES;
-                    adresseDuResultat = &(
-                      problemeHebdo->ResultatsHoraires[pays]
-                        .HydroUsage[pdtHebdo]
-                        .reserveParticipationOfCluster[clusterReserveParticipation
-                                                         .areaIndexClusterParticipation]);
-                    AdresseOuPlacerLaValeurDesVariablesOptimisees[var] = nullptr;
-
-                    var = CorrespondanceVarNativesVarOptim
-                            .LTStorageClusterReserveDownParticipationIndex
-                              [clusterReserveParticipation.globalIndexClusterParticipation];
-                    Xmin[var] = 0;
-                    Xmax[var] = LINFINI_ANTARES;
-                    adresseDuResultat = &(
-                      problemeHebdo->ResultatsHoraires[pays]
-                        .HydroUsage[pdtHebdo]
-                        .reserveParticipationOfCluster[clusterReserveParticipation
-                                                         .areaIndexClusterParticipation]);
-                    AdresseOuPlacerLaValeurDesVariablesOptimisees[var] = adresseDuResultat;
-                }
-            }
-        }
-    }
-}
diff --git a/src/solver/optimisation/opt_gestion_des_couts_reserves.cpp b/src/solver/optimisation/opt_gestion_des_couts_reserves.cpp
index 521bd2d231..57aafe20ae 100644
--- a/src/solver/optimisation/opt_gestion_des_couts_reserves.cpp
+++ b/src/solver/optimisation/opt_gestion_des_couts_reserves.cpp
@@ -19,132 +19,185 @@
 ** along with Antares_Simulator. If not, see <https://opensource.org/license/mpl-2-0/>.
 */
 
+#include "antares/solver/optimisation/opt_fonctions.h"
 #include "antares/solver/optimisation/opt_structure_probleme_a_resoudre.h"
-
-#include "variables/VariableManagerUtils.h"
-#include "antares/solver/simulation/simulation.h"
 #include "antares/solver/simulation/sim_structure_donnees.h"
+#include "antares/solver/simulation/simulation.h"
 
-#include "antares/solver/optimisation/opt_fonctions.h"
+#include "variables/VariableManagerUtils.h"
 
 void OPT_InitialiserLesCoutsLineaireReserves(PROBLEME_HEBDO* problemeHebdo,
-                                                     const int PremierPdtDeLIntervalle,
-                                                     const int DernierPdtDeLIntervalle)
+                                             const int PremierPdtDeLIntervalle,
+                                             const int DernierPdtDeLIntervalle)
 {
-    const auto& ProblemeAResoudre = problemeHebdo->ProblemeAResoudre;
-    std::vector<double>& CoutLineaire = ProblemeAResoudre->CoutLineaire;
-    auto variableManager = VariableManagerFromProblemHebdo(problemeHebdo);
+    struct ReserveCostsInitializer
+    {
+        PROBLEME_HEBDO* problemeHebdo;
+        const std::unique_ptr<PROBLEME_ANTARES_A_RESOUDRE>& ProblemeAResoudre;
+        VariableManagement::VariableManager variableManager;
+        std::vector<double>& CoutLineaire;
+        int pdtHebdo;
+
+        ReserveCostsInitializer(PROBLEME_HEBDO* hebdo):
+            problemeHebdo(hebdo),
+            ProblemeAResoudre(hebdo->ProblemeAResoudre),
+            variableManager(VariableManagerFromProblemHebdo(hebdo)),
+            CoutLineaire(hebdo->ProblemeAResoudre->CoutLineaire),
+            pdtHebdo(0)
+        {
+        }
+
+        void setPdtHebdo(int pdt)
+        {
+            pdtHebdo = pdt;
+        }
+
+        // Init costs for a reserve
+        void initReserveCosts(const CAPACITY_RESERVATION& reserve)
+        {
+            int var = variableManager.InternalExcessReserve(reserve.globalReserveIndex, pdtHebdo);
+            if (var >= 0 && var < ProblemeAResoudre->NombreDeVariables)
+            {
+                CoutLineaire[var] = reserve.spillageCost;
+            }
+
+            var = variableManager.InternalUnsatisfiedReserve(reserve.globalReserveIndex, pdtHebdo);
+            if (var >= 0 && var < ProblemeAResoudre->NombreDeVariables)
+            {
+                CoutLineaire[var] = reserve.failureCost;
+            }
+        }
+
+        // Init costs for a Thermal cluster participation to a reserve up
+        void initThermalReserveUpParticipationCosts(
+          const RESERVE_PARTICIPATION_THERMAL& reserveParticipation)
+        {
+            int var = variableManager.RunningThermalClusterReserveParticipation(
+              reserveParticipation.globalIndexClusterParticipation,
+              pdtHebdo);
+            CoutLineaire[var] = reserveParticipation.participationCost;
+            var = variableManager.OffThermalClusterReserveParticipation(
+              reserveParticipation.globalIndexClusterParticipation,
+              pdtHebdo);
+            CoutLineaire[var] = reserveParticipation.participationCostOff;
+        }
+
+        // Init costs for a Thermal cluster participation to a reserve down
+        void initThermalReserveDownParticipationCosts(
+          const RESERVE_PARTICIPATION_THERMAL& reserveParticipation)
+        {
+            int var = variableManager.RunningThermalClusterReserveParticipation(
+              reserveParticipation.globalIndexClusterParticipation,
+              pdtHebdo);
+            CoutLineaire[var] = reserveParticipation.participationCost;
+        }
 
-    for (int pdtHebdo = PremierPdtDeLIntervalle; pdtHebdo < DernierPdtDeLIntervalle;
-         pdtHebdo++)
+        // Init costs for a ShortTerm cluster participation to a reserve up
+        void initSTStorageReserveUpParticipationCosts(
+          const RESERVE_PARTICIPATION_STSTORAGE& reserveParticipation)
+        {
+            int var = variableManager.STStorageClusterReserveUpParticipation(
+              reserveParticipation.globalIndexClusterParticipation,
+              pdtHebdo);
+            CoutLineaire[var] = reserveParticipation.participationCost;
+        }
+
+        // Init costs for a ShortTerm cluster participation to a reserve down
+        void initSTStorageReserveDownParticipationCosts(
+          const RESERVE_PARTICIPATION_STSTORAGE& reserveParticipation)
+        {
+            int var = variableManager.STStorageClusterReserveDownParticipation(
+              reserveParticipation.globalIndexClusterParticipation,
+              pdtHebdo);
+            CoutLineaire[var] = reserveParticipation.participationCost;
+        }
+
+        // Init costs for a LongTerm cluster participation to a reserve up
+        void initLTStorageReserveUpParticipationCosts(
+          const RESERVE_PARTICIPATION_LTSTORAGE& reserveParticipation)
+        {
+            int var = variableManager.LTStorageClusterReserveUpParticipation(
+              reserveParticipation.globalIndexClusterParticipation,
+              pdtHebdo);
+            CoutLineaire[var] = reserveParticipation.participationCost;
+        }
+
+        // Init costs for a LongTerm cluster participation to a reserve down
+        void initLTStorageReserveDownParticipationCosts(
+          const RESERVE_PARTICIPATION_LTSTORAGE& reserveParticipation)
+        {
+            int var = variableManager.LTStorageClusterReserveDownParticipation(
+              reserveParticipation.globalIndexClusterParticipation,
+              pdtHebdo);
+            CoutLineaire[var] = reserveParticipation.participationCost;
+        }
+    };
+
+    ReserveCostsInitializer reserveCostsInitializer(problemeHebdo);
+
+    for (int pdtHebdo = PremierPdtDeLIntervalle; pdtHebdo < DernierPdtDeLIntervalle; pdtHebdo++)
     {
+        reserveCostsInitializer.setPdtHebdo(pdtHebdo);
         for (uint32_t pays = 0; pays < problemeHebdo->NombreDePays; pays++)
         {
-            auto reservesDuPays = problemeHebdo->allReserves[pays];
+            auto areaReserves = problemeHebdo->allReserves[pays];
             int var;
 
-            for (int index = 0; index < reservesDuPays.areaCapacityReservationsUp.size(); index++)
+            for (auto& areaReserveUp: areaReserves.areaCapacityReservationsUp)
             {
+                reserveCostsInitializer.initReserveCosts(areaReserveUp);
+
                 // Thermal clusters
-                for (const auto& [clusterId, clusterReserveParticipation] :
-                     reservesDuPays.areaCapacityReservationsUp[index]
-                       .AllThermalReservesParticipation)
+                for (const auto& [clusterId, clusterReserveParticipation]:
+                     areaReserveUp.AllThermalReservesParticipation)
                 {
-                    var = variableManager.RunningThermalClusterReserveParticipation(
-                      clusterReserveParticipation.globalIndexClusterParticipation,
-                      pdtHebdo);
-                    CoutLineaire[var] = clusterReserveParticipation.participationCost;
-                    var = variableManager.OffThermalClusterReserveParticipation(
-                      clusterReserveParticipation.globalIndexClusterParticipation,
-                      pdtHebdo);
-                    CoutLineaire[var] = clusterReserveParticipation.participationCostOff;
+                    reserveCostsInitializer.initThermalReserveUpParticipationCosts(
+                      clusterReserveParticipation);
                 }
 
                 // Short Term Storage clusters
-                for (const auto& [clusterId, clusterReserveParticipation] :
-                     reservesDuPays.areaCapacityReservationsUp[index]
-                       .AllSTStorageReservesParticipation)
+                for (const auto& [clusterId, clusterReserveParticipation]:
+                     areaReserveUp.AllSTStorageReservesParticipation)
                 {
-                    var = variableManager.STStorageClusterReserveUpParticipation(
-                      clusterReserveParticipation.globalIndexClusterParticipation,
-                      pdtHebdo);
-                    CoutLineaire[var] = clusterReserveParticipation.participationCost;
+                    reserveCostsInitializer.initSTStorageReserveUpParticipationCosts(
+                      clusterReserveParticipation);
                 }
 
                 // Long Term Storage clusters
                 for (const auto& clusterReserveParticipation:
-                     reservesDuPays.areaCapacityReservationsUp[index]
-                       .AllLTStorageReservesParticipation)
+                     areaReserveUp.AllLTStorageReservesParticipation)
                 {
-                    var = variableManager.LTStorageClusterReserveUpParticipation(
-                      clusterReserveParticipation.globalIndexClusterParticipation,
-                      pdtHebdo);
-                    CoutLineaire[var] = clusterReserveParticipation.participationCost;
-                }
-
-                var = variableManager.InternalExcessReserve(
-                  reservesDuPays.areaCapacityReservationsUp[index].globalReserveIndex, pdtHebdo);
-                if (var >= 0 && var < ProblemeAResoudre->NombreDeVariables)
-                {
-                    CoutLineaire[var] = reservesDuPays.areaCapacityReservationsUp[index].spillageCost;
-                }
-
-               var = variableManager.InternalUnsatisfiedReserve(
-                  reservesDuPays.areaCapacityReservationsUp[index].globalReserveIndex, pdtHebdo);
-                if (var >= 0 && var < ProblemeAResoudre->NombreDeVariables)
-                {
-                    CoutLineaire[var] = reservesDuPays.areaCapacityReservationsUp[index].failureCost;
+                    reserveCostsInitializer.initLTStorageReserveUpParticipationCosts(
+                      clusterReserveParticipation);
                 }
             }
 
-            for (int index = 0; index < reservesDuPays.areaCapacityReservationsDown.size(); index++)
+            for (auto& areaReserveDown: areaReserves.areaCapacityReservationsDown)
             {
+                reserveCostsInitializer.initReserveCosts(areaReserveDown);
+
                 // Thermal clusters
-                for (const auto& [clusterId, clusterReserveParticipation] :
-                     reservesDuPays.areaCapacityReservationsDown[index]
-                       .AllThermalReservesParticipation)
+                for (const auto& [clusterId, clusterReserveParticipation]:
+                     areaReserveDown.AllThermalReservesParticipation)
                 {
-                    var = variableManager.RunningThermalClusterReserveParticipation(
-                      clusterReserveParticipation.globalIndexClusterParticipation,
-                      pdtHebdo);
-                    CoutLineaire[var] = clusterReserveParticipation.participationCost;
+                    reserveCostsInitializer.initThermalReserveDownParticipationCosts(
+                      clusterReserveParticipation);
                 }
 
                 // Short Term Storage clusters
-                for (const auto& [clusterId, clusterReserveParticipation] :
-                     reservesDuPays.areaCapacityReservationsDown[index]
-                       .AllSTStorageReservesParticipation)
+                for (const auto& [clusterId, clusterReserveParticipation]:
+                     areaReserveDown.AllSTStorageReservesParticipation)
                 {
-                    var = variableManager.STStorageClusterReserveDownParticipation(
-                      clusterReserveParticipation.globalIndexClusterParticipation,
-                      pdtHebdo);
-                    CoutLineaire[var] = clusterReserveParticipation.participationCost;
+                    reserveCostsInitializer.initSTStorageReserveDownParticipationCosts(
+                      clusterReserveParticipation);
                 }
 
                 // Long Term Storage clusters
                 for (const auto& clusterReserveParticipation:
-                     reservesDuPays.areaCapacityReservationsDown[index]
-                       .AllLTStorageReservesParticipation)
-                {
-                    var = variableManager.LTStorageClusterReserveDownParticipation(
-                      clusterReserveParticipation.globalIndexClusterParticipation,
-                      pdtHebdo);
-                    CoutLineaire[var] = clusterReserveParticipation.participationCost;
-                }
-
-                var = variableManager.InternalExcessReserve(
-                  reservesDuPays.areaCapacityReservationsDown[index].globalReserveIndex, pdtHebdo);
-                if (var >= 0 && var < ProblemeAResoudre->NombreDeVariables)
-                {
-                    CoutLineaire[var]
-                      = reservesDuPays.areaCapacityReservationsDown[index].spillageCost;
-                }
-
-                var = variableManager.InternalUnsatisfiedReserve(
-                  reservesDuPays.areaCapacityReservationsDown[index].globalReserveIndex, pdtHebdo);
-                if (var >= 0 && var < ProblemeAResoudre->NombreDeVariables)
+                     areaReserveDown.AllLTStorageReservesParticipation)
                 {
-                    CoutLineaire[var] = reservesDuPays.areaCapacityReservationsDown[index].failureCost;
+                    reserveCostsInitializer.initLTStorageReserveDownParticipationCosts(
+                      clusterReserveParticipation);
                 }
             }
         }
diff --git a/src/solver/optimisation/opt_gestion_second_membre_reserves.cpp b/src/solver/optimisation/opt_gestion_second_membre_reserves.cpp
index 3906dac0e7..c6cd179ec8 100644
--- a/src/solver/optimisation/opt_gestion_second_membre_reserves.cpp
+++ b/src/solver/optimisation/opt_gestion_second_membre_reserves.cpp
@@ -19,14 +19,11 @@
 ** along with Antares_Simulator. If not, see <https://opensource.org/license/mpl-2-0/>.
 */
 
+#include <antares/study/study.h>
+#include "antares/solver/optimisation/opt_fonctions.h"
 #include "antares/solver/optimisation/opt_structure_probleme_a_resoudre.h"
-
 #include "antares/solver/simulation/sim_structure_donnees.h"
 
-#include "antares/solver/optimisation/opt_fonctions.h"
-
-#include <antares/study/study.h>
-
 using namespace Antares;
 using namespace Antares::Data;
 using namespace Yuni;
@@ -41,457 +38,538 @@ void OPT_InitialiserLeSecondMembreDuProblemeLineaireReserves(PROBLEME_HEBDO* pro
     std::vector<double*>& AdresseOuPlacerLaValeurDesCoutsMarginaux
       = ProblemeAResoudre->AdresseOuPlacerLaValeurDesCoutsMarginaux;
 
-    auto& areaReserves = problemeHebdo->allReserves;
+    struct ReserveVariablesRightSidesSetter
+    {
+        PROBLEME_HEBDO* problemeHebdo;
+        const std::unique_ptr<PROBLEME_ANTARES_A_RESOUDRE>& ProblemeAResoudre;
+        std::vector<double>& SecondMembre;
+        std::vector<double*>& AdresseOuPlacerLaValeurDesCoutsMarginaux;
+        int pdtJour, pdtHebdo, pdtGlobal, pays;
+
+        ReserveVariablesRightSidesSetter(PROBLEME_HEBDO* hebdo):
+            problemeHebdo(hebdo),
+            ProblemeAResoudre(hebdo->ProblemeAResoudre),
+            SecondMembre(ProblemeAResoudre->SecondMembre),
+            AdresseOuPlacerLaValeurDesCoutsMarginaux(
+              ProblemeAResoudre->AdresseOuPlacerLaValeurDesCoutsMarginaux),
+            pdtJour(0),
+            pdtHebdo(0),
+            pdtGlobal(0),
+            pays(0)
+        {
+        }
+
+        void setPdtJour(int pdt)
+        {
+            pdtJour = pdt;
+        }
+
+        void setPdtHebdo(int pdt)
+        {
+            pdtHebdo = pdt;
+        }
+
+        void setPdtGlobal(int pdt)
+        {
+            pdtGlobal = pdt;
+        }
+
+        void setPays(int p)
+        {
+            pays = p;
+        }
+
+        // Set the rigth sides of equations for a reserve
+        void setReserveRightSides(const CAPACITY_RESERVATION& reserve)
+        {
+            const auto& CorrespondanceCntNativesCntOptim = problemeHebdo
+                                                             ->CorrespondanceCntNativesCntOptim
+                                                               [pdtJour];
+            int cnt = CorrespondanceCntNativesCntOptim
+                        .NumeroDeContrainteDesContraintesDeBesoinEnReserves[reserve
+                                                                              .globalReserveIndex];
+            if (cnt >= 0)
+            {
+                SecondMembre[cnt] = reserve.need.at(pdtGlobal);
+                double* adresseDuResultat = &(problemeHebdo->ResultatsHoraires[pays]
+                                                .Reserves[pdtHebdo]
+                                                .CoutsMarginauxHoraires[reserve.areaReserveIndex]);
+                AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = adresseDuResultat;
+            }
+        }
+
+        // Common setter for the thermal clusters
+        void setThermalReserveParticipationRightSides(
+          const RESERVE_PARTICIPATION_THERMAL& reserveParticipation)
+        {
+            const auto& CorrespondanceCntNativesCntOptim = problemeHebdo
+                                                             ->CorrespondanceCntNativesCntOptim
+                                                               [pdtJour];
+            int cnt = CorrespondanceCntNativesCntOptim
+                        .NumeroDeContrainteDesContraintesDePuissanceMinDuPalier[reserveParticipation
+                                                                                  .clusterIdInArea];
+            if (cnt >= 0)
+            {
+                SecondMembre[cnt] = problemeHebdo->PaliersThermiquesDuPays[pays]
+                                      .PuissanceDisponibleEtCout[reserveParticipation
+                                                                   .clusterIdInArea]
+                                      .PuissanceMinDuPalierThermiqueRef[pdtJour];
+                AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr;
+            }
+
+            cnt = CorrespondanceCntNativesCntOptim
+                    .NumeroDeContrainteDesContraintesDePuissanceMaxDuPalier[reserveParticipation
+                                                                              .clusterIdInArea];
+            if (cnt >= 0)
+            {
+                SecondMembre[cnt] = problemeHebdo->PaliersThermiquesDuPays[pays]
+                                      .PuissanceDisponibleEtCout[reserveParticipation
+                                                                   .clusterIdInArea]
+                                      .PuissanceDisponibleDuPalierThermiqueRef[pdtJour];
+                AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr;
+            }
+        }
+
+        // Set the rigth sides of equations for a Thermal cluster participation to a reserve up
+        void setThermalReserveUpParticipationRightSides(
+          const RESERVE_PARTICIPATION_THERMAL& reserveParticipation)
+        {
+            setThermalReserveParticipationRightSides(reserveParticipation);
+            const auto& CorrespondanceCntNativesCntOptim = problemeHebdo
+                                                             ->CorrespondanceCntNativesCntOptim
+                                                               [pdtJour];
+            int cnt = CorrespondanceCntNativesCntOptim
+                        .nbOffGroupUnitsParticipatingToReservesInThermalClusterConstraintIndex
+                          [reserveParticipation.globalIndexClusterParticipation];
+            if (cnt >= 0)
+            {
+                SecondMembre[cnt] = problemeHebdo->PaliersThermiquesDuPays[pays]
+                                      .PuissanceDisponibleEtCout[reserveParticipation
+                                                                   .clusterIdInArea]
+                                      .NombreMaxDeGroupesEnMarcheDuPalierThermique[pdtJour];
+                AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr;
+            }
+        }
+
+        // Set the rigth sides of equations for a Thermal cluster participation to a reserve down
+        void setThermalReserveDownParticipationRightSides(
+          const RESERVE_PARTICIPATION_THERMAL& reserveParticipation)
+        {
+            setThermalReserveParticipationRightSides(reserveParticipation);
+        }
+
+        // Common setter for the ShortTerm Storage clusters
+        void setSTStorageReserveParticipationRightSides(
+          const RESERVE_PARTICIPATION_STSTORAGE& reserveParticipation,
+          const AREA_RESERVES_VECTOR& reserves,
+          const CAPACITY_RESERVATION& reserve)
+        {
+            const auto& CorrespondanceCntNativesCntOptim = problemeHebdo
+                                                             ->CorrespondanceCntNativesCntOptim
+                                                               [pdtJour];
+            int cnt
+              = CorrespondanceCntNativesCntOptim
+                  .NumeroDeContrainteDesContraintesSTStorageClusterTurbiningCapacityThreasholdsMax
+                    [reserveParticipation.clusterId];
+
+            auto& cluster = problemeHebdo->ShortTermStorage[pays][reserveParticipation.clusterId];
+            if (cnt >= 0)
+            {
+                SecondMembre[cnt] = cluster.series.get()->maxWithdrawalModulation[pdtGlobal]
+                                    * cluster.withdrawalNominalCapacity;
+                AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr;
+            }
+
+            cnt = CorrespondanceCntNativesCntOptim
+                    .NumeroDeContrainteDesContraintesSTStorageClusterTurbiningCapacityThreasholdsMin
+                      [reserveParticipation.clusterId];
+            if (cnt >= 0)
+            {
+                SecondMembre[cnt] = cluster.series.get()->lowerRuleCurve[pdtGlobal]
+                                    * cluster.withdrawalNominalCapacity;
+                AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr;
+            }
+
+            cnt = CorrespondanceCntNativesCntOptim
+                    .NumeroDeContrainteDesContraintesSTStorageClusterPumpingCapacityThreasholds
+                      [reserveParticipation.clusterId];
+            if (cnt >= 0)
+            {
+                SecondMembre[cnt] = cluster.series.get()->maxInjectionModulation[pdtGlobal]
+                                    * cluster.injectionNominalCapacity;
+                AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr;
+            }
+            double level_max = cluster.reservoirCapacity
+                               * cluster.series->upperRuleCurve[pdtGlobal];
+            double level_min = cluster.reservoirCapacity
+                               * cluster.series->lowerRuleCurve[pdtGlobal];
+
+            cnt = CorrespondanceCntNativesCntOptim
+                    .NumeroDeContrainteDesContraintesSTStockLevelReserveParticipationDown
+                      [reserveParticipation.clusterId];
+            if (cnt >= 0)
+            {
+                SecondMembre[cnt] = level_max;
+                AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr;
+            }
 
-    for (int pdtJour = 0, pdtHebdo = PremierPdtDeLIntervalle; pdtHebdo < DernierPdtDeLIntervalle;
+            cnt = CorrespondanceCntNativesCntOptim
+                    .NumeroDeContrainteDesContraintesSTStockLevelReserveParticipationUp
+                      [reserveParticipation.clusterId];
+            if (cnt >= 0)
+            {
+                SecondMembre[cnt] = -level_min;
+                AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr;
+            }
+
+            cnt
+              = CorrespondanceCntNativesCntOptim
+                  .NumeroDeContrainteDesContraintesSTGlobalStockEnergyLevelReserveParticipationDown
+                    [reserveParticipation.clusterId];
+            if (cnt >= 0)
+            {
+                SecondMembre[cnt] = reserves.maxGlobalActivationDurationDown
+                                    * reserves.maxGlobalEnergyActivationRatioDown * level_max;
+                AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr;
+            }
+
+            cnt = CorrespondanceCntNativesCntOptim
+                    .NumeroDeContrainteDesContraintesSTGlobalStockEnergyLevelReserveParticipationUp
+                      [reserveParticipation.clusterId];
+            if (cnt >= 0)
+            {
+                SecondMembre[cnt] = -reserves.maxGlobalActivationDurationUp
+                                    * reserves.maxGlobalEnergyActivationRatioUp * level_min;
+                AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr;
+            }
+        }
+
+        // Set the rigth sides of equations for a ShortTerm cluster participation to a reserve up
+        void setSTStorageReserveUpParticipationRightSides(
+          const RESERVE_PARTICIPATION_STSTORAGE& reserveParticipation,
+          const AREA_RESERVES_VECTOR& reserves,
+          const CAPACITY_RESERVATION& reserve)
+        {
+            setSTStorageReserveParticipationRightSides(reserveParticipation, reserves, reserve);
+            const auto& CorrespondanceCntNativesCntOptim = problemeHebdo
+                                                             ->CorrespondanceCntNativesCntOptim
+                                                               [pdtJour];
+            int cnt = CorrespondanceCntNativesCntOptim
+                        .NumeroDeContrainteDesContraintesSTStorageClusterMaxWithdrawParticipation
+                          [reserveParticipation.globalIndexClusterParticipation];
+            if (cnt >= 0)
+            {
+                SecondMembre[cnt] = reserveParticipation.maxTurbining;
+                AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr;
+            }
+            cnt = CorrespondanceCntNativesCntOptim
+                    .NumeroDeContrainteDesContraintesSTStorageClusterMaxInjectionParticipation
+                      [reserveParticipation.globalIndexClusterParticipation];
+            if (cnt >= 0)
+            {
+                SecondMembre[cnt] = reserveParticipation.maxPumping;
+                AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr;
+            }
+            cnt = CorrespondanceCntNativesCntOptim
+                    .NumeroDeContrainteDesContraintesSTStockEnergyLevelReserveParticipation
+                      [reserveParticipation.globalIndexClusterParticipation];
+            if (cnt >= 0)
+            {
+                auto& cluster = problemeHebdo
+                                  ->ShortTermStorage[pays][reserveParticipation.clusterIdInArea];
+                double level_min = cluster.reservoirCapacity
+                                   * cluster.series->lowerRuleCurve[pdtGlobal];
+
+                SecondMembre[cnt] = -reserve.maxEnergyActivationRatio
+                                    * reserve.maxActivationDuration * level_min;
+                AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr;
+            }
+        }
+
+        // Set the rigth sides of equations for a ShortTerm cluster participation to a reserve down
+        void setSTStorageReserveDownParticipationRightSides(
+          const RESERVE_PARTICIPATION_STSTORAGE& reserveParticipation,
+          const AREA_RESERVES_VECTOR& reserves,
+          const CAPACITY_RESERVATION& reserve)
+        {
+            setSTStorageReserveParticipationRightSides(reserveParticipation, reserves, reserve);
+            const auto& CorrespondanceCntNativesCntOptim = problemeHebdo
+                                                             ->CorrespondanceCntNativesCntOptim
+                                                               [pdtJour];
+            int cnt = CorrespondanceCntNativesCntOptim
+                        .NumeroDeContrainteDesContraintesSTStorageClusterMaxWithdrawParticipation
+                          [reserveParticipation.globalIndexClusterParticipation];
+            if (cnt >= 0)
+            {
+                SecondMembre[cnt] = reserveParticipation.maxTurbining;
+                AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr;
+            }
+            cnt = CorrespondanceCntNativesCntOptim
+                    .NumeroDeContrainteDesContraintesSTStorageClusterMaxInjectionParticipation
+                      [reserveParticipation.globalIndexClusterParticipation];
+            if (cnt >= 0)
+            {
+                SecondMembre[cnt] = reserveParticipation.maxPumping;
+                AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr;
+            }
+            cnt = CorrespondanceCntNativesCntOptim
+                    .NumeroDeContrainteDesContraintesSTStockEnergyLevelReserveParticipation
+                      [reserveParticipation.globalIndexClusterParticipation];
+            if (cnt >= 0)
+            {
+                auto& cluster = problemeHebdo
+                                  ->ShortTermStorage[pays][reserveParticipation.clusterIdInArea];
+                double level_max = cluster.reservoirCapacity
+                                   * cluster.series->upperRuleCurve[pdtGlobal];
+                SecondMembre[cnt] = reserve.maxEnergyActivationRatio * reserve.maxActivationDuration
+                                    * level_max;
+                AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr;
+            }
+        }
+
+        // Common setter for the LongTerm Storage clusters
+        void setLTStorageReserveParticipationRightSides(
+          const RESERVE_PARTICIPATION_LTSTORAGE& reserveParticipation,
+          const AREA_RESERVES_VECTOR& reserves,
+          const CAPACITY_RESERVATION& reserve)
+        {
+            const auto& CorrespondanceCntNativesCntOptim = problemeHebdo
+                                                             ->CorrespondanceCntNativesCntOptim
+                                                               [pdtJour];
+            auto& hydroCluster = problemeHebdo->CaracteristiquesHydrauliques[pays];
+            int globalClusterIdx = hydroCluster.GlobalHydroIndex;
+
+            int cnt
+              = CorrespondanceCntNativesCntOptim
+                  .NumeroDeContrainteDesContraintesLTStorageClusterTurbiningCapacityThreasholdsMax
+                    [globalClusterIdx];
+            if (cnt >= 0)
+            {
+                SecondMembre[cnt] = hydroCluster.ContrainteDePmaxHydrauliqueHoraire[pdtJour];
+                AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr;
+            }
+
+            cnt = CorrespondanceCntNativesCntOptim
+                    .NumeroDeContrainteDesContraintesLTStorageClusterTurbiningCapacityThreasholdsMin
+                      [globalClusterIdx];
+            if (cnt >= 0)
+            {
+                SecondMembre[cnt] = hydroCluster.MingenHoraire[pdtJour];
+                AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr;
+            }
+
+            cnt = CorrespondanceCntNativesCntOptim
+                    .NumeroDeContrainteDesContraintesLTStorageClusterPumpingCapacityThreasholds
+                      [globalClusterIdx];
+            if (cnt >= 0)
+            {
+                SecondMembre[cnt] = hydroCluster.ContrainteDePmaxPompageHoraire[pdtJour];
+                AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr;
+            }
+
+            double level_max = hydroCluster.NiveauHoraireSup[pdtHebdo];
+            double level_min = hydroCluster.NiveauHoraireInf[pdtHebdo];
+            cnt = CorrespondanceCntNativesCntOptim
+                    .NumeroDeContrainteDesContraintesLTStockLevelReserveParticipationDown
+                      [globalClusterIdx];
+            if (cnt >= 0)
+            {
+                SecondMembre[cnt] = hydroCluster.NiveauHoraireSup[pdtHebdo];
+                AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr;
+            }
+
+            cnt = CorrespondanceCntNativesCntOptim
+                    .NumeroDeContrainteDesContraintesLTStockLevelReserveParticipationUp
+                      [globalClusterIdx];
+            if (cnt >= 0)
+            {
+                SecondMembre[cnt] = hydroCluster.NiveauHoraireInf[pdtHebdo];
+                AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr;
+            }
+
+            cnt
+              = CorrespondanceCntNativesCntOptim
+                  .NumeroDeContrainteDesContraintesLTGlobalStockEnergyLevelReserveParticipationDown
+                    [globalClusterIdx];
+            if (cnt >= 0)
+            {
+                SecondMembre[cnt] = reserves.maxGlobalActivationDurationDown
+                                    * reserves.maxGlobalEnergyActivationRatioDown * level_max;
+                AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr;
+            }
+
+            cnt = CorrespondanceCntNativesCntOptim
+                    .NumeroDeContrainteDesContraintesLTGlobalStockEnergyLevelReserveParticipationUp
+                      [globalClusterIdx];
+            if (cnt >= 0)
+            {
+                SecondMembre[cnt] = -reserves.maxGlobalActivationDurationUp
+                                    * reserves.maxGlobalEnergyActivationRatioUp * level_min;
+                AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr;
+            }
+        }
+
+        // Set the rigth sides of equations for a LongTerm cluster participation to a reserve up
+        void setLTStorageReserveUpParticipationRightSides(
+          const RESERVE_PARTICIPATION_LTSTORAGE& reserveParticipation,
+          const AREA_RESERVES_VECTOR& reserves,
+          const CAPACITY_RESERVATION& reserve)
+        {
+            setLTStorageReserveParticipationRightSides(reserveParticipation, reserves, reserve);
+            const auto& CorrespondanceCntNativesCntOptim = problemeHebdo
+                                                             ->CorrespondanceCntNativesCntOptim
+                                                               [pdtJour];
+            int cnt = CorrespondanceCntNativesCntOptim
+                        .NumeroDeContrainteDesContraintesLTStorageClusterMaxWithdrawParticipation
+                          [reserveParticipation.globalIndexClusterParticipation];
+            if (cnt >= 0)
+            {
+                SecondMembre[cnt] = reserveParticipation.maxTurbining;
+                AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr;
+            }
+            cnt = CorrespondanceCntNativesCntOptim
+                    .NumeroDeContrainteDesContraintesLTStorageClusterMaxInjectionParticipation
+                      [reserveParticipation.globalIndexClusterParticipation];
+            if (cnt >= 0)
+            {
+                SecondMembre[cnt] = reserveParticipation.maxPumping;
+                AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr;
+            }
+            cnt = CorrespondanceCntNativesCntOptim
+                    .NumeroDeContrainteDesContraintesLTStockEnergyLevelReserveParticipation
+                      [reserveParticipation.globalIndexClusterParticipation];
+            if (cnt >= 0)
+            {
+                auto& hydroCluster = problemeHebdo->CaracteristiquesHydrauliques[pays];
+                double level_min = hydroCluster.NiveauHoraireInf[pdtHebdo];
+
+                SecondMembre[cnt] = -reserve.maxEnergyActivationRatio
+                                    * reserve.maxActivationDuration * level_min;
+                AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr;
+            }
+        }
+
+        // Set the rigth sides of equations for a LongTerm cluster participation to a reserve down
+        void setLTStorageReserveDownParticipationRightSides(
+          const RESERVE_PARTICIPATION_LTSTORAGE& reserveParticipation,
+          const AREA_RESERVES_VECTOR& reserves,
+          const CAPACITY_RESERVATION& reserve)
+        {
+            setLTStorageReserveParticipationRightSides(reserveParticipation, reserves, reserve);
+            const auto& CorrespondanceCntNativesCntOptim = problemeHebdo
+                                                             ->CorrespondanceCntNativesCntOptim
+                                                               [pdtJour];
+            int cnt = CorrespondanceCntNativesCntOptim
+                        .NumeroDeContrainteDesContraintesLTStorageClusterMaxWithdrawParticipation
+                          [reserveParticipation.globalIndexClusterParticipation];
+            if (cnt >= 0)
+            {
+                SecondMembre[cnt] = reserveParticipation.maxTurbining;
+                AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr;
+            }
+            cnt = CorrespondanceCntNativesCntOptim
+                    .NumeroDeContrainteDesContraintesLTStorageClusterMaxInjectionParticipation
+                      [reserveParticipation.globalIndexClusterParticipation];
+            if (cnt >= 0)
+            {
+                SecondMembre[cnt] = reserveParticipation.maxPumping;
+                AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr;
+            }
+            cnt = CorrespondanceCntNativesCntOptim
+                    .NumeroDeContrainteDesContraintesLTStockEnergyLevelReserveParticipation
+                      [reserveParticipation.globalIndexClusterParticipation];
+            if (cnt >= 0)
+            {
+                auto& hydroCluster = problemeHebdo->CaracteristiquesHydrauliques[pays];
+                double level_max = hydroCluster.NiveauHoraireSup[pdtHebdo];
+                SecondMembre[cnt] = reserve.maxEnergyActivationRatio * reserve.maxActivationDuration
+                                    * level_max;
+                AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr;
+            }
+        }
+    };
+
+    ReserveVariablesRightSidesSetter reserveVariablesRightSidesSetter(problemeHebdo);
+
+    for (int pdtHebdo = PremierPdtDeLIntervalle, pdtJour = 0; pdtHebdo < DernierPdtDeLIntervalle;
          pdtHebdo++, pdtJour++)
     {
-        int hourInTheYear = problemeHebdo->weekInTheYear * 168 + pdtHebdo;
-        const CORRESPONDANCES_DES_CONTRAINTES& CorrespondanceCntNativesCntOptim
-          = problemeHebdo->CorrespondanceCntNativesCntOptim[pdtJour];
+        int pdtGlobal = problemeHebdo->weekInTheYear * problemeHebdo->NombreDePasDeTempsDUneJournee
+                          * problemeHebdo->NombreDeJours
+                        + pdtJour;
+
+        reserveVariablesRightSidesSetter.setPdtJour(pdtJour);
+        reserveVariablesRightSidesSetter.setPdtHebdo(pdtHebdo);
+        reserveVariablesRightSidesSetter.setPdtGlobal(pdtGlobal);
 
-        for (uint32_t pays = 0; pays < problemeHebdo->NombreDePays; pays++)
+        for (int pays = 0; pays < problemeHebdo->NombreDePays; pays++)
         {
+            reserveVariablesRightSidesSetter.setPays(pays);
+            const auto& areaReserves = problemeHebdo->allReserves[pays];
 
-            // Thermal clusters
+            // Up Reserves Right Sides
+            for (const auto& areaReserveUp: areaReserves.areaCapacityReservationsUp)
             {
-                auto& areaReservesUp
-                  = areaReserves[pays].areaCapacityReservationsUp;
-                for (const auto& areaReserveUp : areaReservesUp)
+                reserveVariablesRightSidesSetter.setReserveRightSides(areaReserveUp);
+
+                // Thermal Cluster
+                for (const auto& [clusterId, clusterReserveParticipation]:
+                     areaReserveUp.AllThermalReservesParticipation)
                 {
-                    int cnt = CorrespondanceCntNativesCntOptim
-                                .NumeroDeContrainteDesContraintesDeBesoinEnReserves
-                                  [areaReserveUp.globalReserveIndex];
-                    if (cnt >= 0)
-                    {
-                        SecondMembre[cnt] = areaReserveUp.need.at(hourInTheYear);
-                        double* adresseDuResultat = &(problemeHebdo->ResultatsHoraires[pays].Reserves[pdtHebdo].CoutsMarginauxHoraires[areaReserveUp.areaReserveIndex]);
-                        AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = adresseDuResultat;
-                    }
-
-                    for (const auto& [clusterId, reserveParticipation]:
-                         areaReserveUp.AllThermalReservesParticipation)
-                    {
-                        int cnt1
-                          = CorrespondanceCntNativesCntOptim
-                              .nbOffGroupUnitsParticipatingToReservesInThermalClusterConstraintIndex
-                                [reserveParticipation.globalIndexClusterParticipation];
-                        if (cnt1 >= 0)
-                        {
-                            SecondMembre[cnt1] = problemeHebdo->PaliersThermiquesDuPays[pays]
-                                                   .PuissanceDisponibleEtCout[reserveParticipation
-                                                                                .clusterIdInArea]
-                                                   .NombreMaxDeGroupesEnMarcheDuPalierThermique
-                                                     [pdtJour];
-                            AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt1] = nullptr;
-                        }
-                    }
+                    reserveVariablesRightSidesSetter.setThermalReserveUpParticipationRightSides(
+                      clusterReserveParticipation);
                 }
 
-                auto& areaReservesDown
-                  = areaReserves[pays].areaCapacityReservationsDown;
-                for (const auto& areaReserveDown : areaReservesDown)
+                // Short Term Storage Cluster
+                for (const auto& [clusterId, clusterReserveParticipation]:
+                     areaReserveUp.AllSTStorageReservesParticipation)
                 {
-                    int cnt = CorrespondanceCntNativesCntOptim
-                                .NumeroDeContrainteDesContraintesDeBesoinEnReserves
-                                  [areaReserveDown.globalReserveIndex];
-                    if (cnt >= 0)
-                    {
-                        SecondMembre[cnt] = areaReserveDown.need.at(hourInTheYear);
-                        double* adresseDuResultat = &(problemeHebdo->ResultatsHoraires[pays].Reserves[pdtHebdo].CoutsMarginauxHoraires[areaReserveDown.areaReserveIndex]);
-                        AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = adresseDuResultat;
-                    }
+                    reserveVariablesRightSidesSetter.setSTStorageReserveUpParticipationRightSides(
+                      clusterReserveParticipation,
+                      areaReserves,
+                      areaReserveUp);
                 }
 
-                for (uint32_t cluster = 0;
-                     cluster
-                     < problemeHebdo->PaliersThermiquesDuPays[pays].NombreDePaliersThermiques;
-                     cluster++)
+                // Long Term Storage Cluster
+                for (const auto& clusterReserveParticipation:
+                     areaReserveUp.AllLTStorageReservesParticipation)
                 {
-                    int globalClusterIdx
-                      = problemeHebdo->PaliersThermiquesDuPays[pays]
-                          .NumeroDuPalierDansLEnsembleDesPaliersThermiques[cluster];
-                    int cnt1
-                      = CorrespondanceCntNativesCntOptim
-                          .NumeroDeContrainteDesContraintesDePuissanceMinDuPalier[globalClusterIdx];
-                    if (cnt1 >= 0)
-                    {
-                        SecondMembre[cnt1] = problemeHebdo->PaliersThermiquesDuPays[pays]
-                                               .PuissanceDisponibleEtCout[cluster]
-                                               .PuissanceMinDuPalierThermiqueRef[pdtJour];
-                        AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt1] = nullptr;
-                    }
-
-                    int cnt2
-                      = CorrespondanceCntNativesCntOptim
-                          .NumeroDeContrainteDesContraintesDePuissanceMaxDuPalier[globalClusterIdx];
-                    if (cnt2 >= 0)
-                    {
-                        SecondMembre[cnt2] = problemeHebdo->PaliersThermiquesDuPays[pays]
-                                               .PuissanceDisponibleEtCout[cluster]
-                                               .PuissanceDisponibleDuPalierThermiqueRef[pdtJour];
-                        AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt2] = nullptr;
-                    }
+                    reserveVariablesRightSidesSetter.setLTStorageReserveUpParticipationRightSides(
+                      clusterReserveParticipation,
+                      areaReserves,
+                      areaReserveUp);
                 }
             }
-
-            // Short Term Storage clusters
+            for (const auto& areaReserveDown: areaReserves.areaCapacityReservationsDown)
             {
-                auto& areaReservesUp
-                  = areaReserves[pays].areaCapacityReservationsUp;
-                for (const auto& areaReserveUp : areaReservesUp)
-                {
-                    for (const auto& [clusterId, reserveParticipation]:
-                         areaReserveUp.AllSTStorageReservesParticipation)
-                    {
-                        int cnt
-                          = CorrespondanceCntNativesCntOptim
-                              .NumeroDeContrainteDesContraintesSTStorageClusterMaxWithdrawParticipation
-                                [reserveParticipation.globalIndexClusterParticipation];
-                        if (cnt >= 0)
-                        {
-                            SecondMembre[cnt] = reserveParticipation.maxTurbining;
-                            AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr;
-                        }
-                        cnt
-                          = CorrespondanceCntNativesCntOptim
-                              .NumeroDeContrainteDesContraintesSTStorageClusterMaxInjectionParticipation
-                                [reserveParticipation.globalIndexClusterParticipation];
-                        if (cnt >= 0)
-                        {
-                            SecondMembre[cnt] = reserveParticipation.maxPumping;
-                            AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr;
-                        }
-
-                        cnt
-                          = CorrespondanceCntNativesCntOptim
-                              .NumeroDeContrainteDesContraintesSTStockEnergyLevelReserveParticipation
-                                [reserveParticipation.globalIndexClusterParticipation];
-                        if (cnt >= 0)
-                        {
-                            int weekFirstHour = problemeHebdo->weekInTheYear * 168;
-                            auto& cluster = problemeHebdo->ShortTermStorage[pays][reserveParticipation.clusterIdInArea];
-                            int hourInTheYear = weekFirstHour + pdtHebdo;
-                            double level_min = cluster.reservoirCapacity
-                                             * cluster.series->lowerRuleCurve[hourInTheYear];
-
-                            SecondMembre[cnt] = -areaReserveUp.maxEnergyActivationRatio * areaReserveUp.maxActivationDuration * level_min;
-                            AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr;
-                        }
-                    }
-                }
-                auto& areaReservesDown
-                  = areaReserves[pays].areaCapacityReservationsDown;
-                for (const auto& areaReserveDown : areaReservesDown)
+                reserveVariablesRightSidesSetter.setReserveRightSides(areaReserveDown);
+
+                // Thermal Cluster
+                for (const auto& [clusterId, clusterReserveParticipation]:
+                     areaReserveDown.AllThermalReservesParticipation)
                 {
-                    for (const auto& [clusterId, reserveParticipation] :
-                         areaReserveDown.AllSTStorageReservesParticipation)
-                    {
-                        int cnt
-                          = CorrespondanceCntNativesCntOptim
-                              .NumeroDeContrainteDesContraintesSTStorageClusterMaxWithdrawParticipation
-                                [reserveParticipation.globalIndexClusterParticipation];
-                        if (cnt >= 0)
-                        {
-                            SecondMembre[cnt] = reserveParticipation.maxTurbining;
-                            AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr;
-                        }
-                        cnt
-                          = CorrespondanceCntNativesCntOptim
-                              .NumeroDeContrainteDesContraintesSTStorageClusterMaxInjectionParticipation
-                                [reserveParticipation.globalIndexClusterParticipation];
-                        if (cnt >= 0)
-                        {
-                            SecondMembre[cnt] = reserveParticipation.maxPumping;
-                            AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr;
-                        }
-
-                        cnt
-                          = CorrespondanceCntNativesCntOptim
-                              .NumeroDeContrainteDesContraintesSTStockEnergyLevelReserveParticipation
-                                [reserveParticipation.globalIndexClusterParticipation];
-                        if (cnt >= 0)
-                        {
-                            int weekFirstHour = problemeHebdo->weekInTheYear * 168;
-                            auto& cluster = problemeHebdo->ShortTermStorage[pays][reserveParticipation.clusterIdInArea];
-                            int hourInTheYear = weekFirstHour + pdtHebdo;
-                            double level_max = cluster.reservoirCapacity
-                                             * cluster.series->upperRuleCurve[hourInTheYear];
-                            SecondMembre[cnt] = areaReserveDown.maxEnergyActivationRatio * areaReserveDown.maxActivationDuration * level_max;
-                            AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr;
-                        }
-                    }
+                    reserveVariablesRightSidesSetter.setThermalReserveDownParticipationRightSides(
+                      clusterReserveParticipation);
                 }
-                for (const auto& cluster : problemeHebdo->ShortTermStorage[pays])
+
+                // Short Term Storage Cluster
+                for (const auto& [clusterId, clusterReserveParticipation]:
+                     areaReserveDown.AllSTStorageReservesParticipation)
                 {
-                    int globalClusterIdx = cluster.clusterGlobalIndex;
-                    int cnt
-                      = CorrespondanceCntNativesCntOptim
-                          .NumeroDeContrainteDesContraintesSTStorageClusterTurbiningCapacityThreasholdsMax
-                            [globalClusterIdx];
-                    if (cnt >= 0)
-                    {
-                        SecondMembre[cnt] = cluster.series.get()->maxWithdrawalModulation[hourInTheYear]
-                                            * cluster.withdrawalNominalCapacity;
-                        AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr;
-                    }
-
-                    cnt
-                      = CorrespondanceCntNativesCntOptim
-                          .NumeroDeContrainteDesContraintesSTStorageClusterTurbiningCapacityThreasholdsMin
-                            [globalClusterIdx];
-                    if (cnt >= 0)
-                    {
-                        SecondMembre[cnt] = cluster.series.get()->lowerRuleCurve[hourInTheYear]
-                                            * cluster.withdrawalNominalCapacity;
-                        AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr;
-                    }
-
-                    cnt
-                      = CorrespondanceCntNativesCntOptim
-                          .NumeroDeContrainteDesContraintesSTStorageClusterPumpingCapacityThreasholds
-                            [globalClusterIdx];
-                    if (cnt >= 0)
-                    {
-                        SecondMembre[cnt] = cluster.series.get()->maxInjectionModulation[hourInTheYear]
-                                            * cluster.injectionNominalCapacity;
-                        AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr;
-                    }
-
-                    int weekFirstHour = problemeHebdo->weekInTheYear * 168;
-                    int hourInTheYear = weekFirstHour + pdtHebdo;
-                    double level_max = cluster.reservoirCapacity
-                                     * cluster.series->upperRuleCurve[hourInTheYear];
-                    double level_min = cluster.reservoirCapacity
-                                     * cluster.series->lowerRuleCurve[hourInTheYear];
-
-                    cnt = CorrespondanceCntNativesCntOptim
-                             .NumeroDeContrainteDesContraintesSTStockLevelReserveParticipationDown
-                               [globalClusterIdx];
-                       if (cnt >= 0)
-                       {
-                           SecondMembre[cnt] = level_max;
-                           AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr;
-                       }
-
-                      cnt = CorrespondanceCntNativesCntOptim
-                             .NumeroDeContrainteDesContraintesSTStockLevelReserveParticipationUp
-                               [globalClusterIdx];
-                       if (cnt >= 0)
-                       {
-                           SecondMembre[cnt] = -level_min;
-                           AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr;
-                       }
-
-                       cnt = CorrespondanceCntNativesCntOptim
-                              .NumeroDeContrainteDesContraintesSTGlobalStockEnergyLevelReserveParticipationDown
-                                [globalClusterIdx];
-                        if (cnt >= 0)
-                        {
-                            SecondMembre[cnt] = areaReserves[pays].maxGlobalActivationDurationDown * areaReserves[pays].maxGlobalEnergyActivationRatioDown * level_max;
-                            AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr;
-                        }
-
-                        cnt = CorrespondanceCntNativesCntOptim
-                              .NumeroDeContrainteDesContraintesSTGlobalStockEnergyLevelReserveParticipationUp
-                                [globalClusterIdx];
-                        if (cnt >= 0)
-                        {
-                            SecondMembre[cnt] = -areaReserves[pays].maxGlobalActivationDurationUp * areaReserves[pays].maxGlobalEnergyActivationRatioUp * level_min;
-                            AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr;
-                        }
+                    reserveVariablesRightSidesSetter.setSTStorageReserveDownParticipationRightSides(
+                      clusterReserveParticipation,
+                      areaReserves,
+                      areaReserveDown);
                 }
-            }
 
-            // Long Term Storage clusters
-            {
-                for (uint32_t pays = 0; pays < problemeHebdo->NombreDePays; pays++)
+                // Long Term Storage Cluster
+                for (const auto& clusterReserveParticipation:
+                     areaReserveDown.AllLTStorageReservesParticipation)
                 {
-                   auto& areaReservesUp = areaReserves[pays].areaCapacityReservationsUp;
-                   for (const auto& areaReserveUp : areaReservesUp)
-                   {
-                       for (const auto& reserveParticipation :
-                            areaReserveUp.AllLTStorageReservesParticipation)
-                       {
-                           int cnt
-                             = CorrespondanceCntNativesCntOptim
-                                 .NumeroDeContrainteDesContraintesLTStorageClusterMaxWithdrawParticipation
-                                   [reserveParticipation.globalIndexClusterParticipation];
-                           if (cnt >= 0)
-                           {
-                               SecondMembre[cnt] = reserveParticipation.maxTurbining;
-                               AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr;
-                           }
-
-                           cnt
-                             = CorrespondanceCntNativesCntOptim
-                                 .NumeroDeContrainteDesContraintesLTStorageClusterMaxInjectionParticipation
-                                   [reserveParticipation.globalIndexClusterParticipation];
-                           if (cnt >= 0)
-                           {
-                               SecondMembre[cnt] = reserveParticipation.maxPumping;
-                               AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr;
-                           }
-
-                           cnt
-                             = CorrespondanceCntNativesCntOptim
-                                 .NumeroDeContrainteDesContraintesLTStockEnergyLevelReserveParticipation
-                                   [reserveParticipation.globalIndexClusterParticipation];
-                           if (cnt >= 0)
-                           {
-                               int weekFirstHour = problemeHebdo->weekInTheYear * 168;
-                               auto& hydroCluster = problemeHebdo
-                                                      ->CaracteristiquesHydrauliques[pays];
-                               int hourInTheYear = weekFirstHour + pdtHebdo;
-                               double level_min = hydroCluster.NiveauHoraireInf[pdtHebdo];
-
-                               SecondMembre[cnt] = -areaReserveUp.maxEnergyActivationRatio
-                                                   * areaReserveUp.maxActivationDuration
-                                                   * level_min;
-                               AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr;
-                           }
-                       }
-                   }
-                   auto& areaReservesDown = areaReserves[pays].areaCapacityReservationsDown;
-                   for (const auto& areaReserveDown : areaReservesDown)
-                   {
-                       for (const auto& reserveParticipation :
-                            areaReserveDown.AllLTStorageReservesParticipation)
-                       {
-                           int cnt
-                             = CorrespondanceCntNativesCntOptim
-                                 .NumeroDeContrainteDesContraintesLTStorageClusterMaxWithdrawParticipation
-                                   [reserveParticipation.globalIndexClusterParticipation];
-                           if (cnt >= 0)
-                           {
-                               SecondMembre[cnt] = reserveParticipation.maxTurbining;
-                               AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr;
-                           }
-                           cnt
-                             = CorrespondanceCntNativesCntOptim
-                                 .NumeroDeContrainteDesContraintesLTStorageClusterMaxInjectionParticipation
-                                   [reserveParticipation.globalIndexClusterParticipation];
-                           if (cnt >= 0)
-                           {
-                               SecondMembre[cnt] = reserveParticipation.maxPumping;
-                               AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr;
-                           }
-                           cnt
-                             = CorrespondanceCntNativesCntOptim
-                                 .NumeroDeContrainteDesContraintesLTStockEnergyLevelReserveParticipation
-                                   [reserveParticipation.globalIndexClusterParticipation];
-                           if (cnt >= 0)
-                           {
-                               int weekFirstHour = problemeHebdo->weekInTheYear * 168;
-                               auto& hydroCluster = problemeHebdo
-                                                      ->CaracteristiquesHydrauliques[pays];
-                               int hourInTheYear = weekFirstHour + pdtHebdo;
-                               double level_max = hydroCluster.NiveauHoraireSup[pdtHebdo];
-                               SecondMembre[cnt] = areaReserveDown.maxEnergyActivationRatio
-                                                   * areaReserveDown.maxActivationDuration
-                                                   * level_max;
-                               AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr;
-                           }
-                       }
-                   }
-
-                   // Checks if LTStorage cluster are participating to reserves
-                   auto isClusterParticipatingToReserves =
-                     [](std::vector<CAPACITY_RESERVATION>& reserves)
-                   {
-                       auto hasReserveParticipations = [](CAPACITY_RESERVATION& res)
-                       { return res.AllLTStorageReservesParticipation.size() > 0; };
-                       return std::any_of(reserves.begin(),
-                                          reserves.end(),
-                                          hasReserveParticipations);
-                   };
-
-                   if (isClusterParticipatingToReserves(
-                         problemeHebdo->allReserves[pays].areaCapacityReservationsDown)
-                       || isClusterParticipatingToReserves(
-                         problemeHebdo->allReserves[pays].areaCapacityReservationsUp))
-                   {
-                       int weekFirstHour = problemeHebdo->weekInTheYear * 168;
-                       int hourInTheYear = weekFirstHour + pdtHebdo;
-                       auto& hydroCluster = problemeHebdo->CaracteristiquesHydrauliques[pays];
-                       double level_max = hydroCluster.NiveauHoraireSup[pdtHebdo];
-                       double level_min = hydroCluster.NiveauHoraireInf[pdtHebdo];
-
-                       int globalClusterIdx = hydroCluster.GlobalHydroIndex;
-                       int cnt
-                         = CorrespondanceCntNativesCntOptim
-                             .NumeroDeContrainteDesContraintesLTStorageClusterTurbiningCapacityThreasholdsMax
-                               [globalClusterIdx];
-                       if (cnt >= 0)
-                       {
-                           SecondMembre[cnt] = hydroCluster
-                                                 .ContrainteDePmaxHydrauliqueHoraire[pdtJour];
-                           AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr;
-                       }
-
-                       cnt
-                         = CorrespondanceCntNativesCntOptim
-                             .NumeroDeContrainteDesContraintesLTStorageClusterTurbiningCapacityThreasholdsMin
-                               [globalClusterIdx];
-                       if (cnt >= 0)
-                       {
-                           SecondMembre[cnt] = hydroCluster.MingenHoraire[pdtJour];
-                           AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr;
-                       }
-
-                       cnt
-                         = CorrespondanceCntNativesCntOptim
-                             .NumeroDeContrainteDesContraintesLTStorageClusterPumpingCapacityThreasholds
-                               [globalClusterIdx];
-                       if (cnt >= 0)
-                       {
-                           SecondMembre[cnt] = hydroCluster.ContrainteDePmaxPompageHoraire[pdtJour];
-                           AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr;
-                       }
-
-                       cnt = CorrespondanceCntNativesCntOptim
-                               .NumeroDeContrainteDesContraintesLTStockLevelReserveParticipationDown
-                                 [globalClusterIdx];
-                       if (cnt >= 0)
-                       {
-                           SecondMembre[cnt] = hydroCluster.NiveauHoraireSup[pdtHebdo];
-                           AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr;
-                       }
-
-                       cnt = CorrespondanceCntNativesCntOptim
-                               .NumeroDeContrainteDesContraintesLTStockLevelReserveParticipationUp
-                                 [globalClusterIdx];
-                       if (cnt >= 0)
-                       {
-                           SecondMembre[cnt] = hydroCluster.NiveauHoraireInf[pdtHebdo];
-                           AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr;
-                       }
-
-                       cnt
-                         = CorrespondanceCntNativesCntOptim
-                             .NumeroDeContrainteDesContraintesLTGlobalStockEnergyLevelReserveParticipationDown
-                               [globalClusterIdx];
-                       if (cnt >= 0)
-                       {
-                           SecondMembre[cnt] = areaReserves[pays].maxGlobalActivationDurationDown
-                                               * areaReserves[pays]
-                                                   .maxGlobalEnergyActivationRatioDown
-                                               * level_max;
-                           AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr;
-                       }
-
-                       cnt
-                         = CorrespondanceCntNativesCntOptim
-                             .NumeroDeContrainteDesContraintesLTGlobalStockEnergyLevelReserveParticipationUp
-                               [globalClusterIdx];
-                       if (cnt >= 0)
-                       {
-                           SecondMembre[cnt] = -areaReserves[pays].maxGlobalActivationDurationUp
-                                               * areaReserves[pays].maxGlobalEnergyActivationRatioUp
-                                               * level_min;
-                           AdresseOuPlacerLaValeurDesCoutsMarginaux[cnt] = nullptr;
-                       }
-                   }
+                    reserveVariablesRightSidesSetter.setLTStorageReserveDownParticipationRightSides(
+                      clusterReserveParticipation,
+                      areaReserves,
+                      areaReserveDown);
                 }
             }
         }
diff --git a/src/solver/simulation/include/antares/solver/simulation/sim_structure_probleme_economique.h b/src/solver/simulation/include/antares/solver/simulation/sim_structure_probleme_economique.h
index 28bce2f5a3..6979ffd0c8 100644
--- a/src/solver/simulation/include/antares/solver/simulation/sim_structure_probleme_economique.h
+++ b/src/solver/simulation/include/antares/solver/simulation/sim_structure_probleme_economique.h
@@ -86,7 +86,6 @@ struct CORRESPONDANCES_DES_VARIABLES
         std::vector<int> WithdrawalVariable;
         std::vector<int> LevelVariable;
     } SIM_ShortTermStorage;
-
 };
 
 struct CORRESPONDANCES_DES_CONTRAINTES
@@ -116,8 +115,10 @@ struct CORRESPONDANCES_DES_CONTRAINTES
 
     std::vector<int> NumeroDeContrainteDesContraintesSTStorageClusterMaxWithdrawParticipation;
     std::vector<int> NumeroDeContrainteDesContraintesSTStorageClusterMaxInjectionParticipation;
-    std::vector<int> NumeroDeContrainteDesContraintesSTStorageClusterTurbiningCapacityThreasholdsMax;
-    std::vector<int> NumeroDeContrainteDesContraintesSTStorageClusterTurbiningCapacityThreasholdsMin;
+    std::vector<int>
+      NumeroDeContrainteDesContraintesSTStorageClusterTurbiningCapacityThreasholdsMax;
+    std::vector<int>
+      NumeroDeContrainteDesContraintesSTStorageClusterTurbiningCapacityThreasholdsMin;
     std::vector<int> NumeroDeContrainteDesContraintesSTStorageClusterPumpingCapacityThreasholds;
     std::vector<int> NumeroDeContrainteDesContraintesSTStockLevelReserveParticipationUp;
     std::vector<int> NumeroDeContrainteDesContraintesSTStockLevelReserveParticipationDown;
@@ -127,8 +128,10 @@ struct CORRESPONDANCES_DES_CONTRAINTES
 
     std::vector<int> NumeroDeContrainteDesContraintesLTStorageClusterMaxWithdrawParticipation;
     std::vector<int> NumeroDeContrainteDesContraintesLTStorageClusterMaxInjectionParticipation;
-    std::vector<int> NumeroDeContrainteDesContraintesLTStorageClusterTurbiningCapacityThreasholdsMax;
-    std::vector<int> NumeroDeContrainteDesContraintesLTStorageClusterTurbiningCapacityThreasholdsMin;
+    std::vector<int>
+      NumeroDeContrainteDesContraintesLTStorageClusterTurbiningCapacityThreasholdsMax;
+    std::vector<int>
+      NumeroDeContrainteDesContraintesLTStorageClusterTurbiningCapacityThreasholdsMin;
     std::vector<int> NumeroDeContrainteDesContraintesLTStorageClusterPumpingCapacityThreasholds;
     std::vector<int> NumeroDeContrainteDesContraintesLTStockLevelReserveParticipationUp;
     std::vector<int> NumeroDeContrainteDesContraintesLTStockLevelReserveParticipationDown;
@@ -228,9 +231,9 @@ using AREA_INPUT = std::vector<::ShortTermStorage::PROPERTIES>; // index is loca
 struct RESULTS
 {
     // Index is the number of the STS in the area
-    std::vector<double> level;      // MWh
-    std::vector<double> injection;  // MWh
-    std::vector<double> withdrawal; // MWh
+    std::vector<double> level;                         // MWh
+    std::vector<double> injection;                     // MWh
+    std::vector<double> withdrawal;                    // MWh
     std::vector<double> reserveParticipationOfCluster; // MWh
 };
 } // namespace ShortTermStorage
@@ -306,24 +309,25 @@ struct RESERVE_PARTICIPATION_BASE
     int areaIndexClusterParticipation;
     std::string clusterName;
     int clusterIdInArea;
+    int clusterId;
 
     virtual ~RESERVE_PARTICIPATION_BASE() = default;
 };
 
-struct RESERVE_PARTICIPATION_THERMAL : public RESERVE_PARTICIPATION_BASE
+struct RESERVE_PARTICIPATION_THERMAL: public RESERVE_PARTICIPATION_BASE
 {
     float maxPower;
     float maxPowerOff;
     float participationCostOff;
 };
 
-struct RESERVE_PARTICIPATION_STSTORAGE : public RESERVE_PARTICIPATION_BASE
+struct RESERVE_PARTICIPATION_STSTORAGE: public RESERVE_PARTICIPATION_BASE
 {
     float maxTurbining;
     float maxPumping;
 };
 
-struct RESERVE_PARTICIPATION_LTSTORAGE : public RESERVE_PARTICIPATION_BASE
+struct RESERVE_PARTICIPATION_LTSTORAGE: public RESERVE_PARTICIPATION_BASE
 {
     float maxTurbining;
     float maxPumping;
@@ -332,9 +336,10 @@ struct RESERVE_PARTICIPATION_LTSTORAGE : public RESERVE_PARTICIPATION_BASE
 struct CAPACITY_RESERVATION
 {
     std::map</*area_clusterId*/ int, RESERVE_PARTICIPATION_THERMAL> AllThermalReservesParticipation;
-    std::map</*area_clusterId*/ int, RESERVE_PARTICIPATION_STSTORAGE> AllSTStorageReservesParticipation;
+    std::map</*area_clusterId*/ int, RESERVE_PARTICIPATION_STSTORAGE>
+      AllSTStorageReservesParticipation;
     std::vector<RESERVE_PARTICIPATION_LTSTORAGE> AllLTStorageReservesParticipation;
-    std::vector<int> need;      //!< Vector size is number of hours in year
+    std::vector<int> need; //!< Vector size is number of hours in year
     float failureCost = 0;
     float spillageCost = 0;
     float maxActivationRatio = 0;
@@ -525,7 +530,6 @@ class computeTimeStepLevel
     }
 };
 
-
 struct RESERVES
 {
     std::vector<double> ValeursHorairesInternalUnsatisfied;
@@ -545,7 +549,7 @@ struct RESULTATS_HORAIRES
 
     std::vector<double> CoutsMarginauxHoraires;
     std::vector<PRODUCTION_THERMIQUE_OPTIMALE> ProductionThermique; // index is pdtHebdo
-    std::vector<OPTIMAL_HYDRO_USAGE> HydroUsage; // index is pdtHebdo
+    std::vector<OPTIMAL_HYDRO_USAGE> HydroUsage;                    // index is pdtHebdo
     std::vector<RESERVES> Reserves;
 
     std::vector<::ShortTermStorage::RESULTS> ShortTermStorage;
diff --git a/src/solver/simulation/sim_calcul_economique.cpp b/src/solver/simulation/sim_calcul_economique.cpp
index 598ca73df9..4490d60920 100644
--- a/src/solver/simulation/sim_calcul_economique.cpp
+++ b/src/solver/simulation/sim_calcul_economique.cpp
@@ -133,6 +133,7 @@ static void importShortTermStorages(
             toInsert.initialLevel = st.properties.initialLevel;
             toInsert.initialLevelOptim = st.properties.initialLevelOptim;
             toInsert.name = st.properties.name;
+            toInsert.clusterGlobalIndex = clusterGlobalIndex;
 
             toInsert.series = st.series;
 
@@ -154,6 +155,7 @@ static void importShortTermStorages(
                     reserveParticipation.participationCost = cluster.reserveCost(reserveName);
                     reserveParticipation.clusterName = cluster.id;
                     reserveParticipation.clusterIdInArea = idx;
+                    reserveParticipation.clusterId = cluster.properties.clusterGlobalIndex;
                     reserveParticipation.globalIndexClusterParticipation
                         = globalSTStorageClusterParticipationIndex;
                     reserveParticipation.areaIndexClusterParticipation = areaClusterParticipationIndex;
@@ -179,6 +181,7 @@ static void importShortTermStorages(
                     reserveParticipation.participationCost = cluster.reserveCost(reserveName);
                     reserveParticipation.clusterName = cluster.id;
                     reserveParticipation.clusterIdInArea = idx;
+                    reserveParticipation.clusterId = cluster.properties.clusterGlobalIndex;
                     reserveParticipation.globalIndexClusterParticipation
                         = globalSTStorageClusterParticipationIndex;
                     reserveParticipation.areaIndexClusterParticipation = areaClusterParticipationIndex;
@@ -522,6 +525,7 @@ void SIM_InitialisationProblemeHebdo(Data::Study& study,
                           reserveName);
                         reserveParticipation.clusterName = cluster->name();
                         reserveParticipation.clusterIdInArea = cluster->index;
+                        reserveParticipation.clusterId = NombrePaliers + cluster->index;
                         reserveParticipation.globalIndexClusterParticipation
                           = globalThermalClusterParticipationIndex;
                         reserveParticipation.areaIndexClusterParticipation
@@ -546,6 +550,7 @@ void SIM_InitialisationProblemeHebdo(Data::Study& study,
                         reserveParticipation.participationCost = cluster->reserveCost(reserveName);
                         reserveParticipation.clusterName = cluster->name();
                         reserveParticipation.clusterIdInArea = cluster->index;
+                        reserveParticipation.clusterId = NombrePaliers + cluster->index;
                         reserveParticipation.globalIndexClusterParticipation
                             = globalThermalClusterParticipationIndex;
                         reserveParticipation.areaIndexClusterParticipation
diff --git a/src/solver/variable/include/antares/solver/variable/info.h b/src/solver/variable/include/antares/solver/variable/info.h
index b754e3874f..373d7e3c32 100644
--- a/src/solver/variable/include/antares/solver/variable/info.h
+++ b/src/solver/variable/include/antares/solver/variable/info.h
@@ -22,14 +22,14 @@
 #define __SOLVER_VARIABLE_INFO_H__
 
 #include <cmath>
-#include "./economy/vCardReserveParticipationByDispatchableOnUnitsPlant.h"
-#include "./economy/vCardReserveParticipationByDispatchableOffUnitsPlant.h"
-#include "./economy/vCardReserveParticipationBySTStorage.h"
-#include "./economy/vCardReserveParticipationByLTStorage.h"
-#include "./economy/vCardReserveParticipationBySTStorageGroup.h"
-#include "./economy/vCardReserveParticipationByThermalGroup.h"
-#include "./economy/vCardReserveParticipationUnsuppliedSpilled.h"
-#include "./economy/vCardReserveParticipationMarginalCost.h"
+#include "economy/vCardReserveParticipationByDispatchableOnUnitsPlant.h"
+#include "economy/vCardReserveParticipationByDispatchableOffUnitsPlant.h"
+#include "economy/vCardReserveParticipationBySTStorage.h"
+#include "economy/vCardReserveParticipationByLTStorage.h"
+#include "economy/vCardReserveParticipationBySTStorageGroup.h"
+#include "economy/vCardReserveParticipationByThermalGroup.h"
+#include "economy/vCardReserveParticipationUnsuppliedSpilled.h"
+#include "economy/vCardReserveParticipationMarginalCost.h"
 
 #include "antares/solver/variable/surveyresults.h"
 #include "antares/study/fwd.h"
diff --git a/src/solver/variable/include/antares/solver/variable/state.h b/src/solver/variable/include/antares/solver/variable/state.h
index 60fc6615a3..133bcca697 100644
--- a/src/solver/variable/include/antares/solver/variable/state.h
+++ b/src/solver/variable/include/antares/solver/variable/state.h
@@ -71,7 +71,8 @@ struct ReserveParticipationPerGroupForYear
 {
     //! Reserve Participation for all thermal group types (nuclear / coal / ...) for the whole
     //! year per reserve
-    std::map<Data::ThermalDispatchableGroup, std::map<Data::ReserveName, double>> thermalGroupsReserveParticipation;
+    std::map<Data::ThermalDispatchableGroup, std::map<Data::ReserveName, double>>
+      thermalGroupsReserveParticipation;
 
     //! Reserve Participation for all thermal Short Term storages types (PSP / Battery / ...)
     //! for the whole year per reserve
@@ -79,7 +80,6 @@ struct ReserveParticipationPerGroupForYear
       shortTermStorageGroupsReserveParticipation;
 };
 
-
 class State
 {
 public:
@@ -107,14 +107,14 @@ class State
     */
     void initFromThermalClusterIndex(const unsigned int areaWideIndex);
 
-     /*!
-     ** \brief Initialize some variable according a short term storage cluster index
-     **
-     ** We assume here that the variables related to an area
-     ** are properly initialized.
-     **
-     ** \param areaWideIndex Index of the short term storage cluster for the current area
-     */
+    /*!
+    ** \brief Initialize some variable according a short term storage cluster index
+    **
+    ** We assume here that the variables related to an area
+    ** are properly initialized.
+    **
+    ** \param areaWideIndex Index of the short term storage cluster for the current area
+    */
     void initFromShortTermStorageClusterIndex(const unsigned int areaWideIndex);
 
     /*!
@@ -139,21 +139,8 @@ class State
     void yearEndBuildFromThermalClusterIndex(const unsigned int areaWideIndex);
 
     void calculateReserveParticipationCosts();
-    
-    void initFromHydroStorage();
-
-    //std::map<Data::ReserveName, double> hydroReserveParticipationForYear[Variable::maxHoursInAYear];
-    //double hydroReserveParticipationCostForYear[Variable::maxHoursInAYear];
-
-    // void initFromHydroStorage();
-
-    // void processReserve(const CAPACITY_RESERVATION& reserve, bool isUpReserve);
-
-    //int getAreaIndexReserveParticipationFromReserveAndLTStorage(
-    //   Data::ReserveName reserveName,
-    //   Data::ClusterName clusterName);
-
 
+    void initFromHydroStorage();
 
 private:
     /*!
@@ -171,7 +158,6 @@ class State
       const std::array<uint, HOURS_PER_YEAR>& ON_opt,
       const Data::ThermalCluster* currentCluster);
 
-
     std::array<uint, HOURS_PER_YEAR> computeEconomicallyOptimalNbClustersONforEachHour(
       const uint& maxDurationON,
       const std::array<uint, HOURS_PER_YEAR>& ON_min,
@@ -216,8 +202,6 @@ class State
     //! The current Short Term Storage cluster
     Data::ShortTermStorage::STStorageCluster* STStorageCluster;
 
-
-
     //! The current renewable cluster
     Data::RenewableCluster* renewableCluster;
     //! The Scratchpad for the current area
@@ -246,7 +230,6 @@ class State
     std::vector<ReserveParticipationPerGroupForYear> reserveParticipationPerGroupForYear{
       HOURS_PER_YEAR};
 
-
     struct DetailledParticipation
     {
         double totalParticipation = 0;
@@ -257,7 +240,7 @@ class State
         {
             totalParticipation += participation;
         }
-        
+
         void addOffParticipation(double participation)
         {
             offUnitsParticipation += participation;
@@ -277,12 +260,12 @@ class State
 
     //! Reserve Participation for each STStorage cluster per reserve
     std::vector<std::map<Data::ClusterName, std::map<Data::ReserveName, double>>>
-        reserveParticipationPerSTStorageClusterForYear{ HOURS_PER_YEAR };
+      reserveParticipationPerSTStorageClusterForYear{HOURS_PER_YEAR};
 
     //! Reserve Participation for each LTStorage cluster per reserve
     std::vector<std::map<Data::ClusterName, std::map<Data::ReserveName, double>>>
-        reserveParticipationPerLTStorageClusterForYear{ HOURS_PER_YEAR };
-    
+      reserveParticipationPerLTStorageClusterForYear{HOURS_PER_YEAR};
+
     //! Reserve Participation cost for the whole year
     double reserveParticipationCostForYear[HOURS_PER_YEAR];
 
@@ -303,8 +286,7 @@ class State
     double STStorageClusterReserveParticipationCostForYear[HOURS_PER_YEAR];
 
     //! Reserves participation cost of the Long Term Storage  for the whole year
-    double LTStorageClusterReserveParticipationCostForYear[HOURS_PER_YEAR];  
-
+    double LTStorageClusterReserveParticipationCostForYear[HOURS_PER_YEAR];
 
     double renewableClusterProduction;