10 template<
typename AFIELD>
12 =
"ASolver_BiCGStab_Cmplx";
15 #ifndef AFIELD_HAS_SUB
16 template<
typename AFIELD>
23 #ifndef AFIELD_HAS_DOTC_AND_NORM2
24 template<
typename AFIELD>
38 template<
typename AFIELD>
43 vout.
detailed(m_vl,
"%s: being setup.\n", class_name.c_str());
45 int nin = m_fopr->field_nin();
46 int nvol = m_fopr->field_nvol();
47 int nex = m_fopr->field_nex();
49 m_r.reset(nin, nvol, nex);
50 m_p.reset(nin, nvol, nex);
51 m_v.reset(nin, nvol, nex);
52 m_t.reset(nin, nvol, nex);
53 m_rh.reset(nin, nvol, nex);
57 m_Omega_tolerance = 0.7;
59 vout.
detailed(m_vl,
"%s: setup finished.\n", class_name.c_str());
64 template<
typename AFIELD>
73 template<
typename AFIELD>
76 const string str_vlevel = params.
get_string(
"verbose_level");
83 double Omega_tolerance;
86 err += params.
fetch_int(
"maximum_number_of_iteration", Niter);
87 err += params.
fetch_int(
"maximum_number_of_restart", Nrestart);
88 err += params.
fetch_double(
"convergence_criterion_squared", Stop_cond);
91 vout.
crucial(m_vl,
"Error at %s: input parameter not found.\n",
95 err = params.
fetch_double(
"Omega_tolerance", Omega_tolerance);
97 Omega_tolerance = 0.7;
99 std::string initial_guess_str;
100 err = params.
fetch_string(
"initial_guess_mode", initial_guess_str);
101 initial_guess = InitialGuess::RHS;
104 class_name.c_str(), initial_guess_str.c_str());
106 if (initial_guess_str ==
"ZERO") {
107 initial_guess = InitialGuess::ZERO;
108 }
else if (initial_guess_str ==
"GIVEN") {
109 initial_guess = InitialGuess::GIVEN;
111 vout.
crucial(m_vl,
"%s: unknown initial guess mode string: %d\n",
112 class_name.c_str(), initial_guess_str.c_str());
118 int Niter2 = Niter * Nrestart;
123 set_parameters(Niter2, Stop_cond, initial_guess);
124 set_parameters_BiCGStab_series(Omega_tolerance);
129 template<
typename AFIELD>
133 set_parameters(Niter, Stop_cond, InitialGuess::RHS);
138 template<
typename AFIELD>
141 const InitialGuess init_guess_mode)
146 m_Stop_cond = Stop_cond;
147 std::string prec =
"double";
148 if (
sizeof(
real_t) == 4) prec =
"float";
149 m_initial_mode = init_guess_mode;
152 vout.
general(m_vl,
" Precision: %s\n", prec.c_str());
154 vout.
general(m_vl,
" Stop_cond = %16.8e\n", m_Stop_cond);
155 vout.
general(m_vl,
" init_guess_mode: %d\n", m_initial_mode);
160 template<
typename AFIELD>
166 vout.
general(m_vl,
" Omega_tolerance = %8.2e\n", Omega_tolerance);
172 m_Omega_tolerance = Omega_tolerance;
177 template<
typename AFIELD>
181 vout.
paranoiac(m_vl,
"%s: solver start:\n", class_name.c_str());
190 real_t snorm = sqrt(snorm2);
193 scal(m_t, snorm_inv);
205 solve_init(m_t, rr, coeff, snorm_inv, m_initial_mode);
208 for (
int iter = 0; iter < m_Niter; ++iter) {
210 solve_step(rr, iflg, coeff);
214 scal(m_t, snorm_inv);
215 solve_init_GIVEN(m_t, rr, coeff,
real_t(1.0));
216 vout.
detailed(m_vl,
"%s: restarted.\n", class_name.c_str());
220 if (rr < m_Stop_cond) {
221 nconv = 2 * (iter + 1);
226 if ((m_Stop_cond < 0) || (Nconv < 0)) {
227 vout.
detailed(m_vl,
" truncating with iter= %d\n", 2 * m_Niter);
233 m_Niter, rr * snorm2);
243 m_fopr->mult(m_t, xq);
251 Nconv = nconv + m_init_mult;
252 diff = sqrt(diff2 / snorm2);
259 template<
typename AFIELD>
266 if (init_mode == InitialGuess::RHS) {
267 solve_init_RHS(b, rr, prev);
268 }
else if (init_mode == InitialGuess::GIVEN) {
269 solve_init_GIVEN(b, rr, prev, scale);
270 }
else if (init_mode == InitialGuess::ZERO) {
271 solve_init_ZERO(b, rr, prev);
273 vout.
crucial(
"%s: unkown init guess mode\n", class_name.c_str());
280 template<
typename AFIELD>
291 vout.
detailed(m_vl,
" |m_x|^2 = %23.16e [init_RHS]\n", temp);
294 m_fopr->mult(m_v, m_x);
299 vout.
detailed(m_vl,
" |m_v|^2 = %23.16e [init_RHS]\n", temp);
311 vout.
detailed(m_vl,
"ASolver_BiCGStab_Cmplx rr = %23.16e [init_RHS]\n", rr);
322 template<
typename AFIELD>
329 if (scale !=
real_t(1.0)) {
333 m_fopr->mult(m_v, m_x);
349 vout.
detailed(m_vl,
"ASolver_BiCGStab_Cmplx rr = %23.16e [init_GIVEN]\n", rr);
354 template<
typename AFIELD>
371 vout.
detailed(m_vl,
"ASolver_BiCGStab_Cmplx rr = %23.16e [init_ZERO]\n", rr);
376 template<
typename AFIELD>
380 const real_t Omega_tolerance = m_Omega_tolerance;
384 #ifdef DEBUG_BICGSTAB_CMPLX
385 vout.
detailed(m_vl,
"ASolver_BiCGStab_Cmplx rho = %23.16e %23.16e\n", real(rho), imag(rho));
387 if (abs(rho) < m_ecrit) {
389 vout.
detailed(m_vl,
"too small value of rho = %23.16e %23.16e\n", real(rho), imag(rho));
391 double r2 =
norm2(m_r);
392 double rh2 =
norm2(m_rh);
404 m_fopr->mult(m_v, m_p);
407 #ifdef DEBUG_BICGSTAB_CMPLX
408 vout.
detailed(m_vl,
"ASolver_BiCGStab_Cmplx bet = %23.16e %23.16e\n", real(bet), imag(bet));
409 vout.
detailed(m_vl,
"ASolver_BiCGStab_Cmplx aden = %23.16e %23.16e\n", real(aden), imag(aden));
411 if (abs(aden) < m_ecrit) {
413 vout.
detailed(m_vl,
"too small denominator aden = %23.16e %23.16e\n", real(aden), imag(aden));
417 #ifdef DEBUG_BICGSTAB_CMPLX
418 vout.
detailed(m_vl,
"ASolver_BiCGStab_Cmplx alpha = %23.16e %23.16e\n", real(alpha), imag(alpha));
422 axpy(m_r, -alpha, m_v);
423 m_fopr->mult(m_t, m_r);
435 const double abs_rho = abs(omega_n) / sqrt(omega_d * s_norm2);
437 #ifdef DEBUG_BICGSTAB_CMPLX
438 vout.
detailed(m_vl,
"ASolver_BiCGStab_Cmplx omega_n = %23.16e %23.16e\n", real(omega_n), imag(omega_n));
439 vout.
detailed(m_vl,
"ASolver_BiCGStab_Cmplx omega_d = %23.16e\n", omega_d);
440 vout.
detailed(m_vl,
"ASolver_BiCGStab_Cmplx omega = %23.16e %23.16e\n", real(omega), imag(omega));
441 vout.
detailed(m_vl,
"ASolver_BiCGStab_Cmplx s_norm2 = %23.16e\n", s_norm2);
442 vout.
detailed(m_vl,
"ASolver_BiCGStab_Cmplx abs_rho = %23.16e\n", abs_rho);
447 if (abs_rho < Omega_tolerance) {
448 vout.
detailed(m_vl,
"ASolver_BiCGStab_Cmplx abs_rho = %23.16e, omega = %23.16e %23.16e [Omega presciption applied]\n", abs_rho, real(omega), imag(omega));
449 omega *= Omega_tolerance / abs_rho;
453 axpy(m_x, omega, m_r);
454 axpy(m_x, alpha, m_p);
457 axpy(m_r, -omega, m_t);
467 template<
typename AFIELD>
470 int Nin = m_fopr->field_nin();
471 int Nvol = m_fopr->field_nvol();
472 int Nex = m_fopr->field_nex();
478 double flop_field =
static_cast<double>(Nin * Nvol * Nex) * NPE;
479 double flop_vector = (6 + 4 * ninit + iter * 20) * flop_field;
481 double flop_fopr = (1 + ninit + iter) * m_fopr->flop_count();
483 if (m_initial_mode == InitialGuess::ZERO) {
484 flop_vector -= (2 * ninit) * flop_field;
485 flop_fopr -= m_fopr->flop_count();
488 double flop = flop_vector + flop_fopr;