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