ug4
cg.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2010-2015: G-CSC, Goethe University Frankfurt
3  * Author: Andreas Vogel
4  *
5  * This file is part of UG4.
6  *
7  * UG4 is free software: you can redistribute it and/or modify it under the
8  * terms of the GNU Lesser General Public License version 3 (as published by the
9  * Free Software Foundation) with the following additional attribution
10  * requirements (according to LGPL/GPL v3 §7):
11  *
12  * (1) The following notice must be displayed in the Appropriate Legal Notices
13  * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
14  *
15  * (2) The following notice must be displayed at a prominent place in the
16  * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
17  *
18  * (3) The following bibliography is recommended for citation and must be
19  * preserved in all covered files:
20  * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
21  * parallel geometric multigrid solver on hierarchically distributed grids.
22  * Computing and visualization in science 16, 4 (2013), 151-164"
23  * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
24  * flexible software system for simulating pde based models on high performance
25  * computers. Computing and visualization in science 16, 4 (2013), 165-179"
26  *
27  * This program is distributed in the hope that it will be useful,
28  * but WITHOUT ANY WARRANTY; without even the implied warranty of
29  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30  * GNU Lesser General Public License for more details.
31  */
32 
33 #ifndef __H__UG__LIB_DISC__OPERATOR__LINEAR_SOLVER__CG__
34 #define __H__UG__LIB_DISC__OPERATOR__LINEAR_SOLVER__CG__
35 
36 #include <iostream>
37 #include <string>
38 
43 #ifdef UG_PARALLEL
45 #endif
46 
47 namespace ug{
48 
50 
64 template <typename TVector>
65 class CG
66  : public IPreconditionedLinearOperatorInverse<TVector>
67 {
68  public:
70  typedef TVector vector_type;
71 
74 
75  protected:
80 
81  public:
83  CG() : base_type() {}
84 
86  : base_type ( spPrecond ) {}
87 
89  : base_type ( spPrecond, spConvCheck) {}
90 
92  virtual const char* name() const {return "CG";}
93 
95  virtual bool supports_parallel() const
96  {
97  if(preconditioner().valid())
98  return preconditioner()->supports_parallel();
99  return true;
100  }
101 
104  {
105  PROFILE_BEGIN_GROUP(CG_apply_return_defect, "CG algebra");
106  // check parallel storage types
107  #ifdef UG_PARALLEL
108  if(!b.has_storage_type(PST_ADDITIVE) || !x.has_storage_type(PST_CONSISTENT))
109  UG_THROW("CG::apply_return_defect:"
110  "Inadequate storage format of Vectors.");
111  #endif
112 
113  // rename r as b (for convenience)
114  vector_type& r = b;
115 
116  // Build defect: r := b - J(u)*x
117  linear_operator()->apply_sub(r, x);
118 
119  // create help vector (h will be consistent r)
120  SmartPtr<vector_type> spQ = r.clone_without_values(); vector_type& q = *spQ;
121  SmartPtr<vector_type> spZ = x.clone_without_values(); vector_type& z = *spZ;
122  SmartPtr<vector_type> spP = x.clone_without_values(); vector_type& p = *spP;
123 
125 
126  // Preconditioning
127  if(preconditioner().valid())
128  {
130  // apply z = M^-1 * s
131  if(!preconditioner()->apply(z, r))
132  {
133  UG_LOG("ERROR in 'CG::apply_return_defect': "
134  "Cannot apply preconditioner. Aborting.\n");
136  return false;
137  }
139  }
140  else z = r;
141 
142  // make z consistent
143  #ifdef UG_PARALLEL
144  if(!z.change_storage_type(PST_CONSISTENT))
145  UG_THROW("CG::apply_return_defect: "
146  "Cannot convert z to consistent vector.");
147  #endif
148 
149  // post-process the correction
151 
152  // compute start defect
154  convergence_check()->start(r);
155 
156  // start search direction
157  p = z;
158 
159  // start rho
160  number rhoOld = VecProd(z, r), rho;
161 
162  // Iteration loop
163  while(!convergence_check()->iteration_ended())
164  {
165  // Build q = A*p (q is additive afterwards)
166  linear_operator()->apply(q, p);
167 
168  // lambda = (q,p)
169  number lambda = VecProd(q, p);
170 
171  // check lambda
172  if(lambda == 0.0)
173  {
174  if (p.size())
175  {
176  UG_LOG("ERROR in 'CG::apply_return_defect': lambda=" <<
177  lambda<< " is not admitted. Aborting solver.\n");
178  return false;
179  }
180  // in cases where a proc has no geometry, we do not want to fail here
181  // so we set lambda = 1, this is not harmful
182  else
183  lambda = 1.0;
184  }
185 
186  // alpha = rho / (q,p)
187  const number alpha = rhoOld/lambda;
188 
189  // Update x := x + alpha*p
190  VecScaleAdd(x, 1.0, x, alpha, p);
191 
192  // Update r := r - alpha*t
193  VecScaleAdd(r, 1.0, r, -alpha, q);
194 
196 
197  // Check convergence
198  convergence_check()->update(r);
199  if(convergence_check()->iteration_ended()) break;
200 
201  // Preconditioning
202  if(preconditioner().valid())
203  {
205  // apply z = M^-1 * r
206  if(!preconditioner()->apply(z, r))
207  {
208  UG_LOG("ERROR in 'CG::apply_return_defect': "
209  "Cannot apply preconditioner. Aborting.\n");
211  return false;
212  }
214  }
215  else z = r;
216 
217  #ifdef UG_PARALLEL
218  // make z consistent
219  if(!z.change_storage_type(PST_CONSISTENT))
220  UG_THROW("CG::apply_return_defect': "
221  "Cannot convert z to consistent vector.");
222  #endif
223 
224  // post-process the correction
226 
227  // new rho = (z,r)
228  rho = VecProd(z, r);
229 
230  // new beta = rho / rhoOld
231  const number beta = rho/rhoOld;
232 
233  // new direction p := beta * p + z
234  VecScaleAdd(p, beta, p, 1.0, z);
235 
236  // remember old rho
237  rhoOld = rho;
238  }
239 
240  // post output
241  return convergence_check()->post();
242  }
243 
246  {
248  }
249 
252  {
254  }
255 
256  protected:
259  {
260  // set iteration symbol and name
261  convergence_check()->set_name(name());
262  convergence_check()->set_symbol('%');
263 
264  // set preconditioner string
265  std::string s;
266  if(preconditioner().valid())
267  s = std::string(" (Precond: ") + preconditioner()->name() + ")";
268  else
269  s = " (No Preconditioner) ";
270  convergence_check()->set_info(s);
271  }
272 
274  void write_debugXR(vector_type &x, vector_type &r, int loopCnt)
275  {
276  if(!this->vector_debug_writer_valid()) return;
277  char ext[20]; sprintf(ext, "_iter%03d", loopCnt);
278  write_debug(r, std::string("CG_Residual") + ext + ".vec");
279  write_debug(x, std::string("CG_Solution") + ext + ".vec");
280  }
281 
283  void enter_precond_debug_section(int loopCnt)
284  {
285  if(!this->vector_debug_writer_valid()) return;
286  char ext[20]; sprintf(ext, "_iter%03d", loopCnt);
287  this->enter_vector_debug_writer_section(std::string("CG_Precond_") + ext);
288  }
289 
290  protected:
292  {
293  return a.dotprod(b);
294  }
295 
296  protected:
298 
304 };
305 
306 } // end namespace ug
307 
308 #endif /* __H__UG__LIB_DISC__OPERATOR__LINEAR_SOLVER__CG__ */
parameterString p
parameterString s
Definition: smart_pointer.h:108
the CG method as a solver for linear operators
Definition: cg.h:67
virtual const char * name() const
name of solver
Definition: cg.h:92
CG(SmartPtr< ILinearIterator< vector_type, vector_type > > spPrecond)
Definition: cg.h:85
void write_debugXR(vector_type &x, vector_type &r, int loopCnt)
debugger output: solution and residual
Definition: cg.h:274
void enter_precond_debug_section(int loopCnt)
debugger section for the preconditioner
Definition: cg.h:283
IPreconditionedLinearOperatorInverse< vector_type > base_type
Base type.
Definition: cg.h:73
void remove_postprocess_corr(SmartPtr< IPProcessVector< vector_type > > p)
removes a post-process for the iterates
Definition: cg.h:251
TVector vector_type
Vector type.
Definition: cg.h:70
CG(SmartPtr< ILinearIterator< vector_type, vector_type > > spPrecond, SmartPtr< IConvergenceCheck< vector_type > > spConvCheck)
Definition: cg.h:88
virtual bool apply_return_defect(vector_type &x, vector_type &b)
Solve J(u)*x = b, such that x = J(u)^{-1} b.
Definition: cg.h:103
void add_postprocess_corr(SmartPtr< IPProcessVector< vector_type > > p)
adds a post-process for the iterates
Definition: cg.h:245
PProcessChain< vector_type > m_corr_post_process
postprocessor for the correction in the iterations
Definition: cg.h:303
SmartPtr< ILinearIterator< X, X > > preconditioner()
Definition: preconditioned_linear_operator_inverse.h:118
void prepare_conv_check()
adjust output of convergence check
Definition: cg.h:258
virtual bool supports_parallel() const
returns if parallel solving is supported
Definition: cg.h:95
CG()
constructors
Definition: cg.h:83
number VecProd(vector_type &a, vector_type &b)
Definition: cg.h:291
Definition: convergence_check.h:72
describes a linear iterator
Definition: linear_iterator.h:81
ConstSmartPtr< IConvergenceCheck< X > > convergence_check() const
returns the convergence check
Definition: linear_operator_inverse.h:202
SmartPtr< ILinearOperator< Y, X > > linear_operator()
returns the current Operator this Inverse Operator is initialized for
Definition: linear_operator_inverse.h:227
int step() const
returns the current number of steps
Definition: linear_operator_inverse.h:211
interface for pre- and postprocess functions
Definition: pprocess.h:59
describes an inverse linear mapping X->X
Definition: preconditioned_linear_operator_inverse.h:63
virtual bool apply(TVector &x, const TVector &b)
Definition: preconditioned_linear_operator_inverse.h:152
SmartPtr< ILinearIterator< X, X > > preconditioner()
Definition: preconditioned_linear_operator_inverse.h:118
void add(SmartPtr< p_process_type > p)
adds an operation at the end of the chain
Definition: pprocess.h:96
void apply(vector_type &v)
performs all the operations
Definition: pprocess.h:86
void remove(SmartPtr< p_process_type > p)
removes an operation from the chain
Definition: pprocess.h:108
bool vector_debug_writer_valid() const
returns true if the debug writer is set
Definition: debug_writer.h:290
void enter_vector_debug_writer_section(std::string secDir)
enters a debugging section
Definition: debug_writer.h:331
void leave_vector_debug_writer_section()
leaves a debugging section
Definition: debug_writer.h:342
void write_debug(const vector_type &vec, const char *filename)
writing debug output for a vector (if debug writer set)
Definition: debug_writer.h:293
TVector vector_type
type of vector
Definition: debug_writer.h:269
@ PST_CONSISTENT
Definition: parallel_storage_type.h:68
@ PST_ADDITIVE
Definition: parallel_storage_type.h:69
function common sprintf(s,...)
number alpha
#define UG_THROW(msg)
Definition: error.h:57
#define UG_LOG(msg)
Definition: log.h:367
double number
Definition: types.h:124
void VecScaleAdd(vector_t &vOut, typename vector_t::value_type s1, const vector_t &v1, typename vector_t::value_type s2, const vector_t &v2)
Scales two Vectors, adds them and returns the sum in a third vector.
Definition: math_vector_functions_common_impl.hpp:265
the ug namespace
#define PROFILE_BEGIN_GROUP(name, groups)
Definition: profiler.h:255