Bridge++  Ver. 2.0.2
shiftsolver_CG.cpp
Go to the documentation of this file.
1 
14 #include "Solver/ashiftsolver_CG.h"
16 #include "Solver/shiftsolver_CG.h"
17 
18 template<>
20  = "Shiftsolver_CG";
21 
22 template class AShiftsolver_CG<Field, Fopr>;
23 
24 /*
25 //====================================================================
26 void Shiftsolver_CG::set_parameters(const Parameters& params)
27 {
28  std::string vlevel;
29  if (!params.fetch_string("verbose_level", vlevel)) {
30  m_vl = vout.set_verbose_level(vlevel);
31  }
32 
33  //- fetch and check input parameters
34  int Niter;
35  double Stop_cond;
36 
37  int err = 0;
38  err += params.fetch_int("maximum_number_of_iteration", Niter);
39  err += params.fetch_double("convergence_criterion_squared", Stop_cond);
40 
41  if (err) {
42  vout.crucial(m_vl, "Error at %s: input parameter not found.\n", class_name.c_str());
43  exit(EXIT_FAILURE);
44  }
45 
46  set_parameters(Niter, Stop_cond);
47 }
48 
49 
50 //====================================================================
51 void Shiftsolver_CG::set_parameters(const int Niter, const double Stop_cond)
52 {
53  //- print input parameters
54  vout.general(m_vl, "%s:\n", class_name.c_str());
55  vout.general(m_vl, " Niter = %d\n", Niter);
56  vout.general(m_vl, " Stop_cond = %8.2e\n", Stop_cond);
57 
58  //- range check
59  int err = 0;
60  err += ParameterCheck::non_negative(Niter);
61  err += ParameterCheck::square_non_zero(Stop_cond);
62 
63  if (err) {
64  vout.crucial(m_vl, "Error at %s: parameter range check failed.\n", class_name.c_str());
65  exit(EXIT_FAILURE);
66  }
67 
68  //- store values
69  m_Niter = Niter;
70  m_Stop_cond = Stop_cond;
71 }
72 
73 
74 //====================================================================
75 void Shiftsolver_CG::solve(std::vector<Field>& xq,
76  const std::vector<double>& sigma,
77  const Field& b,
78  int& Nconv, double& diff)
79 {
80  int Nshift = sigma.size();
81 
82  vout.paranoiac(m_vl, " Shift CG solver start.\n");
83  vout.paranoiac(m_vl, " number of shift = %d\n", Nshift);
84  vout.paranoiac(m_vl, " values of shift:\n");
85  for (int i = 0; i < Nshift; ++i) {
86  vout.paranoiac(m_vl, " %d %12.8f\n", i, sigma[i]);
87  }
88 
89  m_snorm = 1.0 / b.norm2();
90 
91  int Nconv2 = -1;
92 
93  reset_field(b, sigma, Nshift);
94 
95  copy(m_s, b);
96  copy(m_r, b);
97 
98  double rr = 0.0;
99 
100  solve_init(rr);
101 
102  vout.detailed(m_vl, " iter: %8d %22.15e\n", 0, rr * m_snorm);
103 
104  bool is_converged = false;
105 
106  for (int iter = 0; iter < m_Niter; iter++) {
107  solve_step(rr);
108 
109  Nconv2 += 1;
110 
111  vout.detailed(m_vl, " iter: %8d %22.15e %4d\n", (iter + 1), rr * m_snorm, m_Nshift2);
112 
113  if (rr * m_snorm < m_Stop_cond) {
114  is_converged = true;
115  break;
116  }
117  }
118 
119  if (!is_converged) {
120  vout.crucial(m_vl, "Error at %s: not converged.\n", class_name.c_str());
121  exit(EXIT_FAILURE);
122  }
123 
124 
125  std::vector<double> diffs(Nshift);
126  for (int i = 0; i < Nshift; ++i) {
127  diffs[i] = 0.0;
128  }
129 
130  for (int i = 0; i < Nshift; ++i) {
131  m_fopr->mult(m_s, m_x[i]);
132  axpy(m_s, sigma[i], m_x[i]);
133  axpy(m_s, -1.0, b);
134 
135  double diff1 = sqrt(m_s.norm2() * m_snorm);
136 
137  vout.paranoiac(m_vl, " %4d %22.15e\n", i, diff1);
138 
139  // if (diff1 > diff2) diff2 = diff1;
140  diffs[i] = diff1;
141  }
142 
143 #pragma omp barrier
144 #pragma omp master
145  {
146  double diff2 = -1.0;
147 
148  for (int i = 0; i < Nshift; ++i) {
149  if (diffs[i] > diff2) diff2 = diffs[i];
150  }
151 
152  diff = diff2;
153 
154  Nconv = Nconv2;
155  }
156 #pragma omp barrier
157 
158  for (int i = 0; i < Nshift; ++i) {
159  copy(xq[i], m_x[i]);
160  }
161 
162  vout.paranoiac(m_vl, " diff(max) = %22.15e \n", diff);
163 }
164 
165 
166 //====================================================================
167 void Shiftsolver_CG::solve_init(double& rr)
168 {
169  int Nshift = m_p.size();
170 
171  vout.paranoiac(m_vl, "number of shift = %d\n", Nshift);
172 
173  for (int i = 0; i < Nshift; ++i) {
174  copy(m_p[i], m_s);
175  scal(m_x[i], 0.0);
176  }
177 
178  copy(m_r, m_s);
179  rr = m_r.norm2();
180 
181 #pragma omp barrier
182 #pragma omp master
183  {
184  m_alpha_p = 0.0;
185  m_beta_p = 1.0;
186  }
187 #pragma omp barrier
188 }
189 
190 
191 //====================================================================
192 void Shiftsolver_CG::solve_step(double& rr)
193 {
194  m_fopr->mult(m_s, m_p[0]);
195  axpy(m_s, m_sigma0, m_p[0]);
196 
197  double rr_p = rr;
198  double pa_p = dot(m_s, m_p[0]);
199  double beta = -rr_p / pa_p;
200 
201  axpy(m_x[0], -beta, m_p[0]);
202  axpy(m_r, beta, m_s);
203  rr = m_r.norm2();
204 
205  double alpha = rr / rr_p;
206 
207  aypx(alpha, m_p[0], m_r);
208 
209 #pragma omp barrier
210 #pragma omp master
211  {
212  m_pp[0] = rr;
213  }
214 #pragma omp barrier
215 
216  double alpha_h = 1.0 + m_alpha_p * beta / m_beta_p;
217 
218  for (int ish = 1; ish < m_Nshift2; ++ish) {
219  double zeta = (alpha_h - m_csh2[ish] * beta) / m_zeta1[ish]
220  + (1.0 - alpha_h) / m_zeta2[ish];
221  zeta = 1.0 / zeta;
222  double zr = zeta / m_zeta1[ish];
223  double beta_s = beta * zr;
224  double alpha_s = alpha * zr * zr;
225 
226  axpy(m_x[ish], -beta_s, m_p[ish]);
227  scal(m_p[ish], alpha_s);
228  axpy(m_p[ish], zeta, m_r);
229 
230  double ppr = m_p[ish].norm2();
231 
232 #pragma omp barrier
233 #pragma omp master
234  {
235  m_pp[ish] = ppr * m_snorm;
236 
237  m_zeta2[ish] = m_zeta1[ish];
238  m_zeta1[ish] = zeta;
239  }
240 #pragma omp barrier
241  }
242 
243  int ish1 = m_Nshift2;
244 
245  for (int ish = m_Nshift2 - 1; ish >= 0; --ish) {
246  vout.paranoiac(m_vl, "%4d %16.8e\n", ish, m_pp[ish]);
247  if (m_pp[ish] > m_Stop_cond) {
248  ish1 = ish + 1;
249  break;
250  }
251  }
252 
253 #pragma omp barrier
254 #pragma omp master
255  {
256  m_Nshift2 = ish1;
257 
258  m_alpha_p = alpha;
259  m_beta_p = beta;
260  }
261 #pragma omp barrier
262 }
263 
264 
265 //====================================================================
266 void Shiftsolver_CG::reset_field(const FIELD& b,
267  const std::vector<double>& sigma,
268  const int Nshift)
269 {
270 #pragma omp barrier
271 #pragma omp master
272  {
273  int Nin = b.nin();
274  int Nvol = b.nvol();
275  int Nex = b.nex();
276 
277  m_p.resize(Nshift);
278  m_x.resize(Nshift);
279  m_zeta1.resize(Nshift);
280  m_zeta2.resize(Nshift);
281  m_csh2.resize(Nshift);
282  m_pp.resize(Nshift);
283 
284  for (int i = 0; i < Nshift; ++i) {
285  m_p[i].reset(Nin, Nvol, Nex);
286  m_x[i].reset(Nin, Nvol, Nex);
287  m_zeta1[i] = 1.0;
288  m_zeta2[i] = 1.0;
289  m_csh2[i] = sigma[i] - sigma[0];
290 
291  m_pp[i] = 0.0;
292  }
293 
294  m_s.reset(Nin, Nvol, Nex);
295  m_r.reset(Nin, Nvol, Nex);
296 
297  m_sigma0 = sigma[0];
298 
299  m_Nshift2 = Nshift;
300  }
301 #pragma omp barrier
302 }
303 */
304 
305 //====================================================================
306 //============================================================END=====
shiftsolver_CG.h
ashiftsolver_CG.h
ashiftsolver_CG-tmpl.h
AShiftsolver_CG
Multishift Conjugate Gradient solver.
Definition: ashiftsolver_CG.h:32