diff --git a/mex/sources/bytecode/SparseMatrix.cc b/mex/sources/bytecode/SparseMatrix.cc
index a38e8207105f549ffc957ff281733a5ea35162da..cca9eaf234dff8f0c4de8e308d8688f4e5d31a34 100644
--- a/mex/sources/bytecode/SparseMatrix.cc
+++ b/mex/sources/bytecode/SparseMatrix.cc
@@ -2050,215 +2050,216 @@ dynSparseMatrix::golden(double ax, double bx, double cx, double tol, double solv
 }
 
 void
-dynSparseMatrix::Solve_Matlab_Relaxation(mxArray *A_m, mxArray *b_m, unsigned int Size, double slowc_l, bool is_two_boundaries, int it_)
+dynSparseMatrix::Solve_Matlab_Relaxation(mxArray *A_m, mxArray *b_m, unsigned int Size, double slowc_l, int it_)
 {
   double *b_m_d = mxGetPr(b_m);
   if (!b_m_d)
     throw FatalExceptionHandling(" in Solve_Matlab_Relaxation, can't retrieve b_m vector\n");
   mwIndex *A_m_i = mxGetIr(A_m);
   if (!A_m_i)
-    throw FatalExceptionHandling(" in Solve_Matlab_Relaxation, can't allocate A_m_i index vector\n");
+    throw FatalExceptionHandling(" in Solve_Matlab_Relaxation, can't retrieve Ir vector of matrix A\n");
   mwIndex *A_m_j = mxGetJc(A_m);
   if (!A_m_j)
-    throw FatalExceptionHandling(" in Solve_Matlab_Relaxation, can't allocate A_m_j index vector\n");
+    throw FatalExceptionHandling(" in Solve_Matlab_Relaxation, can't retrieve Jc vectior of matrix A\n");
   double *A_m_d = mxGetPr(A_m);
   if (!A_m_d)
-    throw FatalExceptionHandling(" in Solve_Matlab_Relaxation, can't retrieve A matrix\n");
-  size_t max_nze = A_m_j[Size*periods];
-  unsigned nze = 0;
-  size_t var = A_m_j[nze];
+    throw FatalExceptionHandling(" in Solve_Matlab_Relaxation, can't retrieve double float data of matrix A\n");
+
+  /* Extract submatrices from the upper-left corner of A and subvectors at the
+     beginning of b, so that the system looks like:
+     ⎛B1 C1 …⎞   ⎛b1⎞
+     ⎢A2 B2 …⎥   ⎢b2⎥
+     ⎢   A3 …⎥ = ⎢ …⎥
+     ⎢    … …⎥   ⎢ …⎥
+     ⎝      …⎠   ⎝ …⎠
+  */
   mxArray *B1 = mxCreateSparse(Size, Size, Size*Size, mxREAL);
   mwIndex *B1_i = mxGetIr(B1);
   mwIndex *B1_j = mxGetJc(B1);
   double *B1_d = mxGetPr(B1);
-  unsigned B1_nze = 0, B1_var = 0;
-  B1_i[B1_nze] = 0;
-  B1_j[B1_var] = 0;
   mxArray *C1 = mxCreateSparse(Size, Size, Size*Size, mxREAL);
   mwIndex *C1_i = mxGetIr(C1);
   mwIndex *C1_j = mxGetJc(C1);
   double *C1_d = mxGetPr(C1);
-  unsigned C1_nze = 0, C1_var = 0;
-  C1_i[C1_nze] = 0;
-  C1_j[C1_var] = 0;
   mxArray *A2 = mxCreateSparse(Size, Size, Size*Size, mxREAL);
   mwIndex *A2_i = mxGetIr(A2);
   mwIndex *A2_j = mxGetJc(A2);
   double *A2_d = mxGetPr(A2);
-  unsigned A2_nze = 0, A2_var = 0;
-  A2_i[A2_nze] = 0;
-  A2_j[A2_var] = 0;
   mxArray *B2 = mxCreateSparse(Size, Size, Size*Size, mxREAL);
   mwIndex *B2_i = mxGetIr(B2);
   mwIndex *B2_j = mxGetJc(B2);
   double *B2_d = mxGetPr(B2);
-  unsigned B2_nze = 0, B2_var = 0;
-  B2_i[B2_nze] = 0;
-  B2_j[B2_var] = 0;
   mxArray *A3 = mxCreateSparse(Size, Size, Size*Size, mxREAL);
   mwIndex *A3_i = mxGetIr(A3);
   mwIndex *A3_j = mxGetJc(A3);
   double *A3_d = mxGetPr(A3);
-  unsigned A3_nze = 0, A3_var = 0;
-  A3_i[A3_nze] = 0;
-  A3_j[A3_var] = 0;
+
   mxArray *b1 = mxCreateDoubleMatrix(Size, 1, mxREAL);
   double *b1_d = mxGetPr(b1);
   mxArray *b2 = mxCreateDoubleMatrix(Size, 1, mxREAL);
   double *b2_d = mxGetPr(b2);
-  size_t eq = 0;
-  /*B1 C1
-    A2 B2
-    A3*/
-  while (var < 2*Size && nze < max_nze)
+
+  unsigned int nze = 0; // Counter in nonzero elements of A
+  unsigned int B1_nze = 0, C1_nze = 0, A2_nze = 0, B2_nze = 0, A3_nze = 0; // Same for submatrices
+
+  for (size_t var = 0; var < 2*Size; var++) // Iterate over columns of A
     {
-      if (static_cast<unsigned int>(A_m_j[var+1]) <= nze)
+      if (var < Size)
         {
-          if (var < Size)
-            b1_d[var] = b_m_d[var];
-          else
-            b2_d[var - Size] = b_m_d[var];
-          var++;
+          b1_d[var] = b_m_d[var];
+
+          B1_j[var] = B1_nze;
+          A2_j[var] = A2_nze;
         }
-      eq = A_m_i[nze];
-      if (var < Size)
+      else
         {
-          if (eq < Size)
-            {
-              while (B1_var < var)
-                B1_j[++B1_var] = B1_nze;
-              B1_i[B1_nze] = eq;
-              B1_d[B1_nze] = A_m_d[nze];
-              B1_nze++;
-            }
-          else
-            {
-              while (A2_var < var)
-                A2_j[++A2_var] = A2_nze;
-              A2_i[A2_nze] = eq - Size;
-              A2_d[A2_nze] = A_m_d[nze];
-              A2_nze++;
-            }
+          b2_d[var - Size] = b_m_d[var];
+
+          C1_j[var - Size] = C1_nze;
+          B2_j[var - Size] = B2_nze;
+          A3_j[var - Size] = A3_nze;
         }
-      else if (var < 2*Size)
+
+      while (static_cast<unsigned int>(A_m_j[var+1]) > nze)
         {
-          if (eq < Size)
-            {
-              while (C1_var < var - Size)
-                C1_j[++C1_var] = C1_nze;
-              C1_i[C1_nze] = eq;
-              C1_d[C1_nze] = A_m_d[nze];
-              C1_nze++;
-            }
-          else if (eq < 2*Size)
+          size_t eq = A_m_i[nze];
+          if (var < Size)
             {
-              while (B2_var < var - Size)
-                B2_j[++B2_var] = B2_nze;
-              B2_i[B2_nze] = eq - Size;
-              B2_d[B2_nze] = A_m_d[nze];
-              B2_nze++;
+              if (eq < Size)
+                {
+                  B1_i[B1_nze] = eq;
+                  B1_d[B1_nze] = A_m_d[nze];
+                  B1_nze++;
+                }
+              else // Here we know that eq < 2*Size, because of the structure of A
+                {
+                  A2_i[A2_nze] = eq - Size;
+                  A2_d[A2_nze] = A_m_d[nze];
+                  A2_nze++;
+                }
             }
-          else
+          else if (var < 2*Size)
             {
-              while (A3_var < var - Size)
-                A3_j[++A3_var] = A3_nze;
-              A3_i[A3_nze] = eq - 2*Size;
-              A3_d[A3_nze] = A_m_d[nze];
-              A3_nze++;
+              if (eq < Size)
+                {
+                  C1_i[C1_nze] = eq;
+                  C1_d[C1_nze] = A_m_d[nze];
+                  C1_nze++;
+                }
+              else if (eq < 2*Size)
+                {
+                  B2_i[B2_nze] = eq - Size;
+                  B2_d[B2_nze] = A_m_d[nze];
+                  B2_nze++;
+                }
+              else // Here we know that eq < 3*Size, because of the structure of A
+                {
+                  A3_i[A3_nze] = eq - 2*Size;
+                  A3_d[A3_nze] = A_m_d[nze];
+                  A3_nze++;
+                }
             }
+          nze++;
         }
-      nze++;
     }
-  while (B1_var < Size)
-    B1_j[++B1_var] = B1_nze;
-  while (C1_var < Size)
-    C1_j[++C1_var] = C1_nze;
-  while (A2_var < Size)
-    A2_j[++A2_var] = A2_nze;
-  while (B2_var < Size)
-    B2_j[++B2_var] = B2_nze;
-  while (A3_var < Size)
-    A3_j[++A3_var] = A3_nze;
-  mxArray *d1 = nullptr;
+  B1_j[Size] = B1_nze;
+  C1_j[Size] = C1_nze;
+  A2_j[Size] = A2_nze;
+  B2_j[Size] = B2_nze;
+  A3_j[Size] = A3_nze;
+
   vector<pair<mxArray *, mxArray *>> triangular_form;
-  double sumc = 0, C_sumc = 1000;
-  mxArray *B1_inv = nullptr;
-  mxArray *B1_inv_t = nullptr;
+  mxArray *d1 = nullptr;
   for (int t = 1; t <= periods; t++)
     {
-      if (abs(sumc / C_sumc -1) > 1e-10*res1)
-        {
-          C_sumc = sumc;
-          if (B1_inv)
-            mxDestroyArray(B1_inv);
-          mexCallMATLAB(1, &B1_inv, 1, &B1, "inv");
-          mwIndex *B_inv_j = mxGetJc(B1_inv);
-          size_t B_inv_nze = B_inv_j[Size];
-          double *B_inv_d = mxGetPr(B1_inv);
-          sumc = 0;
-          for (unsigned int i = 0; i < B_inv_nze; i++)
-            sumc += fabs(B_inv_d[i]);
-        }
-      B1_inv_t = Sparse_transpose(B1_inv);
-      mxArray *S1 = Sparse_mult_SAT_SB(B1_inv_t, C1);
+      mxArray *B1_inv;
+      mexCallMATLAB(1, &B1_inv, 1, &B1, "inv");
 
+      // Compute subvector d1 of the triangularized system.
+      mxArray *B1_inv_t = Sparse_transpose(B1_inv);
+      mxDestroyArray(B1_inv);
       d1 = mult_SAT_B(B1_inv_t, b1);
+
+      /* Compute block S1 of the triangularized system.
+         Update B1, C1, B2, A2, A3, b1 and b2 for the next relaxation iteration.
+         Save S1 and d1 for the subsequent backward iteration.
+         E.g. at the end of the first iteration, the system will look like:
+         ⎛ I S1  … …⎞   ⎛d1⎞
+         ⎢   B1 C1 …⎥   ⎢b1⎥
+         ⎢   A2 B2 …⎥ = ⎢b2⎥
+         ⎢      A3 …⎥   ⎢ …⎥
+         ⎝         …⎠   ⎝ …⎠
+      */
       if (t < periods)
-        //Computation for the next lines
         {
-          mxDestroyArray(B1_inv_t);
-          mxArray *A2_t = Sparse_transpose(A2);
-          mxDestroyArray(A2);
+          // Compute S1
+          mxArray *S1 = Sparse_mult_SAT_SB(B1_inv_t, C1);
 
+          // Update A2, B1, b1
+          mxArray *A2_t = Sparse_transpose(A2);
           mxArray *tmp = Sparse_mult_SAT_SB(A2_t, S1);
           mxDestroyArray(B1);
           B1 = Sparse_substract_SA_SB(B2, tmp);
           mxDestroyArray(tmp);
 
           tmp = mult_SAT_B(A2_t, d1);
+          mxDestroyArray(A2_t);
+          mxDestroyArray(b1);
           b1 = substract_A_B(b2, tmp);
           mxDestroyArray(tmp);
 
+          mxDestroyArray(A2);
+          A2 = mxDuplicateArray(A3);
+
+          // Save S1 and d1
           triangular_form.emplace_back(S1, d1);
-          mxDestroyArray(A2_t);
         }
-      A2 = mxDuplicateArray(A3);
-
-      //I  S1
-      //0  B1 C1  =>B1 =
-      //   A2 B2  => A2 = A3
-      //      A3
-      C1_nze = B2_nze = A3_nze = 0;
-      C1_var = B2_var = A3_var = 0;
-
-      if (nze < max_nze)
-        nze--;
-      while (var < (t+2)*Size && nze < max_nze)
+
+      mxDestroyArray(B1_inv_t);
+
+      if (t < periods - 1)
         {
-          if (static_cast<unsigned int>(A_m_j[var+1]) <= nze)
-            {
-              b2_d[var - (t+1) * Size] = b_m_d[var];
-              var++;
-            }
-          eq = A_m_i[nze];
-          if (eq < (t+1) * Size)
-            {
-              C1_d[C1_nze] = A_m_d[nze];
-              C1_nze++;
-            }
-          else if (eq < (t+2)*Size)
+          // Update C1, B2, A3, b2
+          C1_nze = B2_nze = A3_nze = 0;
+          for (size_t var = (t+1)*Size; var < (t+2)*Size; var++)
             {
-              B2_d[B2_nze] = A_m_d[nze];
-              B2_nze++;
-            }
-          else
-            {
-              A3_d[A3_nze] = A_m_d[nze];
-              A3_nze++;
+              b2_d[var - (t+1)*Size] = b_m_d[var];
+
+              C1_j[var - (t+1)*Size] = C1_nze;
+              B2_j[var - (t+1)*Size] = B2_nze;
+              A3_j[var - (t+1)*Size] = A3_nze;
+
+              while (static_cast<unsigned int>(A_m_j[var+1]) > nze)
+                {
+                  size_t eq = A_m_i[nze];
+                  if (eq < (t+1) * Size)
+                    {
+                      C1_i[C1_nze] = eq - t*Size;
+                      C1_d[C1_nze] = A_m_d[nze];
+                      C1_nze++;
+                    }
+                  else if (eq < (t+2)*Size)
+                    {
+                      B2_i[B2_nze] = eq - (t+1)*Size;
+                      B2_d[B2_nze] = A_m_d[nze];
+                      B2_nze++;
+                    }
+                  else
+                    {
+                      A3_i[A3_nze] = eq - (t+2)*Size;
+                      A3_d[A3_nze] = A_m_d[nze];
+                      A3_nze++;
+                    }
+                  nze++;
+                }
             }
-          nze++;
+          C1_j[Size] = C1_nze;
+          B2_j[Size] = B2_nze;
+          A3_j[Size] = A3_nze;
         }
     }
+
+  // At this point, d1 contains the solution for the last period
   double *d1_d = mxGetPr(d1);
   for (unsigned i = 0; i < Size; i++)
     {
@@ -2268,17 +2269,19 @@ dynSparseMatrix::Solve_Matlab_Relaxation(mxArray *A_m, mxArray *b_m, unsigned in
       y[eq] += slowc_l * yy;
     }
 
-  pair<mxArray *, mxArray *> tf;
+  // Perform backward iteration to compute the solution for other periods
   for (int t = periods-2; t >= 0; t--)
     {
-      mxArray *tmp;
-      tf = triangular_form.back();
+      auto [S1, d1_next] = triangular_form.back();
       triangular_form.pop_back();
-      mxArray *tf_first_t = Sparse_transpose(tf.first);
-      mxDestroyArray(tf.first);
-      tmp = mult_SAT_B(tf_first_t, d1);
-      d1 = substract_A_B(tf.second, tmp);
+      mxArray *S1_t = Sparse_transpose(S1);
+      mxDestroyArray(S1);
+      mxArray *tmp = mult_SAT_B(S1_t, d1);
+      mxDestroyArray(S1_t);
+      mxDestroyArray(d1);
+      d1 = substract_A_B(d1_next, tmp);
       d1_d = mxGetPr(d1);
+      mxDestroyArray(d1_next);
       mxDestroyArray(tmp);
       for (unsigned i = 0; i < Size; i++)
         {
@@ -2287,9 +2290,8 @@ dynSparseMatrix::Solve_Matlab_Relaxation(mxArray *A_m, mxArray *b_m, unsigned in
           direction[eq] = yy;
           y[eq] += slowc_l * yy;
         }
-      mxDestroyArray(tf_first_t);
-      mxDestroyArray(tf.second);
     }
+
   mxDestroyArray(B1);
   mxDestroyArray(C1);
   mxDestroyArray(A2);
@@ -2299,6 +2301,7 @@ dynSparseMatrix::Solve_Matlab_Relaxation(mxArray *A_m, mxArray *b_m, unsigned in
   mxDestroyArray(b2);
   mxDestroyArray(A_m);
   mxDestroyArray(b_m);
+  mxDestroyArray(d1);
 }
 
 void
@@ -4191,7 +4194,7 @@ dynSparseMatrix::Simulate_Newton_Two_Boundaries(int blck, int y_size, int y_kmin
       if (stack_solve_algo == 0 || stack_solve_algo == 4)
         Solve_LU_UMFPack(Ap, Ai, Ax, b, Size * periods, Size, slowc, true, 0, vector_table_conditional_local);
       else if (stack_solve_algo == 1)
-        Solve_Matlab_Relaxation(A_m, b_m, Size, slowc, true, 0);
+        Solve_Matlab_Relaxation(A_m, b_m, Size, slowc, 0);
       else if (stack_solve_algo == 2)
         Solve_Matlab_GMRES(A_m, b_m, Size, slowc, blck, true, 0, x0_m);
       else if (stack_solve_algo == 3)
diff --git a/mex/sources/bytecode/SparseMatrix.hh b/mex/sources/bytecode/SparseMatrix.hh
index de533dab5db19d7d61144f497ed2e07e19878694..8a97f7e917009e26b7a7b9e560776c8868aa4aa8 100644
--- a/mex/sources/bytecode/SparseMatrix.hh
+++ b/mex/sources/bytecode/SparseMatrix.hh
@@ -76,7 +76,7 @@ private:
   bool golden(double ax, double bx, double cx, double tol, double solve_tolf, double *xmin);
   void Solve_ByteCode_Symbolic_Sparse_GaussianElimination(int Size, bool symbolic, int Block_number);
   bool Solve_ByteCode_Sparse_GaussianElimination(int Size, int blck, int it_);
-  void Solve_Matlab_Relaxation(mxArray *A_m, mxArray *b_m, unsigned int Size, double slowc_l, bool is_two_boundaries, int it_);
+  void Solve_Matlab_Relaxation(mxArray *A_m, mxArray *b_m, unsigned int Size, double slowc_l, int it_);
   void Solve_Matlab_LU_UMFPack(mxArray *A_m, mxArray *b_m, int Size, double slowc_l, bool is_two_boundaries, int it_);
   static void Print_UMFPack(const SuiteSparse_long *Ap, const SuiteSparse_long *Ai, const double *Ax, int n);
   static void Printfull_UMFPack(const SuiteSparse_long *Ap, const SuiteSparse_long *Ai, const double *Ax, const double *b, int n);