ug4
Loading...
Searching...
No Matches
auto_linear_solver.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2013-2015: G-CSC, Goethe University Frankfurt
3 * Author: Martin Rupp
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__AUTO_LINEAR_OPERATOR__LINEAR_SOLVER__
34#define __H__UG__LIB_DISC__OPERATOR__AUTO_LINEAR_OPERATOR__LINEAR_SOLVER__
35#include <iostream>
36#include <string>
37
40#ifdef UG_PARALLEL
42#endif
44namespace ug{
45
46// this is for matrix operators which recalculate their "real" operator
47// if necessary
49{
50public:
52 virtual void calculate_matrix() = 0;
53};
54
56
62template <typename TVector>
65{
66 public:
68 typedef TVector vector_type;
69
72
73 protected:
78
79 public:
80 AutoLinearSolver //(double reductionAlwaysAccept, double worseThenAverage, double desiredDefect)
81 (double desiredDefect, double desiredReduction)
82 {
83 m_bInited=-1;
84// m_N = 0;
85// m_reductionAlwaysAccept = reductionAlwaysAccept;
86// m_worseThenAverage = worseThenAverage;
87 m_desiredDefect = desiredDefect;
88 m_desiredReduction = desiredReduction;
90 m_savedTime = 0.0;
91 }
93 {
94 m_bInited=-1;
95// m_N = 0;
99 m_savedTime = 0.0;
100 }
101
103 virtual bool supports_parallel() const
104 {
105 if(preconditioner().valid())
106 return preconditioner()->supports_parallel();
107 else return true;
108 }
109
110private:
114// size_t m_N;
120
125
126 public:
127
129 {
131 }
132
134 {
136 }
137
139 virtual const char* name() const {return "Auto Iterative Linear Solver";}
140
141
143 {
144 m_u = u;
145 return init_op(J);
146 }
148 {
149 m_u.resize(0);
150 return init_op(J);
151 }
152
154 {
156 //UG_LOG("ALS:init\n");
157 m_initCalled++;
158 if(m_bInited == -1)
159 {
160 m_bInited=false;
161 pJ = J;
162 reinit();
163 }
164 else
165 {
166 m_bInited=false;
167 pJ = J;
168// if(u.size() != m_N)
169// reinit(u);
170// else
171// m_u = u;
172 }
173
174 return true;
175 }
176
177 bool reinit()
178 {
179 if(m_bInited) return true;
180 m_bInited = true;
181 //UG_LOG("ALS:reinit\n");
182
183 double tStart = get_clock_s();
184 // this does not work with stuff.
185 SmartPtr<UpdateableMatrixOperator> uo = pJ.template cast_dynamic<UpdateableMatrixOperator> ();
186 if(uo.valid()) uo->calculate_matrix();
187 if(m_u.size() != 0.0)
188 { if(!base_type::init(pJ, m_u)) return false; }
189 else if(!base_type::init(pJ)) return false;
190 m_lastInitTime = get_clock_s()-tStart;
191
192 m_initsDone++;
193
194// m_N = u.size();
195
196 return true;
197 }
198
200 {
201 // Compute a correction c := B*d using one iterative step
202 // Internally the defect is updated d := d - A*c = b - A*(x+c)
203 if(preconditioner().valid()) {
204 LS_PROFILE_BEGIN(LS_ApplyPrecond);
205
206 if(!preconditioner()->apply(c, d))
207 {
208 UG_LOG("ERROR in 'LinearSolver::apply': Iterator "
209 "Operator applied incorrectly. Aborting.\n");
210 return false;
211 }
212 linear_operator()->apply_sub(d, c);
213 LS_PROFILE_END(LS_ApplyPrecond);
214 }
215
216 return true;
217 }
218
219 virtual bool apply(vector_type& x, const vector_type& b)
220 {
221 //UG_LOG("ALS:apply\n");
222 SmartPtr<vector_type> spB = b.clone_without_values();
223 *spB = b;
224 return apply_return_defect(x, *spB);
225 }
228 {
229 //UG_LOG("ALS:return_defect\n");
230 LS_PROFILE_BEGIN(LS_ApplyReturnDefect);
231
232 #ifdef UG_PARALLEL
233 if(!b.has_storage_type(PST_ADDITIVE) || !x.has_storage_type(PST_CONSISTENT))
234 UG_THROW("LinearSolver::apply: Inadequate storage format of Vectors.");
235 #endif
236
237 // rename b as d (for convenience)
238 vector_type& d = b;
239
240 // build defect: d := b - J(u)*x
241 LS_PROFILE_BEGIN(LS_BuildDefect);
242 linear_operator()->apply_sub(d, x);
243 LS_PROFILE_END(LS_BuildDefect);
244
245 // create correction
246 LS_PROFILE_BEGIN(LS_CreateCorrection);
247 SmartPtr<vector_type> spC = x.clone_without_values();
248 vector_type& c = *spC;
249 LS_PROFILE_END(LS_CreateCorrection);
250
251 LS_PROFILE_BEGIN(LS_ComputeStartDefect);
253 convergence_check()->start(d);
254 LS_PROFILE_END(LS_ComputeStartDefect);
255
256 int loopCnt = 0;
257 char ext[20]; snprintf(ext, 20, "_iter%03d", loopCnt);
258 std::string name("LS_Defect_"); name.append(ext).append(".vec");
259 write_debug(d, name.c_str());
260 name = std::string("LS_Solution_"); name.append(ext).append(".vec");
261 write_debug(x, name.c_str());
262
263 // Iteration loop
264
265 if(m_bInited == false)
266 {
267 vector_type x2 = x;
268 vector_type d2 = d;
269 try{
270 double tStartIterationTime = get_clock_s();
271 while(!convergence_check()->iteration_ended())
272 {
273 //double tComputeTime = get_clock_s();
274 if( !compute_correction(c, d) ) return false;
275 x += c;
276 convergence_check()->update(d);
277
278
279 double r = convergence_check()->rate();
280 double reduction = convergence_check()->reduction();
281 double defect = convergence_check()->defect();
282 double steps = convergence_check()->step();
283// if(r > m_reductionAlwaysAccept
284// && (r >= 1 || r * m_worseThenAverage > m_avgReduction))
285 double spentTime = get_clock_s() - tStartIterationTime;
286
287 double tComputeTime = spentTime/steps; //get_clock_s()-tComputeTime;
288
289// double timeForOriginalAlgorithm = reduction/m_reductionPerTime + m_lastInitTime;
290 double approxSteps =
291 std::min(log(m_desiredDefect/defect)/log(r),
292 log(m_desiredReduction/reduction)/log(r) );
293 double approxRemainingTimeForSolution = approxSteps*tComputeTime;
294 /*UG_LOG("\n");
295 UG_LOG("m_lastCallReduction = " << reset_floats << m_lastCallReduction << "\n");
296 UG_LOG("reduction = " << reset_floats << reduction << "\n");
297 UG_LOG("reduction remain = " << reset_floats << m_lastCallReduction/reduction << "\n");
298 UG_LOG("approxSteps = " << reset_floats << approxSteps << "\n");
299 UG_LOG("approxTimeForSolution = " << approxTimeForSolution << "\n");
300 UG_LOG("spentTime = " << spentTime << "\n");
301 UG_LOG("tComputeTime = " << tComputeTime << "\n");
302 UG_LOG("rate = " << r << "\n");
303 UG_LOG("reduction = " << reduction << "\n");*/
304 if(r > 1)
305 {
306 m_savedTime -= spentTime;
307 UG_LOG("AutoLinearSolver: REINIT because reduction rate >= 1.")
308 UG_LOG(" [ Inits called: " << m_initCalled << ", inits done: " << reset_floats << m_initsDone+1
309 << " (" << (100.0*(m_initsDone+1))/m_initCalled << " %), Total Time saved: " << m_savedTime << " s]\n");
310
311
312 reinit();
313 break;
314 }
315 double approxResolveTime = m_lastCallTime + m_lastInitTime;
316 if(approxResolveTime < approxRemainingTimeForSolution)
317 {
318 m_savedTime -= spentTime;
319 UG_LOG("AutoLinearSolver: REINIT because\n" << reset_floats )
320 UG_LOG(" approximated remaining Time for Solution with old preconditioner = " << approxRemainingTimeForSolution << " s\n");
321 UG_LOG(" > approximated Time for Reinit preconditioner and solve = " << approxResolveTime << " s\n");
322 UG_LOG(" with old preconditioner:\n");
323 UG_LOG(" reduction rate = " << r << " avg reduction = " << convergence_check()->avg_rate() << "\n")
324 UG_LOG(" steps = " << steps << ", reduction = " << reduction << "\n")
325 UG_LOG(" spentTime = " << spentTime << ", time per Step = " << tComputeTime << "\n");
326 UG_LOG(" approximation of solution with old:\n")
327 UG_LOG(" reduction remain = " << reset_floats << m_lastCallReduction/reduction << "\n");
328 UG_LOG(" approxSteps with last reduction rate = " << approxSteps << "\n");
329 UG_LOG(" [ Inits called: " << m_initCalled << ", inits done: " << reset_floats << m_initsDone+1
330 << " (" << (100.0*(m_initsDone+1))/m_initCalled << " %), Total Time saved: " << m_savedTime << " s]\n");
331 reinit();
332
333 break;
334 }
335 else
336 {
337 x2 = x;
338 d2 = d;
339 }
340 }
341 if(!m_bInited)
342 {
343 double spentTime = get_clock_s() - tStartIterationTime;
345 UG_LOG("AutoLinearSolver solved with old preconditioner [")
346 UG_LOG(" Inits called: " << m_initCalled << ", inits done: " << reset_floats << m_initsDone+1
347 << " (" << (100.0*(m_initsDone+1))/m_initCalled << " %), Total Time saved: " << m_savedTime << " s]\n");
348 UG_LOG(" time spent with old = " << reset_floats << spentTime << " s, ");
349 UG_LOG(" last time init + solve = " << m_lastCallTime+m_lastInitTime << " s, ");
350
351 if(m_lastCallTime+m_lastInitTime > spentTime)
352 { UG_LOG("saved " << m_lastCallTime+m_lastInitTime - spentTime << " s!.\n"); }
353 else
354 { UG_LOG("spent too much time with old! " << spentTime - m_lastCallTime+m_lastInitTime<< " s!\n"); }
355
356 }
357
358 }
359 catch(...)
360 {
361
362 }
363 x = x2;
364 d = d2;
365 }
366
367 if(!convergence_check()->iteration_ended())
368 {
369 double T = get_clock_s();
370 convergence_check()->start(d);
371 while(!convergence_check()->iteration_ended())
372 {
373 if( !compute_correction(c, d) ) return false;
374 x += c;
375 convergence_check()->update(d);
376 }
377 m_avgReduction = convergence_check()->avg_rate();
378 T = get_clock_s() - T;
379 m_reductionPerTime = convergence_check()->reduction()/T;
380 m_lastCallTime = T;
381 m_lastCallReduction = convergence_check()->reduction();
382 }
383
384
385 // write some information when ending the iteration
386 if(!convergence_check()->post())
387 {
388 UG_LOG("ERROR in 'LinearSolver::apply': post-convergence-check "
389 "signaled failure. Aborting.\n");
390 return false;
391 }
392
393 // end profiling of whole function
394 LS_PROFILE_END(LS_ApplyReturnDefect);
395
396 // we're done
397 return true;
398 }
399
401 {
402 UG_LOG("AutoLinearSolver:\n");
403 UG_LOG(" avg reduction is " << m_avgReduction << "\n");
404 UG_LOG(" Inits called: " << m_initCalled << ", inits done: " << reset_floats << m_initsDone
405 << " (" << (100.0*(m_initsDone))/m_initCalled << " %)\n");
406 UG_LOG(" m_reductionPerTime = " << m_reductionPerTime << " s\n");
407 UG_LOG(" reductionTime for 0.1 reduction = " << 0.1/m_reductionPerTime << " s\n");
408 UG_LOG(" m_lastInitTime = " << m_lastInitTime << " s\n");
409 UG_LOG(" SAVED TIME: " << m_savedTime << " s\n");
410 }
411
412 protected:
415 {
416 convergence_check()->set_name(name());
417 convergence_check()->set_symbol('%');
418 if(preconditioner().valid())
419 {
420 std::string s;
421 if(preconditioner().valid())
422 s = std::string(" (Precond: ") + preconditioner()->name() + ")";
423 else
424 s = " (No Preconditioner) ";
425 convergence_check()->set_info(s);
426 }
427 }
428};
429
430} // end namespace ug
431
432#endif /* __H__UG__LIB_DISC__OPERATOR__LINEAR_OPERATOR__LINEAR_SOLVER__ */
parameterString s
Definition smart_pointer.h:108
bool valid() const
returns true if the pointer is valid, false if not.
Definition smart_pointer.h:206
linear solver using abstract preconditioner interface
Definition auto_linear_solver.h:65
int m_bInited
Definition auto_linear_solver.h:113
void set_reinit_when_worse_then_average(double d)
Definition auto_linear_solver.h:133
virtual const char * name() const
returns the name of the solver
Definition auto_linear_solver.h:139
void prepare_conv_check()
prepares the convergence check output
Definition auto_linear_solver.h:414
double m_savedTime
Definition auto_linear_solver.h:124
AutoLinearSolver()
Definition auto_linear_solver.h:92
vector_type m_u
Definition auto_linear_solver.h:116
virtual bool apply(vector_type &x, const vector_type &b)
Definition auto_linear_solver.h:219
bool init_op(SmartPtr< ILinearOperator< vector_type, vector_type > > J)
Definition auto_linear_solver.h:153
void set_reduction_always_accept(double d)
Definition auto_linear_solver.h:128
double m_reductionPerTime
Definition auto_linear_solver.h:122
size_t m_initCalled
Definition auto_linear_solver.h:119
double m_lastCallTime
Definition auto_linear_solver.h:122
bool reinit()
Definition auto_linear_solver.h:177
SmartPtr< ILinearOperator< vector_type, vector_type > > pJ
Definition auto_linear_solver.h:115
IPreconditionedLinearOperatorInverse< vector_type > base_type
Base type.
Definition auto_linear_solver.h:71
double m_reductionAlwaysAccept
Definition auto_linear_solver.h:111
bool compute_correction(vector_type &c, vector_type &d)
Definition auto_linear_solver.h:199
double m_worseThenAverage
Definition auto_linear_solver.h:112
double m_desiredReduction
Definition auto_linear_solver.h:123
virtual bool apply_return_defect(vector_type &x, vector_type &b)
solves the system and returns the last defect
Definition auto_linear_solver.h:227
double m_avgReduction
Definition auto_linear_solver.h:117
TVector vector_type
Vector type.
Definition auto_linear_solver.h:68
double m_lastCallReduction
Definition auto_linear_solver.h:122
size_t m_initsDone
Definition auto_linear_solver.h:118
virtual bool supports_parallel() const
returns if parallel solving is supported
Definition auto_linear_solver.h:103
virtual bool init(SmartPtr< ILinearOperator< vector_type, vector_type > > J)
initializes the solver for an operator
Definition auto_linear_solver.h:147
double m_desiredDefect
Definition auto_linear_solver.h:123
double m_lastInitTime
Definition auto_linear_solver.h:121
virtual bool init(SmartPtr< ILinearOperator< vector_type, vector_type > > J, const vector_type &u)
initializes the solver for an operator
Definition auto_linear_solver.h:142
void print_information()
Definition auto_linear_solver.h:400
describes a linear mapping X->Y
Definition linear_operator.h:80
number reduction() const
returns the current relative reduction
Definition linear_operator_inverse.h:214
number defect() const
returns the current defect
Definition linear_operator_inverse.h:208
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
virtual bool init(SmartPtr< ILinearOperator< Y, X > > L)
initializes for the inverse for a linear operator
Definition linear_operator_inverse.h:135
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 init(SmartPtr< ILinearOperator< vector_type, vector_type > > J, const vector_type &u)
initializes the solver for an operator
Definition preconditioned_linear_operator_inverse.h:123
Definition auto_linear_solver.h:49
virtual void calculate_matrix()=0
virtual ~UpdateableMatrixOperator()
Definition auto_linear_solver.h:51
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_ADDITIVE
Definition parallel_storage_type.h:69
static std::ios_base & reset_floats(std::ios_base &o)
used to unset flags set by std::scientific or std::fixed.
Definition ostream_util.h:52
#define UG_THROW(msg)
Definition error.h:57
#define UG_LOG(msg)
Definition log.h:367
#define LS_PROFILE_BEGIN(name)
Definition linear_solver_profiling.h:40
#define LS_PROFILE_END(name)
Definition linear_solver_profiling.h:41
the ug namespace
double get_clock_s()
Definition stopwatch.h:103