Bridge++  Ver. 1.1.x
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
solver_CG.cpp
Go to the documentation of this file.
1 
14 #include "solver_CG.h"
15 
16 #ifdef USE_PARAMETERS_FACTORY
17 #include "parameters_factory.h"
18 #endif
19 
20 #ifdef USE_FACTORY
21 namespace {
22  Solver *create_object(Fopr *fopr)
23  {
24  return new Solver_CG(fopr);
25  }
26 
27 
28  bool init = Solver::Factory::Register("CG", create_object);
29 }
30 #endif
31 
32 //- parameter entries
33 namespace {
34  void append_entry(Parameters& param)
35  {
36  param.Register_int("maximum_number_of_iteration", 0);
37  param.Register_double("convergence_criterion_squared", 0.0);
38 
39  param.Register_string("verbose_level", "NULL");
40  }
41 
42 
43 #ifdef USE_PARAMETERS_FACTORY
44  bool init_param = ParametersFactory::Register("Solver.CG", append_entry);
45 #endif
46 }
47 //- end
48 
49 //- parameters class
51 //- end
52 
53 //====================================================================
55 {
56  const string str_vlevel = params.get_string("verbose_level");
57 
58  m_vl = vout.set_verbose_level(str_vlevel);
59 
60  //- fetch and check input parameters
61  int Niter;
62  double Stop_cond;
63 
64  int err = 0;
65  err += params.fetch_int("maximum_number_of_iteration", Niter);
66  err += params.fetch_double("convergence_criterion_squared", Stop_cond);
67 
68  if (err) {
69  vout.crucial(m_vl, "Solver_CG: fetch error, input parameter not found.\n");
70  abort();
71  }
72 
73 
74  set_parameters(Niter, Stop_cond);
75 }
76 
77 
78 //====================================================================
79 void Solver_CG::set_parameters(const int Niter, const double Stop_cond)
80 {
81  //- print input parameters
82  vout.general(m_vl, "Parameters of Solver_CG:\n");
83  vout.general(m_vl, " Niter = %d\n", Niter);
84  vout.general(m_vl, " Stop_cond = %16.8e\n", Stop_cond);
85 
86  //- range check
87  int err = 0;
88  err += ParameterCheck::non_negative(Niter);
89  err += ParameterCheck::square_non_zero(Stop_cond);
90 
91  if (err) {
92  vout.crucial(m_vl, "Solver_CG: parameter range check failed.\n");
93  abort();
94  }
95 
96  //- store values
97  m_Niter = Niter;
98  m_Stop_cond = Stop_cond;
99 }
100 
101 
102 //====================================================================
103 void Solver_CG::solve(Field& xq, const Field& b,
104  int& Nconv, double& diff)
105 {
106  vout.detailed(m_vl, " CG solver starts\n");
107 
108  reset_field(b);
109 
110  vout.paranoiac(m_vl, " norm of b = %16.8e\n", b.norm2());
111  vout.paranoiac(m_vl, " size of b = %d\n", b.size());
112 
113  double snorm = 1.0 / b.norm2();
114  double rr;
115 
116  Nconv = -1;
117  s = b;
118 
119  solve_init(b, rr);
120 
121  vout.detailed(m_vl, " iter: %8d %22.15e\n", 0, rr * snorm);
122 
123  for (int iter = 0; iter < m_Niter; iter++) {
124  solve_step(rr);
125 
126  vout.detailed(m_vl, " iter: %8d %22.15e\n", (iter + 1), rr * snorm);
127 
128  if (rr * snorm < m_Stop_cond) {
129  // s = m_fopr->mult(x);
130  m_fopr->mult(s, x);
131  s -= b;
132  diff = s.norm();
133 
134  if (diff * diff * snorm < m_Stop_cond) {
135  Nconv = iter + 1;
136  break;
137  }
138 
139  s = x;
140  solve_init(b, rr);
141  }
142  }
143  if (Nconv == -1) {
144  vout.crucial(m_vl, "CG solver not converged.\n");
145  abort();
146  }
147 
148  // p = m_fopr->mult(x);
149  m_fopr->mult(p, x);
150  p -= b;
151  diff = p.norm();
152 
153  xq = x;
154 }
155 
156 
157 //====================================================================
158 void Solver_CG::reset_field(const Field& b)
159 {
160  int Nin = b.nin();
161  int Nvol = b.nvol();
162  int Nex = b.nex();
163 
164  if ((s.nin() != Nin) || (s.nvol() != Nvol) || (s.nex() != Nex)) {
165  s.reset(Nin, Nvol, Nex);
166  r.reset(Nin, Nvol, Nex);
167  x.reset(Nin, Nvol, Nex);
168  p.reset(Nin, Nvol, Nex);
169  v.reset(Nin, Nvol, Nex);
170 
171  vout.paranoiac(m_vl, " Solver_CG: field size reset.\n");
172  }
173 }
174 
175 
176 //====================================================================
177 void Solver_CG::solve_init(const Field& b, double& rr)
178 {
179  r = b;
180  x = s;
181 
182  // s = m_fopr->mult(x);
183  m_fopr->mult(s, x);
184 
185  r -= s;
186  p = r;
187  rr = r * r;
188 }
189 
190 
191 //====================================================================
192 void Solver_CG::solve_step(double& rr)
193 {
194  // s = m_fopr->mult(p);
195  m_fopr->mult(s, p);
196 
197  double pap = p * s;
198  double rr_p = rr;
199  double cr = rr_p / pap;
200 
201  v = p;
202  v *= cr;
203  x += v;
204  // x += cr*p;
205 
206  s *= cr;
207  r -= s;
208 
209  rr = r * r;
210  p *= rr / rr_p;
211  p += r;
212 }
213 
214 
215 //====================================================================
216 //============================================================END=====