Loading [MathJax]/extensions/tex2jax.js
ug4
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
gmres.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2013-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_OPERATOR__GMRES__
34#define __H__UG__LIB_DISC__OPERATOR__LINEAR_OPERATOR__GMRES__
35
36#include <iostream>
37#include <string>
38
42#ifdef UG_PARALLEL
44#endif
45
46namespace ug{
47
49
63template <typename TVector>
64class GMRES
66{
67 public:
69 typedef TVector vector_type;
70
73
74 protected:
79
80 public:
82 GMRES(size_t restart) : m_restart(restart) {};
83
85 GMRES( size_t restart,
88 : base_type(spPrecond, spConvCheck), m_restart(restart)
89 {};
90
92 virtual const char* name() const {return "GMRES";}
93
95 virtual bool supports_parallel() const
96 {
97 if(preconditioner().valid())
98 return preconditioner()->supports_parallel();
99 return true;
100 }
101
102 // Solve J(u)*x = b, such that x = J(u)^{-1} b
104 {
105 // check correct storage type in parallel
106 #ifdef UG_PARALLEL
107 if(!b.has_storage_type(PST_ADDITIVE) || !x.has_storage_type(PST_CONSISTENT))
108 UG_THROW("GMRES: Inadequate storage format of Vectors.");
109 #endif
110
111 // copy rhs
112 SmartPtr<vector_type> spR = b.clone();
113
114 // build defect: b := b - A*x
115 linear_operator()->apply_sub(*spR, x);
116
117 // prepare convergence check
119
120 // compute start defect norm
121 convergence_check()->start(*spR);
122
123 // storage for v, h, gamma
124 std::vector<SmartPtr<vector_type> > v(m_restart+1);
125 std::vector<std::vector<number> > h(m_restart+1);
126 for(size_t i = 0; i < h.size(); ++i) h[i].resize(m_restart+1);
127 std::vector<number> gamma(m_restart+1);
128 std::vector<number> c(m_restart+1);
129 std::vector<number> s(m_restart+1);
130
131 // old norm
132 number oldNorm;
133
134 // Iteration loop
135 while(!convergence_check()->iteration_ended())
136 {
137 // get storage for first vector v[0]
138 if(v[0].invalid()) v[0] = x.clone_without_values();
139
140 // apply v[0] = M^-1 * (b-A*x)
141 if(preconditioner().valid()){
142 if(!preconditioner()->apply(*v[0], *spR)){
143 UG_LOG("GMRES: Cannot apply preconditioner to b-A*x0.\n");
144 return false;
145 }
146 }
147 // ... or reuse v[0] = (b-A*x)
148 else{
149 SmartPtr<vector_type> tmp = v[0]; v[0] = spR; spR = tmp;
150 }
151
152 // make v[0] unique
153 #ifdef UG_PARALLEL
154 if(!v[0]->change_storage_type(PST_UNIQUE))
155 UG_THROW("GMRES: Cannot convert v0 to consistent vector.");
156 #endif
157
158 // post-process the correction
160
161 // Compute norm of inital residuum:
162 oldNorm = gamma[0] = v[0]->norm();
163
164 // normalize v[0] := v[0] / ||v[0]||
165 *v[0] *= 1./gamma[0];
166
167 // loop gmres iterations
168 size_t numIter = 0;
169 for(size_t j = 0; j < m_restart; ++j)
170 {
171 numIter = j;
172
173 // get storage for v[j+1]
174 if(v[j+1].invalid()) v[j+1] = x.clone_without_values();
175
176#ifdef UG_PARALLEL
177 if(!v[j]->change_storage_type(PST_CONSISTENT))
178 UG_THROW("GMRES: Cannot convert v["<<j+1<<"] to consistent vector.");
179#endif
180
181 // compute r = A*v[j]
182 linear_operator()->apply(*spR, *v[j]);
183
184 // apply v[j+1] = M^-1 * A * v[j]
185 if(preconditioner().valid()){
186 if(!preconditioner()->apply(*v[j+1], *spR)){
187 UG_LOG("GMRES: Cannot apply preconditioner to A*v["<<j<<"].\n");
188 return false;
189 }
190 }
191 // ... or reuse v[j+1] = A * v[j]
192 else{
193 SmartPtr<vector_type> tmp = v[j+1]; v[j+1] = spR; spR = tmp;
194 }
195
196 // make v[j], v[j+1] unique
197 #ifdef UG_PARALLEL
198 if(!v[j]->change_storage_type(PST_UNIQUE))
199 UG_THROW("GMRES: Cannot convert v0 to consistent vector.");
200 if(!v[j+1]->change_storage_type(PST_UNIQUE))
201 UG_THROW("GMRES: Cannot convert v["<<j<<"] to consistent vector.");
202 #endif
203
204 // post-process the correction
205 m_corr_post_process.apply (*v[j+1]);
206
207 // loop previous steps
208 for(size_t i = 0; i <= j; ++i)
209 {
210 // h_ij := (r, v[j])
211 h[i][j] = VecProd(*v[j+1], *v[i]);
212
213 // v[j+1] -= h_ij * v[i]
214 VecScaleAppend(*v[j+1], *v[i], (-1)*h[i][j]);
215 }
216
217 // compute h_{j+1,j}
218 h[j+1][j] = v[j+1]->norm();
219
220 // update h
221 for(size_t i = 0; i < j; ++i)
222 {
223 const number hij = h[i][j];
224 const number hi1j = h[i+1][j];
225
226 h[i][j] = c[i+1]*hij + s[i+1]*hi1j;
227 h[i+1][j] = s[i+1]*hij - c[i+1]*hi1j;
228 }
229
230 // alpha := sqrt(h_jj ^2 + h_{j+1,j}^2)
231 const number alpha = sqrt(h[j][j]*h[j][j] + h[j+1][j]*h[j+1][j]);
232
233 // update s, c
234 s[j+1] = h[j+1][j] / alpha;
235 c[j+1] = h[j][j] / alpha;
236 h[j][j] = alpha;
237
238 // compute new norm
239 gamma[j+1] = s[j+1]*gamma[j];
240 gamma[j] = c[j+1]*gamma[j];
241
242 if(preconditioner().valid()) {
243 UG_LOG(std::string(convergence_check()->get_offset(),' '));
244 UG_LOG("% GMRES "<<std::setw(4) <<j+1<<": "
245 << gamma[j+1] << " " << gamma[j+1] / oldNorm);
246 UG_LOG(" (in Precond-Norm) \n");
247 oldNorm = gamma[j+1];
248 }
249 else{
250 convergence_check()->update_defect(gamma[j+1]);
251 }
252
253 // normalize v[j+1]
254 *v[j+1] *= 1./(h[j+1][j]);
255 }
256
257 // compute current x
258 for(size_t i = numIter; ; --i){
259 for(size_t j = i+1; j <= numIter; ++j)
260 gamma[i] -= h[i][j] * gamma[j];
261
262 gamma[i] /= h[i][i];
263
264 // x = x + gamma[i] * v[i]
265 VecScaleAppend(x, *v[i], gamma[i]);
266
267 if(i == 0) break;
268 }
269
270 // compute fresh defect: b := b - A*x
271 *spR = b;
272 linear_operator()->apply_sub(*spR, x);
273
274 if(preconditioner().valid())
275 convergence_check()->update(*spR);
276 }
277
278 // print ending output
279 return convergence_check()->post();
280 }
281
282 public:
283 virtual std::string config_string() const
284 {
285 std::stringstream ss;
286 ss << "GMRes ( restart = " << m_restart << ")\n";
288 return ss.str();
289 }
290
296
302
303 protected:
306 {
307 // set iteration symbol and name
308 convergence_check()->set_name(name());
309 convergence_check()->set_symbol('%');
310
311 // set preconditioner string
312 std::string s;
313 if(preconditioner().valid())
314 s = std::string(" (Precond: ") + preconditioner()->name() + ")";
315 else
316 s = " (No Preconditioner) ";
317 convergence_check()->set_info(s);
318 }
319
320 protected:
322 size_t m_restart;
323
325
331
334 {
335 #ifdef UG_PARALLEL
336 if(a.has_storage_type(PST_UNIQUE) && b.has_storage_type(PST_UNIQUE));
337 else if(a.has_storage_type(PST_CONSISTENT) && b.has_storage_type(PST_CONSISTENT));
338 else if (a.has_storage_type(PST_ADDITIVE) && b.has_storage_type(PST_ADDITIVE));
339 else
340 {
341 a.change_storage_type(PST_ADDITIVE);
342 b.change_storage_type(PST_ADDITIVE);
343 }
344 #endif
345
346 for(size_t i = 0; i < a.size(); ++i)
347 {
348 // todo: move VecScaleAppend to ParallelVector
349 VecScaleAdd(a[i], 1.0, a[i], s, b[i]);
350 }
351 return true;
352 }
353
356 {
357 return a.dotprod(b);
358 }
359};
360
361} // end namespace ug
362
363#endif /* __H__UG__LIB_DISC__OPERATOR__LINEAR_OPERATOR__GMRES__ */
parameterString p
parameterString s
Definition smart_pointer.h:108
the GMREs method as a solver for linear operators
Definition gmres.h:66
void remove_postprocess_corr(SmartPtr< IPProcessVector< vector_type > > p)
removes a post-process for the iterates
Definition gmres.h:298
virtual std::string config_string() const
returns information about configuration parameters
Definition gmres.h:283
TVector vector_type
Vector type.
Definition gmres.h:69
number VecProd(vector_type &a, vector_type &b)
computes the vector product
Definition gmres.h:355
virtual bool apply_return_defect(vector_type &x, vector_type &b)
Definition gmres.h:103
size_t m_restart
restart parameter
Definition gmres.h:322
virtual const char * name() const
name of solver
Definition gmres.h:92
void prepare_conv_check()
prepares the output of the convergence check
Definition gmres.h:305
GMRES(size_t restart, SmartPtr< ILinearIterator< vector_type > > spPrecond, SmartPtr< IConvergenceCheck< vector_type > > spConvCheck)
constructor setting the preconditioner and the convergence check
Definition gmres.h:85
void add_postprocess_corr(SmartPtr< IPProcessVector< vector_type > > p)
adds a post-process for the iterates
Definition gmres.h:292
virtual bool supports_parallel() const
returns if parallel solving is supported
Definition gmres.h:95
PProcessChain< vector_type > m_corr_post_process
postprocessor for the correction in the iterations
Definition gmres.h:330
GMRES(size_t restart)
default constructor
Definition gmres.h:82
IPreconditionedLinearOperatorInverse< vector_type > base_type
Base type.
Definition gmres.h:72
bool VecScaleAppend(vector_type &a, vector_type &b, number s)
adds a scaled vector to a second one
Definition gmres.h:333
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
interface for pre- and postprocess functions
Definition pprocess.h:59
describes an inverse linear mapping X->X
Definition preconditioned_linear_operator_inverse.h:63
SmartPtr< ILinearIterator< vector_type, vector_type > > preconditioner()
Definition preconditioned_linear_operator_inverse.h:118
virtual bool apply(TVector &x, const TVector &b)
Definition preconditioned_linear_operator_inverse.h:152
std::string config_string_preconditioner_convergence_check() const
returns config information of convergence check and preconditioner
Definition preconditioned_linear_operator_inverse.h:200
a chain of pre- or postprocess operations
Definition pprocess.h:78
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
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
@ PST_CONSISTENT
Definition parallel_storage_type.h:68
@ PST_UNIQUE
Definition parallel_storage_type.h:70
@ PST_ADDITIVE
Definition parallel_storage_type.h:69
#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
bool resize(size_t newRows, size_t newCols)