Bridge++  Version 1.5.4
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
decompose_LUP_Cmplx.cpp
Go to the documentation of this file.
1 
14 #include "decompose_LUP_Cmplx.h"
15 
16 //====================================================================
17 void Decompose_LUP_Cmplx::set_matrix(const double *mat)
18 {
19  for (int i = 0; i < size; ++i) {
20  m_lu[i] = mat[i];
21  }
22 
23  // scale factor
24  std::valarray<double> scale(N);
25  for (int i = 0; i < N; ++i) {
26  scale[i] = 1;
27  }
28  double epsilon = DBL_EPSILON;
29  m_sign = 1;
30  // define scale;
31  // abort singlar matrix
32  for (int i = 0; i < N; ++i) {
33  double max_norm = 0;
34  for (int j = 0; j < N; ++j) {
35  double norm2 = m_lu[re(i, j)] * m_lu[re(i, j)] + m_lu[im(i, j)] * m_lu[im(i, j)];
36  if (norm2 > max_norm) {
37  max_norm = norm2;
38  }
39  if (max_norm < epsilon) {
40  // assert
41  }
42  scale[i] = max_norm;
43  }
44  }
45 
46  for (int r = 0; r < N - 1; ++r) {
47  // pivot
48  double max = 0;
49  for (int i = r; i < N; ++i) {
50  double norm_ir = m_lu[re(i, r)] * m_lu[re(i, r)] + m_lu[im(i, r)] * m_lu[im(i, r)];
51  if (norm_ir > scale[i] * max) {
52  max = norm_ir;
53  m_pivot[r] = i;
54  }
55  }
56 
57  // pivot (a_{rj} <-> a_{pj})
58  if (m_pivot[r] != r) {
59  int p = m_pivot[r];
60  for (int j = 0; j < N; ++j) {
61  std::swap(m_lu[re(r, j)], m_lu[re(p, j)]);
62  std::swap(m_lu[im(r, j)], m_lu[im(p, j)]);
63  }
64  std::swap(scale[r], scale[p]);
65  m_sign *= -1;
66  }
67  double inv_rr_re = m_lu[re(r, r)] / max;
68  double inv_rr_im = -m_lu[im(r, r)] / max;
69  // a_{ir} /= a_{rr}
70  // a_{ij} -= a_{ir} a_{rj} (j > r)
71  for (int i = r + 1; i < N; ++i) {
72  double ir_re = m_lu[re(i, r)];
73  double ir_im = m_lu[im(i, r)];
74  m_lu[re(i, r)] = ir_re * inv_rr_re - ir_im * inv_rr_im;
75  m_lu[im(i, r)] = ir_re * inv_rr_im + ir_im * inv_rr_re;
76  ir_re = m_lu[re(i, r)];
77  ir_im = m_lu[im(i, r)];
78 
79  for (int j = r + 1; j < N; ++j) {
80  double& rj_re = m_lu[re(r, j)];
81  double& rj_im = m_lu[im(r, j)];
82  m_lu[re(i, j)] -= ir_re * rj_re - ir_im * rj_im;
83  m_lu[im(i, j)] -= ir_re * rj_im + ir_im * rj_re;
84  }
85  }
86  }
87 
88  m_pivot[N - 1] = N - 1;
89 }
90 
91 
92 //====================================================================
93 void Decompose_LUP_Cmplx::solve(double *vec)
94 {
95  // Pivot
96  for (int i = 0; i < N; ++i) {
97  std::swap(vec[re(i)], vec[re(m_pivot[i])]);
98  std::swap(vec[im(i)], vec[im(m_pivot[i])]);
99  }
100 
101  // Forward substitution
102  for (int i = 0; i < N; ++i) {
103  for (int j = 0; j < i; ++j) {
104  vec[re(i)] -= m_lu[re(i, j)] * vec[re(j)] - m_lu[im(i, j)] * vec[im(j)];
105  vec[im(i)] -= m_lu[re(i, j)] * vec[im(j)] + m_lu[im(i, j)] * vec[re(j)];
106  }
107  }
108 
109  // Back substitution
110  for (int i = N - 1; i >= 0; --i) {
111  for (int j = i + 1; j < N; ++j) {
112  vec[re(i)] -= m_lu[re(i, j)] * vec[re(j)] - m_lu[im(i, j)] * vec[im(j)];
113  vec[im(i)] -= m_lu[re(i, j)] * vec[im(j)] + m_lu[im(i, j)] * vec[re(j)];
114  }
115  double inv_norm = 1 / (m_lu[re(i, i)] * m_lu[re(i, i)] + m_lu[im(i, i)] * m_lu[im(i, i)]);
116  double real = vec[re(i)];
117  double imag = vec[im(i)];
118 
119  vec[re(i)] = (real * m_lu[re(i, i)] + imag * m_lu[im(i, i)]) * inv_norm;
120  vec[im(i)] = (imag * m_lu[re(i, i)] - real * m_lu[im(i, i)]) * inv_norm;
121  }
122 }
123 
124 
125 //====================================================================
127 {
128  for (int i = 0; i < size; ++i) {
129  mat[i] = 0;
130  }
131  for (int i = 0; i < N; ++i) {
132  mat[re(i, i)] = 1;
133  }
134 
135  mult_inverse(mat);
136 }
137 
138 
139 //====================================================================
141 {
142  // Pivot
143  for (int i = 0; i < N; ++i) {
144  for (int j = 0; j < N; ++j) {
145  std::swap(mat[re(i, j)], mat[re(m_pivot[i], j)]);
146  std::swap(mat[im(i, j)], mat[im(m_pivot[i], j)]);
147  }
148  }
149 
150  // Forward substitution
151  for (int i = 0; i < N; ++i) {
152  for (int r = 0; r < i; ++r) {
153  double& luir_re = m_lu[re(i, r)];
154  double& luir_im = m_lu[im(i, r)];
155  for (int j = 0; j < N; ++j) {
156  mat[re(i, j)] -= luir_re * mat[re(r, j)] - luir_im * mat[im(r, j)];
157  mat[im(i, j)] -= luir_re * mat[im(r, j)] + luir_im * mat[re(r, j)];
158  }
159  }
160  }
161 
162  // Back substitution
163  for (int i = N - 1; i >= 0; --i) {
164  for (int r = i + 1; r < N; ++r) {
165  double& luir_re = m_lu[re(i, r)];
166  double& luir_im = m_lu[im(i, r)];
167  for (int j = 0; j < N; ++j) {
168  mat[re(i, j)] -= luir_re * mat[re(r, j)] - luir_im * mat[im(r, j)];
169  mat[im(i, j)] -= luir_re * mat[im(r, j)] + luir_im * mat[re(r, j)];
170  }
171  }
172  for (int j = 0; j < N; ++j) {
173  double inv = 1 / (m_lu[re(i, i)] * m_lu[re(i, i)] + m_lu[im(i, i)] * m_lu[im(i, i)]);
174  double real = mat[re(i, j)];
175  double imag = mat[im(i, j)];
176 
177  mat[re(i, j)] = (real * m_lu[re(i, i)] + imag * m_lu[im(i, i)]) * inv;
178  mat[im(i, j)] = (imag * m_lu[re(i, i)] - real * m_lu[im(i, i)]) * inv;
179  }
180  }
181 }
182 
183 
184 //====================================================================
186 {
187  double real = m_sign;
188  double imag = 0;
189 
190  for (int i = 0; i < N; ++i) {
191  double old_re = real;
192  double old_im = imag;
193  real = old_re * m_lu[re(i, i)] - old_im * m_lu[im(i, i)];
194  imag = old_re * m_lu[im(i, i)] + old_im * m_lu[re(i, i)];
195  }
196 
197  return cmplx(real, imag);
198 }
199 
200 
201 //====================================================================
202 
203 /*
204 void Decompose_LU_Cmplx::copy_LU(double* l, double* u)
205 {
206  for (int i = 0; i < N; ++i) {
207  for (int j = 0; j < i; ++j) {
208  l[re(i,j)] = m_lu[re(i,j)];
209  l[im(i,j)] = m_lu[im(i,j)];
210  u[re(i,j)] = 0;
211  u[im(i,j)] = 0;
212  }
213  l[re(i,i)] = 1;
214  l[im(i,i)] = 0;
215  u[re(i,i)] = m_lu[re(i,i)];
216  u[im(i,i)] = m_lu[im(i,i)];
217  for (int j = i+1; j < N; ++j) {
218  l[re(i,j)] = 0;
219  l[im(i,j)] = 0;
220  u[re(i,j)] = m_lu[re(i,j)];
221  u[im(i,j)] = m_lu[im(i,j)];
222  }
223  }
224 
225 }
226 */
227 
228 //====================================================================
size_t re(int i, int j)
void solve(double *vec)
void mult_inverse(double *mat)
std::valarray< int > m_pivot
size_t im(int i, int j)
void get_inverse(double *mat_inv)
void set_matrix(const double *mat)
std::valarray< double > m_lu