ug4
Loading...
Searching...
No Matches
newton_impl.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2010-2015: G-CSC, Goethe University Frankfurt
3 * Author: Andreas Vogel, modifications nested Newton: Markus Knodel
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__NON_LINEAR_OPERATOR__NEWTON_SOLVER__NEWTON_IMPL__
34#define __H__UG__LIB_DISC__OPERATOR__NON_LINEAR_OPERATOR__NEWTON_SOLVER__NEWTON_IMPL__
35
36#include <iostream>
37#include <sstream>
38#include <limits>
39
40#include "newton.h"
43
44//#include "lib_disc/operator/non_linear_operator/newton_solver/nestedNewtonRFSwitch.h"
45
46#define PROFILE_NEWTON
47#ifdef PROFILE_NEWTON
48 #define NEWTON_PROFILE_FUNC() PROFILE_FUNC_GROUP("Newton")
49 #define NEWTON_PROFILE_BEGIN(name) PROFILE_BEGIN_GROUP(name, "Newton")
50 #define NEWTON_PROFILE_END() PROFILE_END()
51#else
52 #define NEWTON_PROFILE_FUNC()
53 #define NEWTON_PROFILE_BEGIN(name)
54 #define NEWTON_PROFILE_END()
55#endif
56
57namespace ug{
58
59template <typename TAlgebra>
63 SmartPtr<ILineSearch<vector_type> > spLineSearch) :
64 m_spLinearSolver(LinearSolver),
65 m_spConvCheck(spConvCheck),
66 m_spLineSearch(spLineSearch),
67 m_N(NULL),
68 m_J(NULL),
69 m_spAss(NULL),
70 m_reassembe_J_freq(0),
71 m_dgbCall(0),
72 m_lastNumSteps(0),
73 m_newtonUpdater(SPNULL)
74//#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE
75// m_newtonUpdater(new NewtonUpdaterGeneric<vector_type>{})
76//#endif
77{};
78
79template <typename TAlgebra>
82 m_spLinearSolver(NULL),
83 m_spConvCheck(new StdConvCheck<vector_type>(10, 1e-8, 1e-10, true)),
84 m_spLineSearch(NULL),
85 m_N(NULL),
86 m_J(NULL),
87 m_spAss(NULL),
88 m_reassembe_J_freq(0),
89 m_dgbCall(0),
90 m_lastNumSteps(0),
91 m_newtonUpdater(SPNULL)
92//#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE
93// ,
94// m_newtonUpdater(new NewtonUpdaterGeneric<vector_type>{})
95//#endif
96{};
97
98template <typename TAlgebra>
101 m_spLinearSolver(NULL),
102 m_spConvCheck(new StdConvCheck<vector_type>(10, 1e-8, 1e-10, true)),
103 m_spLineSearch(NULL),
104 m_N(NULL),
105 m_J(NULL),
106 m_spAss(NULL),
107 m_reassembe_J_freq(0),
108 m_dgbCall(0),
109 m_lastNumSteps(0),
110 m_newtonUpdater(SPNULL)
111//#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE
112// ,
113// m_newtonUpdater(new NewtonUpdaterGeneric<vector_type>{})
114//#endif
115{
116 init(N);
117};
118
119template <typename TAlgebra>
122 m_spLinearSolver(NULL),
123 m_spConvCheck(new StdConvCheck<vector_type>(10, 1e-8, 1e-10, true)),
124 m_spLineSearch(NULL),
125 m_N(NULL),
126 m_J(NULL),
127 m_spAss(NULL),
128 m_reassembe_J_freq(0),
129 m_dgbCall(0),
130 m_lastNumSteps(0),
131 m_newtonUpdater(SPNULL)
132//#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE
133// ,
134// m_newtonUpdater(new NewtonUpdaterGeneric<vector_type>{})
135//#endif
136{
137 m_spAss = spAss;
139};
140
141template <typename TAlgebra>
144{
145 m_spConvCheck = spConvCheck;
146 m_spConvCheck->set_offset(3);
147 m_spConvCheck->set_symbol('#');
148 m_spConvCheck->set_name("Newton Solver");
149}
150
151template <typename TAlgebra>
153{
154 NEWTON_PROFILE_BEGIN(NewtonSolver_init);
155 m_N = N.template cast_dynamic<AssembledOperator<TAlgebra> >();
156 if(m_N.invalid())
157 UG_THROW("NewtonSolver: currently only works for AssembledDiscreteOperator.");
158
159 m_spAss = m_N->discretization();
160 return true;
161}
162
163template <typename TAlgebra>
165{
166// todo: maybe remove this from interface
167 return true;
168}
169
170template <typename TAlgebra>
172{
173 NEWTON_PROFILE_BEGIN(NewtonSolver_apply);
174// increase call count
175 m_dgbCall++;
176
177// Check for linear solver
178 if(m_spLinearSolver.invalid())
179 UG_THROW("NewtonSolver::apply: Linear Solver not set.");
180
181// Jacobian
182 if(m_J.invalid() || m_J->discretization() != m_spAss) {
183 m_J = make_sp(new AssembledLinearOperator<TAlgebra>(m_spAss));
184 }
185 m_J->set_level(m_N->level());
186
187// create tmp vectors
188 SmartPtr<vector_type> spD = u.clone_without_values();
189 SmartPtr<vector_type> spC = u.clone_without_values();
190
191// Set dirichlet values
192 try{
193 m_N->prepare(u);
194 }
195 UG_CATCH_THROW("NewtonSolver::prepare: Prepare of Operator failed.");
196
197// Compute first Defect
198 try{
199 NEWTON_PROFILE_BEGIN(NewtonComputeDefect1);
200 m_N->apply(*spD, u);
202 }UG_CATCH_THROW("NewtonSolver::apply: Computation of Start-Defect failed.");
203
204// loop counts (for the the convergence rate statistics etc.)
205 int loopCnt = 0;
206 m_lastNumSteps = 0;
207
208// write start defect for debug
209 char debug_name_ext[20];
210 if (this->debug_writer_valid())
211 {
212 snprintf(debug_name_ext, 20, "_iter%03d", loopCnt);
213 write_debug(*spD, std::string("NEWTON_Defect") + debug_name_ext);
214 write_debug(u, "NEWTON_StartSolution");
215 }
216
217// increase offset of output for linear solver
218 const int stdLinOffset = m_spLinearSolver->standard_offset();
219 m_spLinearSolver->convergence_check()->set_offset(stdLinOffset + 3);
220
221// set info string indicating the used linear solver
222 std::stringstream ss; ss << "(Linear Solver: " << m_spLinearSolver->name() << ")";
223 m_spConvCheck->set_info(ss.str());
224
225// start convergence check
226 m_spConvCheck->start(*spD);
227
228 for(size_t i = 0; i < m_stepUpdate.size(); ++i)
229 m_stepUpdate[i]->update();
230
231// loop iteration
232 while(!m_spConvCheck->iteration_ended())
233 {
234 m_lastNumSteps = loopCnt;
235
236 // set c = 0
237 NEWTON_PROFILE_BEGIN(NewtonSetCorretionZero);
238 spC->set(0.0);
240
241 for(size_t i = 0; i < m_innerStepUpdate.size(); ++i)
242 m_innerStepUpdate[i]->update();
243
244 // Compute Jacobian
245 try{
246 if(m_reassembe_J_freq == 0 || loopCnt % m_reassembe_J_freq == 0) // if we need to reassemble
247 {
248 NEWTON_PROFILE_BEGIN(NewtonComputeJacobian);
249 m_J->init(u);
251 }
252 }UG_CATCH_THROW("NewtonSolver::apply: Initialization of Jacobian failed.");
253
254 // Write the current Jacobian for debug and prepare the section for the lin. solver
255 if (this->debug_writer_valid())
256 {
257 write_debug(m_J->get_matrix(), std::string("NEWTON_Jacobian") + debug_name_ext);
258 this->enter_debug_writer_section(std::string("NEWTON_LinSolver") + debug_name_ext);
259 }
260
261 // Init Jacobi Inverse
262 try{
263 NEWTON_PROFILE_BEGIN(NewtonPrepareLinSolver);
264 if(!m_spLinearSolver->init(m_J, u))
265 {
266 UG_LOG("ERROR in 'NewtonSolver::apply': Cannot init Inverse Linear "
267 "Operator for Jacobi-Operator.\n");
268 return false;
269 }
271 }UG_CATCH_THROW("NewtonSolver::apply: Initialization of Linear Solver failed.");
272
273 // Solve Linearized System
274 try{
275 NEWTON_PROFILE_BEGIN(NewtonApplyLinSolver);
276 if(!m_spLinearSolver->apply(*spC, *spD))
277 {
278 UG_LOG("ERROR in 'NewtonSolver::apply': Cannot apply Inverse Linear "
279 "Operator for Jacobi-Operator.\n");
280 return false;
281 }
283 }UG_CATCH_THROW("NewtonSolver::apply: Application of Linear Solver failed.");
284
285 this->leave_debug_writer_section();
286
287 // store convergence history
288 const int numSteps = m_spLinearSolver->step();
289 if(loopCnt >= (int)m_vTotalLinSolverSteps.size()) m_vTotalLinSolverSteps.resize(loopCnt+1);
290 if(loopCnt >= (int)m_vLinSolverCalls.size()) m_vLinSolverCalls.resize(loopCnt+1, 0);
291 if(loopCnt >= (int)m_vLinSolverRates.size()) m_vLinSolverRates.resize(loopCnt+1, 0);
292 m_vTotalLinSolverSteps[loopCnt] += numSteps;
293 m_vLinSolverCalls[loopCnt] += 1;
294 m_vLinSolverRates[loopCnt] += m_spLinearSolver->convergence_check()->avg_rate();
295
296 try{
297 // Line Search
298 if(m_spLineSearch.valid())
299 {
300 m_spLineSearch->set_offset(" # ");
301 NEWTON_PROFILE_BEGIN(NewtonLineSearch);
302
303//#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE
304
305 if( m_newtonUpdater != SPNULL )
306 m_spLineSearch->setNewtonUpdater(m_newtonUpdater);
307
308//#endif
309 if(!m_spLineSearch->search(m_N, u, *spC, *spD, m_spConvCheck->defect()))
310 {
311 UG_LOG("ERROR in 'NewtonSolver::apply': "
312 "Newton Solver did not converge.\n");
313 return false;
314 }
316 }
317 // No line search: Compute new defect
318 else
319 {
320 if( m_newtonUpdater != SPNULL )
321 {
322//#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE
323
324 if( ! m_newtonUpdater->updateSolution(u,*spC) )
325 {
326 UG_LOG("ERROR in 'NewtonSolver::apply': "
327 "Newton Update did not work.\n");
328 // TODO FIXME was macht conv check update? wie kriege ich hier einfach ein riesiges Residuum rein, ohne was zu rechnen?
329 return false;
330 }
331
332 if( ! m_newtonUpdater->tellAndFixUpdateEvents(u) )
333 {
334 UG_LOG("unable to fix local Newton updates" << std::endl );
335 return false;
336 }
337
338 }
339 else
340 {
341//#else
342 // update solution
343 u -= *spC;
344 }
345//#endif
346
347 // compute new Defect
348 NEWTON_PROFILE_BEGIN(NewtonComputeDefect);
349 m_N->prepare(u);
350 m_N->apply(*spD, u);
352 }
353 }UG_CATCH_THROW("NewtonSolver::apply: Line Search update failed.");
354
355
356 // update counter
357 loopCnt++;
358
359 // check convergence
360 m_spConvCheck->update(*spD);
361 if(loopCnt-1 >= (int)m_vNonLinSolverRates.size()) m_vNonLinSolverRates.resize(loopCnt, 0);
362 m_vNonLinSolverRates[loopCnt-1] += m_spConvCheck->rate();
363
364 // write defect for debug
365 if (this->debug_writer_valid())
366 {
367 snprintf(debug_name_ext, 20, "_iter%03d", loopCnt);
368 write_debug(*spD, std::string("NEWTON_Defect") + debug_name_ext);
369 write_debug(*spC, std::string("NEWTON_Correction") + debug_name_ext);
370 write_debug(u, std::string("NEWTON_Solution") + debug_name_ext);
371 }
372 }
373
374 // reset offset of output for linear solver to previous value
375 m_spLinearSolver->convergence_check()->set_offset(stdLinOffset);
376
377 return m_spConvCheck->post();
378}
379
380template <typename TAlgebra>
382{
383 UG_LOG("\nNewton solver convergence history:\n");
384 UG_LOG("Newton Step | Num Calls | Total Lin Iters | Avg Lin Iters | Avg Nonlin Rates | Avg Lin Rates \n");
385 int allCalls = 0, allLinSteps = 0;
386 number allLinRatesProduct = 1.0, allNonLinRatesProduct = 1.0;
387 for(int call = 0; call < (int)m_vLinSolverCalls.size(); ++call)
388 {
389 UG_LOG( " " << std::setw(10) << call+1 << " | ");
390 UG_LOG(std::setw(9) << m_vLinSolverCalls[call] << " | ");
391 allCalls += m_vLinSolverCalls[call];
392 UG_LOG(std::setw(15) << m_vTotalLinSolverSteps[call] << " | ");
393 allLinSteps += m_vTotalLinSolverSteps[call];
394 UG_LOG(std::setw(13) << std::setprecision(2) << std::fixed << m_vTotalLinSolverSteps[call] / (double)m_vLinSolverCalls[call] << " | ");
395 allNonLinRatesProduct *= pow((number)m_vNonLinSolverRates[call]/(double)m_vLinSolverCalls[call],(double)m_vLinSolverCalls[call]);
396 UG_LOG(std::setw(16) << std::setprecision(6) << std::scientific << m_vNonLinSolverRates[call] / (double)m_vLinSolverCalls[call] << " | ");
397 allLinRatesProduct *= (number)std::pow((number)m_vLinSolverRates[call]/(double)m_vLinSolverCalls[call],(number)m_vTotalLinSolverSteps[call]);
398 UG_LOG(std::setw(13) << std::setprecision(6) << std::scientific << m_vLinSolverRates[call] / (double)m_vLinSolverCalls[call]);
399 UG_LOG("\n");
400 }
401 UG_LOG( " all | ");
402 UG_LOG(std::setw(9) << allCalls << " | ");
403 UG_LOG(std::setw(15) << allLinSteps << " | ");
404 UG_LOG(std::setw(13) << std::setprecision(2) << std::fixed << allLinSteps / (number)allCalls << " | ");
405 UG_LOG(std::setw(16) << std::setprecision(6) << std::scientific << std::pow((number)allNonLinRatesProduct,(number)1.0/(number)allCalls) << " | ");
406 UG_LOG(std::setw(13) << std::setprecision(6) << std::scientific << std::pow((number)allLinRatesProduct,(number)1.0/(number)allLinSteps));
407 UG_LOG("\n");
408}
409
410template <typename TAlgebra>
412{
413 return m_vLinSolverCalls.size();
414}
415
416template <typename TAlgebra>
418{
419 return m_vLinSolverCalls[call];
420}
421
422template <typename TAlgebra>
424{
425 return m_vTotalLinSolverSteps[call];
426}
427
428template <typename TAlgebra>
430{
431 return m_vTotalLinSolverSteps[call] / ((double)m_vLinSolverCalls[call]);
432}
433
434template <typename TAlgebra>
436{
437 int allCalls = 0;
438 for(size_t call = 0; call < m_vLinSolverCalls.size(); ++call)
439 allCalls += m_vLinSolverCalls[call];
440 return allCalls;
441}
442
443template <typename TAlgebra>
445{
446 int allSteps = 0;
447 for(size_t call = 0; call < m_vLinSolverCalls.size(); ++call)
448 allSteps += m_vTotalLinSolverSteps[call];
449 return allSteps;
450}
451
452template <typename TAlgebra>
454{
455 return total_linsolver_steps()/((double)total_linsolver_calls());
456}
457
458
459template <typename TAlgebra>
461{
462 m_vLinSolverRates.clear();
463 m_vNonLinSolverRates.clear();
464 m_vLinSolverCalls.clear();
465 m_vTotalLinSolverSteps.clear();
466}
467
468template <typename TAlgebra>
470{
471// add call count to name
472 char ext[20]; snprintf(ext, 20, "_call%03d", m_dgbCall);
473
474// write
475 typedef DebugWritingObject<TAlgebra> base_writer_type;
476 base_writer_type::write_debug(vec, name + ext);
477}
478
479template <typename TAlgebra>
481{
482// add call count to name
483 char ext[20]; snprintf(ext, 20, "_call%03d", m_dgbCall);
484
485// write
486 typedef DebugWritingObject<TAlgebra> base_writer_type;
487 base_writer_type::write_debug(mat, name + ext);
488}
489
490template <typename TAlgebra>
492{
493 std::stringstream ss;
494 ss << "NewtonSolver\n";
495 ss << " LinearSolver: ";
496 if(m_spLinearSolver.valid()) ss << ConfigShift(m_spLinearSolver->config_string()) << "\n";
497 else ss << " NOT SET!\n";
498 ss << " ConvergenceCheck: ";
499 if(m_spConvCheck.valid()) ss << ConfigShift(m_spConvCheck->config_string()) << "\n";
500 else ss << " NOT SET!\n";
501 ss << " LineSearch: ";
502 if(m_spLineSearch.valid()) ss << ConfigShift(m_spLineSearch->config_string()) << "\n";
503 else ss << " not set.\n";
504 if(m_reassembe_J_freq != 0) ss << " Reassembling Jacobian only once per " << m_reassembe_J_freq << " step(s)\n";
505 return ss.str();
506}
507
508
509}
510
511#endif /* __H__UG__LIB_DISC__OPERATOR__NON_LINEAR_OPERATOR__NEWTON_SOLVER__NEWTON_IMPL__ */
512
location name
Definition checkpoint_util.lua:128
Definition smart_pointer.h:108
matrix operator based on the assembling of a problem
Definition assembled_linear_operator.h:60
Definition assembled_non_linear_operator.h:43
Definition debug_writer.h:354
Interface providing Jacobian and Defect of a discretization.
Definition assemble_interface.h:110
Definition convergence_check.h:72
Definition line_search.h:71
describes an inverse linear mapping X->Y
Definition linear_operator_inverse.h:80
describes a mapping X->Y
Definition operator.h:86
linear solver using abstract preconditioner interface
Definition linear_solver.h:57
int total_linsolver_calls() const
Definition newton_impl.h:435
void clear_average_convergence()
resets average linear solver convergence
Definition newton_impl.h:460
virtual bool prepare(vector_type &u)
prepare Operator
Definition newton_impl.h:164
virtual bool apply(vector_type &u)
apply Operator, i.e. N^{-1}(0) = u
Definition newton_impl.h:171
NewtonSolver()
default constructor
Definition newton_impl.h:81
virtual bool init(SmartPtr< IOperator< vector_type > > N)
This operator inverts the Operator N: Y -> X.
Definition newton_impl.h:152
int num_linsolver_steps(size_t call) const
Definition newton_impl.h:423
void write_debug(const vector_type &vec, std::string filename)
Definition newton_impl.h:469
TAlgebra::matrix_type matrix_type
Matrix type.
Definition newton.h:74
double total_average_linear_steps() const
Definition newton_impl.h:453
virtual std::string config_string() const
returns information about configuration parameters
Definition newton_impl.h:491
double average_linear_steps(size_t call) const
Definition newton_impl.h:429
TAlgebra::vector_type vector_type
Vector type.
Definition newton.h:71
SmartPtr< AssembledOperator< algebra_type > > m_N
assembling routine
Definition newton.h:203
void print_average_convergence() const
prints average linear solver convergence
Definition newton_impl.h:381
size_t num_newton_steps() const
Definition newton_impl.h:411
void set_convergence_check(SmartPtr< IConvergenceCheck< vector_type > > spConvCheck)
sets the convergence check
Definition newton_impl.h:143
SmartPtr< IAssemble< TAlgebra > > m_spAss
assembling
Definition newton.h:207
int num_linsolver_calls(size_t call) const
Definition newton_impl.h:417
int total_linsolver_steps() const
Definition newton_impl.h:444
Definition convergence_check.h:179
virtual void init()
const NullSmartPtr SPNULL
The equivalent to NULL for smart pointers.
Definition smart_pointer.h:90
#define UG_CATCH_THROW(msg)
Definition error.h:64
#define UG_THROW(msg)
Definition error.h:57
#define UG_LOG(msg)
Definition log.h:367
double number
Definition types.h:124
the ug namespace
string ConfigShift(string s)
Definition string_util.cpp:457
#define NEWTON_PROFILE_END()
Definition newton_impl.h:50
#define NEWTON_PROFILE_BEGIN(name)
Definition newton_impl.h:49
SmartPtr< T, FreePolicy > make_sp(T *inst)
returns a SmartPtr for the passed raw pointer
Definition smart_pointer.h:836