Antares Simulator
Power System Simulator
matrix-dp-make.hxx
1 /*
2  * Copyright 2007-2025, RTE (https://www.rte-france.com)
3  * See AUTHORS.txt
4  * SPDX-License-Identifier: MPL-2.0
5  * This file is part of Antares-Simulator,
6  * Adequacy and Performance assessment for interconnected energy networks.
7  *
8  * Antares_Simulator is free software: you can redistribute it and/or modify
9  * it under the terms of the Mozilla Public Licence 2.0 as published by
10  * the Mozilla Foundation, either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * Antares_Simulator is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * Mozilla Public Licence 2.0 for more details.
17  *
18  * You should have received a copy of the Mozilla Public Licence 2.0
19  * along with Antares_Simulator. If not, see <https://opensource.org/license/mpl-2-0/>.
20  */
21 #ifndef __ANTARES_SOLVER_MISC_MATRIX_DP_MAKE_HXX__
22 #define __ANTARES_SOLVER_MISC_MATRIX_DP_MAKE_HXX__
23 
24 namespace Antares::Solver
25 {
26 template<class T, class U1, class U2, class U3, class U4>
27 T MatrixDPMake(U1& L, U2& A, U3& B, U4& C, uint size, T* temp, bool CIsIdentity)
28 {
29  enum
30  {
32  dichotomie = 10,
34  maxLoopCount = 10,
35  };
36 
37  T rho = T(1);
38  T top = T(1);
39  T bot = T(0);
40  T r;
41 
42  if (not Cholesky<T>(L, A, size, temp))
43  {
44  for (uint j = 0; j != size; ++j)
45  {
46  for (uint k = 0; k <= j; ++k)
47  {
48  B[j][k] = A[j][k];
49  }
50  }
51  // A est definie positive ou semi-dp: pas de redressement à faire et LtL = A
52  return T(1);
53  }
54 
55  // Il faut trouver B definie positive et proche de A
56  for (uint j = 0; j != size; ++j)
57  {
58  B[j][j] = T(1);
59  }
60 
61  uint compteur = 0;
62  do
63  {
64  for (uint i = 0; i != dichotomie; ++i)
65  {
66  r = (top + bot) / T(2);
67  if (not CIsIdentity)
68  {
69  for (uint j = 0; j != size; ++j)
70  {
71  for (uint k = 0; k < j; ++k)
72  {
73  B[j][k] = A[j][k] * r + C[j][k] * (T(1) - r);
74  }
75  }
76  }
77  else
78  {
79  for (uint j = 0; j != size; ++j)
80  {
81  for (uint k = 0; k < j; ++k)
82  {
83  B[j][k] = A[j][k] * r; // + C[j][k] * (T(1) - r);
84  }
85  }
86  }
87 
88  if (Cholesky<T>(L, B, size, temp))
89  {
90  top = r;
91  }
92  else
93  {
94  bot = r;
95  rho = bot;
96  }
97  }
98 
99  if (rho < T(1))
100  {
101  // la derniere matrice n'etait pas bonne, il faut recalculer
102  if (r != rho)
103  {
104  if (!CIsIdentity)
105  {
106  for (uint j = 0; j != size; ++j)
107  {
108  for (uint k = 0; k < j; ++k)
109  {
110  B[j][k] = A[j][k] * rho + C[j][k] * (T(1) - rho);
111  }
112  }
113  }
114  else
115  {
116  for (uint j = 0; j != size; ++j)
117  {
118  for (uint k = 0; k < j; ++k)
119  {
120  B[j][k] = A[j][k] * rho; // + C[j][k] * (T(1) - rho);
121  }
122  }
123  }
124  Cholesky<T>(L, B, size, temp);
125  }
126  return rho;
127  }
128 
129  // avoid infinite loops
130  if (++compteur > maxLoopCount) // si on n'a pas eu convergence C n'est pas valide
131  {
132  return T(-1);
133  }
134  } while (true);
135 
136  return rho;
137 }
138 
139 } // namespace Antares::Solver
140 
141 #endif // __ANTARES_SOLVER_MISC_MATRIX_DP_MAKE_HXX__