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