Bridge++  Ver. 1.1.x
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
solver_BiCGStab_Cmplx.cpp
Go to the documentation of this file.
1 
14 #include "solver_BiCGStab_Cmplx.h"
15 
16 #ifdef USE_PARAMETERS_FACTORY
17 #include "parameters_factory.h"
18 #endif
19 
20 #ifdef USE_FACTORY
21 namespace {
22  Solver *create_object(Fopr *fopr)
23  {
24  return new Solver_BiCGStab_Cmplx(fopr);
25  }
26 
27 
28  bool init = Solver::Factory::Register("BiCGStab_Cmplx", create_object);
29 }
30 #endif
31 
32 //- parameter entries
33 namespace {
34  void append_entry(Parameters& param)
35  {
36  param.Register_int("maximum_number_of_iteration", 0);
37  param.Register_double("convergence_criterion_squared", 0.0);
38 
39  param.Register_string("verbose_level", "NULL");
40  }
41 
42 
43 #ifdef USE_PARAMETERS_FACTORY
44  bool init_param = ParametersFactory::Register("Solver.BiCGStab_Cmplx", append_entry);
45 #endif
46 }
47 //- end
48 
49 //- parameters class
51 //- end
52 
53 //====================================================================
55 {
56  const string str_vlevel = params.get_string("verbose_level");
57 
58  m_vl = vout.set_verbose_level(str_vlevel);
59 
60  //- fetch and check input parameters
61  int Niter;
62  double Stop_cond;
63 
64  int err = 0;
65  err += params.fetch_int("maximum_number_of_iteration", Niter);
66  err += params.fetch_double("convergence_criterion_squared", Stop_cond);
67 
68  if (err) {
69  vout.crucial(m_vl, "Solver_BiCGStab_Cmplx: fetch error, input parameter not found.\n");
70  abort();
71  }
72 
73 
74  set_parameters(Niter, Stop_cond);
75 }
76 
77 
78 //====================================================================
79 void Solver_BiCGStab_Cmplx::set_parameters(const int Niter, const double Stop_cond)
80 {
81  //- print input parameters
82  vout.general(m_vl, "Parameters of Solver_BiCGStab_Cmplx:\n");
83  vout.general(m_vl, " Niter = %d\n", Niter);
84  vout.general(m_vl, " Stop_cond = %16.8e\n", Stop_cond);
85 
86  //- range check
87  int err = 0;
88  err += ParameterCheck::non_negative(Niter);
89  err += ParameterCheck::square_non_zero(Stop_cond);
90 
91  if (err) {
92  vout.crucial(m_vl, "Solver_BiCGStab_Cmplx: parameter range check failed.\n");
93  abort();
94  }
95 
96  //- store values
97  m_Niter = Niter;
98  m_Stop_cond = Stop_cond;
99 }
100 
101 
102 //====================================================================
104  int& Nconv, double& diff)
105 {
106  vout.paranoiac(m_vl, " BiCGStab_Cmplx solver starts\n");
107 
108  reset_field(b);
109 
110  vout.paranoiac(m_vl, " norm of b = %16.8e\n", b.norm2());
111  vout.paranoiac(m_vl, " size of b = %d\n", b.size());
112 
113  reset_field(b);
114 
115  double snorm = 1.0 / b.norm2();
116  double rr;
117 
118  Nconv = -1;
119  s = b;
120 
121  solve_init(b, rr);
122 
123  vout.detailed(m_vl, " iter: %8d %22.15e\n", 0, rr * snorm);
124 
125  for (int iter = 0; iter < m_Niter; iter++) {
126  solve_step(rr);
127 
128  vout.detailed(m_vl, " iter: %8d %22.15e\n", 2 * (iter + 1), rr * snorm);
129 
130  if (rr * snorm < m_Stop_cond) {
131  s = m_fopr->mult(x);
132  s -= b;
133  diff = s.norm();
134 
135  if (diff * diff * snorm < m_Stop_cond) {
136  Nconv = 2 * (iter + 1);
137  break;
138  }
139 
140  s = x;
141  solve_init(b, rr);
142  }
143  }
144  if (Nconv == -1) {
145  vout.crucial(m_vl, "BiCGStab_Cmplx solver not converged.\n");
146  abort();
147  }
148 
149  p = m_fopr->mult(x);
150  p -= b;
151  diff = p.norm();
152 
153  xq = x;
154 }
155 
156 
157 //====================================================================
159 {
160  int Nin = b.nin();
161  int Nvol = b.nvol();
162  int Nex = b.nex();
163 
164  if ((s.nin() != Nin) || (s.nvol() != Nvol) || (s.nex() != Nex)) {
165  s.reset(Nin, Nvol, Nex);
166  r.reset(Nin, Nvol, Nex);
167  x.reset(Nin, Nvol, Nex);
168  p.reset(Nin, Nvol, Nex);
169  v.reset(Nin, Nvol, Nex);
170 
171  w.reset(Nin, Nvol, Nex);
172 
173  rh.reset(Nin, Nvol, Nex);
174 
175  vout.paranoiac(m_vl, " Solver_BiCGStab_Cmplx: field size reset.\n");
176  }
177 }
178 
179 
180 //====================================================================
181 void Solver_BiCGStab_Cmplx::solve_init(const Field& b, double& rr)
182 {
183  v = m_fopr->mult(s);
184  r = b;
185  x = s;
186  r -= v;
187  rh = r;
188  rr = r * r;
189 
190  rho_p = cmplx(1.0, 0.0);
191  alpha_p = cmplx(1.0, 0.0);
192  omega_p = cmplx(1.0, 0.0);
193 
194  p = 0.0;
195  v = 0.0;
196 
197  w = 0.0;
198 }
199 
200 
201 //====================================================================
203 {
204  // dcomplex rho = rh * r;
205  double const_r, const_i;
206 
207  innerprod_c(const_r, const_i, rh, r);
208  dcomplex rho = cmplx(const_r, const_i);
209 
210  dcomplex bet = rho * alpha_p / (rho_p * omega_p);
211 
212  // p = r + bet * (p - omega_p * v);
213  mult_c(w, v, real(omega_p), imag(omega_p));
214  v = p - w;
215  mult_c(w, v, real(bet), imag(bet));
216  p = r + w;
217 
218  v = m_fopr->mult(p);
219 
220  // dcomplex aden = rh * v;
221  innerprod_c(const_r, const_i, rh, v);
222  dcomplex aden = cmplx(const_r, const_i);
223 
224  dcomplex alpha = rho / aden;
225 
226  // s = r - ( alpha * v);
227  mult_c(w, v, real(alpha), imag(alpha));
228  s = r - w;
229 
230  Field t(s);
231  t = m_fopr->mult(s);
232 
233  double omega_d = t * t;
234 
235  // dcomplex omega_n = t * s;
236  innerprod_c(const_r, const_i, t, s);
237  dcomplex omega_n = cmplx(const_r, const_i);
238 
239  dcomplex omega = omega_n / omega_d;
240 
241  // x += omega * s + alpha * p;
242  mult_c(w, s, real(omega), imag(omega));
243  x += w;
244  mult_c(w, p, real(alpha), imag(alpha));
245  x += w;
246 
247  // r = s - omega * t;
248  mult_c(w, t, real(omega), imag(omega));
249  r = s - w;
250 
251  rho_p = rho;
252  alpha_p = alpha;
253  omega_p = omega;
254 
255  rr = r * r;
256 }
257 
258 
259 //====================================================================
260 void Solver_BiCGStab_Cmplx::innerprod_c(double& prod_r, double& prod_i,
261  const Field& v, const Field& w)
262 {
263  // prod = (v,w);
264 
265  int size = w.size();
266 
267  assert(v.size() == size);
268 
269  prod_r = 0.0;
270  prod_i = 0.0;
271 
272  for (int i = 0; i < size; i += 2) {
273  prod_r += v.cmp(i) * w.cmp(i) + v.cmp(i + 1) * w.cmp(i + 1);
274  prod_i += v.cmp(i) * w.cmp(i + 1) - v.cmp(i + 1) * w.cmp(i);
275  }
276 
277  prod_r = Communicator::reduce_sum(prod_r);
278  prod_i = Communicator::reduce_sum(prod_i);
279 }
280 
281 
282 //====================================================================
284  const Field& w,
285  const double& prod_r, const double& prod_i)
286 {
287  // v = dcomplex(prod_r,prod_i) * w;
288 
289  int size = w.size();
290 
291  assert(v.size() == size);
292 
293  double v_r, v_i;
294  for (int i = 0; i < size; i += 2) {
295  v_r = prod_r * w.cmp(i) - prod_i * w.cmp(i + 1);
296  v_i = prod_r * w.cmp(i + 1) + prod_i * w.cmp(i);
297 
298  v.set(i, v_r);
299  v.set(i + 1, v_i);
300  }
301 }
302 
303 
304 //====================================================================
305 //============================================================END=====