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