Bridge++  Ver. 1.1.x
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
solver_BiCGStab_L_Cmplx.cpp
Go to the documentation of this file.
1 
15 
16 using std::valarray;
17 
18 #ifdef USE_PARAMETERS_FACTORY
19 #include "parameters_factory.h"
20 #endif
21 
22 #ifdef USE_FACTORY
23 namespace {
24  Solver *create_object(Fopr *fopr)
25  {
26  return new Solver_BiCGStab_L_Cmplx(fopr);
27  }
28 
29 
30  bool init = Solver::Factory::Register("BiCGStab_L_Cmplx", create_object);
31 }
32 #endif
33 
34 //- parameter entries
35 namespace {
36  void append_entry(Parameters& param)
37  {
38  param.Register_int("maximum_number_of_iteration", 0);
39  param.Register_double("convergence_criterion_squared", 0.0);
40 
41  param.Register_int("number_of_orthonormal_vectors", 0);
42 
43  param.Register_string("verbose_level", "NULL");
44  }
45 
46 
47 #ifdef USE_PARAMETERS_FACTORY
48  bool init_param = ParametersFactory::Register("Solver.BiCGStab_L_Cmplx", append_entry);
49 #endif
50 }
51 //- end
52 
53 //- parameters class
55 //- end
56 
57 //====================================================================
59 {
60  const string str_vlevel = params.get_string("verbose_level");
61 
62  m_vl = vout.set_verbose_level(str_vlevel);
63 
64  //- fetch and check input parameters
65  int Niter;
66  double Stop_cond;
67  int N_L;
68 
69  int err = 0;
70  err += params.fetch_int("maximum_number_of_iteration", Niter);
71  err += params.fetch_double("convergence_criterion_squared", Stop_cond);
72  err += params.fetch_int("number_of_orthonormal_vectors", N_L);
73 
74  if (err) {
75  vout.crucial(m_vl, "Solver_BiCGStab_L_Cmplx: fetch error, input parameter not found.\n");
76  abort();
77  }
78 
79 
80  set_parameters(Niter, Stop_cond);
81  set_parameters_L(N_L);
82 }
83 
84 
85 //====================================================================
86 void Solver_BiCGStab_L_Cmplx::set_parameters(const int Niter, const double Stop_cond)
87 {
88  //- print input parameters
89  vout.general(m_vl, "Parameters of Solver_BiCGStab_L_Cmplx:\n");
90  vout.general(m_vl, " Niter = %d\n", Niter);
91  vout.general(m_vl, " Stop_cond = %16.8e\n", Stop_cond);
92 
93  //- range check
94  int err = 0;
95  err += ParameterCheck::non_negative(Niter);
96  err += ParameterCheck::square_non_zero(Stop_cond);
97 
98  if (err) {
99  vout.crucial(m_vl, "Solver_BiCGStab_L_Cmplx: parameter range check failed.\n");
100  abort();
101  }
102 
103  //- store values
104  m_Niter = Niter;
105  m_Stop_cond = Stop_cond;
106 }
107 
108 
109 //====================================================================
111 {
112  //- print input parameters
113  vout.general(m_vl, " N_L = %d\n", N_L);
114 
115  //- range check
116  int err = 0;
117  err += ParameterCheck::non_negative(N_L);
118 
119  if (err) {
120  vout.crucial(m_vl, "Solver_BiCGStab_L_Cmplx: parameter range check failed.\n");
121  abort();
122  }
123 
124  //- store values
125  m_N_L = N_L;
126 }
127 
128 
129 //====================================================================
131  int& Nconv, double& diff)
132 {
133  vout.detailed(m_vl, " BiCGStab_L_Cmplx solver starts\n");
134 
135  reset_field(b);
136 
137  vout.paranoiac(m_vl, " norm of b = %16.8e\n", b.norm2());
138  vout.paranoiac(m_vl, " size of b = %d\n", b.size());
139 
140  double snorm = 1.0 / b.norm2();
141  double rr;
142 
143  Nconv = -1;
144  s = b;
145 
146  solve_init(b, rr);
147 
148  vout.detailed(m_vl, " iter: %8d %22.15e\n", 0, rr * snorm);
149 
150  for (int iter = 0; iter < m_Niter; iter++) {
151  solve_step(rr);
152 
153  vout.detailed(m_vl, " iter: %8d %22.15e\n", 2 * m_N_L * (iter + 1), rr * snorm);
154 
155  if (rr * snorm < m_Stop_cond) {
156  s = m_fopr->mult(x);
157  s -= b;
158  diff = s.norm();
159 
160  if (diff * diff * snorm < m_Stop_cond) {
161  Nconv = 2 * m_N_L * (iter + 1);
162  break;
163  }
164 
165  s = x;
166  solve_init(b, rr);
167  }
168  }
169  if (Nconv == -1) {
170  vout.crucial(m_vl, "BiCGStab_L_Cmplx solver not converged.\n");
171  abort();
172  }
173 
174  s = m_fopr->mult(x);
175  s -= b;
176  diff = s.norm();
177 
178  xq = x;
179 }
180 
181 
182 //====================================================================
184 {
185  int Nin = b.nin();
186  int Nvol = b.nvol();
187  int Nex = b.nex();
188 
189  if ((s.nin() != Nin) || (s.nvol() != Nvol) || (s.nex() != Nex)) {
190  s.reset(Nin, Nvol, Nex);
191  x.reset(Nin, Nvol, Nex);
192 
193  r_init.reset(Nin, Nvol, Nex);
194 
195  v_tmp.reset(Nin, Nvol, Nex);
196 
197  vout.paranoiac(m_vl, " Solver_BiCGStab_L_Cmplx: field size reset.\n");
198  }
199 
200  u.resize(m_N_L + 1);
201  r.resize(m_N_L + 1);
202 
203  for (int i = 0; i < m_N_L + 1; ++i) {
204  u[i].reset(Nin, Nvol, Nex);
205  r[i].reset(Nin, Nvol, Nex);
206  }
207 }
208 
209 
210 //====================================================================
211 void Solver_BiCGStab_L_Cmplx::solve_init(const Field& b, double& rr)
212 {
213  x = s;
214 
215  // r[0] = b - A x_0, x_0 = s
216  v_tmp = m_fopr->mult(x);
217  r[0] = b;
218  r[0] -= v_tmp;
219 
220  r_init = r[0];
221 
222  rr = r[0] * r[0];
223 
224  // NB. alpha_p = 0.0 \neq 1.0
225  rho_p = cmplx(1.0, 0.0);
226  alpha_p = cmplx(0.0, 0.0);
227  omega_p = cmplx(1.0, 0.0);
228 
229  u[0] = 0.0;
230 }
231 
232 
233 //====================================================================
235 {
236  double const_r, const_i;
237 
238  rho_p *= -omega_p;
239 
240  for (int j = 0; j < m_N_L; ++j) {
241  // dcomplex rho = r[j] * r_init;
242  innerprod_c(const_r, const_i, r[j], r_init);
243  dcomplex rho = cmplx(const_r, -const_i);
244 
245  dcomplex beta = alpha_p * (rho / rho_p);
246  rho_p = rho;
247 
248  for (int i = 0; i < j + 1; ++i) {
249  // u[i] = r[i] - beta * u[i];
250  mult_c(v_tmp, u[i], real(beta), imag(beta));
251  u[i] = r[i] - v_tmp;
252  }
253 
254  u[j + 1] = m_fopr->mult(u[j]);
255 
256  // dcomplex gamma = u[j+1] * r_init;
257  innerprod_c(const_r, const_i, u[j + 1], r_init);
258  dcomplex gamma = cmplx(const_r, -const_i);
259 
260  alpha_p = rho_p / gamma;
261 
262  for (int i = 0; i < j + 1; ++i) {
263  // r[i] -= alpha_p * u[i+1];
264  mult_c(v_tmp, u[i + 1], real(alpha_p), imag(alpha_p));
265  r[i] -= v_tmp;
266  }
267 
268  r[j + 1] = m_fopr->mult(r[j]);
269 
270  // x += alpha_p * u[0];
271  mult_c(v_tmp, u[0], real(alpha_p), imag(alpha_p));
272  x += v_tmp;
273  }
274 
275 
276  valarray<double> sigma(m_N_L + 1);
277  valarray<dcomplex> gamma_prime(m_N_L + 1);
278 
279  // NB. tau(m_N_L,m_N_L+1), not (m_N_L+1,m_N_L+1)
280  valarray<dcomplex> tau(m_N_L * (m_N_L + 1));
281  int ij, ji;
282 
283  for (int j = 1; j < m_N_L + 1; ++j) {
284  for (int i = 1; i < j; ++i) {
285  ij = index_ij(i, j);
286 
287  // tau[i,j] = (r[j] * r[i]) / sigma[i];
288  innerprod_c(const_r, const_i, r[j], r[i]);
289  tau[ij] = cmplx(const_r, -const_i) / sigma[i];
290 
291  // r[ j] -= tau[i,j] * r[i];
292  mult_c(v_tmp, r[i], real(tau[ij]), imag(tau[ij]));
293  r[j] -= v_tmp;
294  }
295 
296 
297  sigma[j] = r[j] * r[j];
298 
299 
300  // gamma_prime[j] = (r[0] * r[j]) / sigma[j];
301  innerprod_c(const_r, const_i, r[0], r[j]);
302  gamma_prime[j] = cmplx(const_r, -const_i) / sigma[j];
303  }
304 
305 
306  valarray<dcomplex> gamma(m_N_L + 1);
307  dcomplex c_tmp;
308 
309  gamma[m_N_L] = gamma_prime[m_N_L];
310  omega_p = gamma[m_N_L];
311 
312  for (int j = m_N_L - 1; j > 0; --j) {
313  c_tmp = cmplx(0.0, 0.0);
314 
315  for (int i = j + 1; i < m_N_L + 1; ++i) {
316  ji = index_ij(j, i);
317  c_tmp += tau[ji] * gamma[i];
318  }
319 
320  gamma[j] = gamma_prime[j] - c_tmp;
321  }
322 
323 
324  // NB. gamma_double_prime(m_N_L), not (m_N_L+1)
325  valarray<dcomplex> gamma_double_prime(m_N_L);
326 
327  for (int j = 1; j < m_N_L; ++j) {
328  c_tmp = cmplx(0.0, 0.0);
329 
330  for (int i = j + 1; i < m_N_L; ++i) {
331  ji = index_ij(j, i);
332  c_tmp += tau[ji] * gamma[i + 1];
333  }
334 
335  gamma_double_prime[j] = gamma[j + 1] + c_tmp;
336  }
337 
338  // x += gamma[ 1] * r[ 0];
339  // r[0] -= gamma_prime[m_N_L] * r[m_N_L];
340  // u[0] -= gamma[ m_N_L] * u[m_N_L];
341 
342  mult_c(v_tmp, r[0], real(gamma[1]), imag(gamma[1]));
343  x += v_tmp;
344 
345  mult_c(v_tmp, r[m_N_L], real(gamma_prime[m_N_L]), imag(gamma_prime[m_N_L]));
346  r[0] -= v_tmp;
347 
348  mult_c(v_tmp, u[m_N_L], real(gamma[m_N_L]), imag(gamma[m_N_L]));
349  u[0] -= v_tmp;
350 
351 
352  for (int j = 1; j < m_N_L; ++j) {
353  // x += gamma_double_prime[j] * r[j];
354  // r[0] -= gamma_prime[ j] * r[j];
355  // u[0] -= gamma[ j] * u[j];
356 
357  mult_c(v_tmp, r[j], real(gamma_double_prime[j]), imag(gamma_double_prime[j]));
358  x += v_tmp;
359 
360  mult_c(v_tmp, r[j], real(gamma_prime[j]), imag(gamma_prime[j]));
361  r[0] -= v_tmp;
362 
363  mult_c(v_tmp, u[j], real(gamma[j]), imag(gamma[j]));
364  u[0] -= v_tmp;
365  }
366 
367  rr = r[0] * r[0];
368 }
369 
370 
371 //====================================================================
372 void Solver_BiCGStab_L_Cmplx::innerprod_c(double& prod_r, double& prod_i,
373  const Field& v, const Field& w)
374 {
375  // prod = (v,w);
376 
377  int size = w.size();
378 
379  assert(v.size() == size);
380 
381  prod_r = 0.0;
382  prod_i = 0.0;
383 
384  for (int i = 0; i < size; i += 2) {
385  prod_r += v.cmp(i) * w.cmp(i) + v.cmp(i + 1) * w.cmp(i + 1);
386  prod_i += v.cmp(i) * w.cmp(i + 1) - v.cmp(i + 1) * w.cmp(i);
387  }
388 
389  prod_r = Communicator::reduce_sum(prod_r);
390  prod_i = Communicator::reduce_sum(prod_i);
391 }
392 
393 
394 //====================================================================
396  const Field& w,
397  const double& prod_r, const double& prod_i)
398 {
399  // v = dcomplex(prod_r,prod_i) * w;
400 
401  int size = w.size();
402 
403  assert(v.size() == size);
404 
405  double vr, vi;
406  for (int i = 0; i < size; i += 2) {
407  vr = prod_r * w.cmp(i) - prod_i * w.cmp(i + 1);
408  vi = prod_r * w.cmp(i + 1) + prod_i * w.cmp(i);
409 
410  v.set(i, vr);
411  v.set(i + 1, vi);
412  }
413 }
414 
415 
416 //====================================================================
417 //============================================================END=====