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__
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()
52 #define NEWTON_PROFILE_FUNC()
53 #define NEWTON_PROFILE_BEGIN(name)
54 #define NEWTON_PROFILE_END()
59template <
typename TAlgebra>
65 m_spConvCheck(spConvCheck),
66 m_spLineSearch(spLineSearch),
70 m_reassembe_J_freq(0),
79template <
typename TAlgebra>
82 m_spLinearSolver(NULL),
88 m_reassembe_J_freq(0),
98template <
typename TAlgebra>
101 m_spLinearSolver(NULL),
103 m_spLineSearch(NULL),
107 m_reassembe_J_freq(0),
119template <
typename TAlgebra>
122 m_spLinearSolver(NULL),
124 m_spLineSearch(NULL),
128 m_reassembe_J_freq(0),
141template <
typename TAlgebra>
145 m_spConvCheck = spConvCheck;
146 m_spConvCheck->set_offset(3);
147 m_spConvCheck->set_symbol(
'#');
148 m_spConvCheck->set_name(
"Newton Solver");
151template <
typename TAlgebra>
155 m_N = N.template cast_dynamic<AssembledOperator<TAlgebra> >();
157 UG_THROW(
"NewtonSolver: currently only works for AssembledDiscreteOperator.");
159 m_spAss = m_N->discretization();
163template <
typename TAlgebra>
170template <
typename TAlgebra>
178 if(m_spLinearSolver.invalid())
179 UG_THROW(
"NewtonSolver::apply: Linear Solver not set.");
182 if(m_J.invalid() || m_J->discretization() != m_spAss) {
185 m_J->set_level(m_N->level());
195 UG_CATCH_THROW(
"NewtonSolver::prepare: Prepare of Operator failed.");
202 }
UG_CATCH_THROW(
"NewtonSolver::apply: Computation of Start-Defect failed.");
209 char debug_name_ext[20];
210 if (this->debug_writer_valid())
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");
218 const int stdLinOffset = m_spLinearSolver->standard_offset();
219 m_spLinearSolver->convergence_check()->set_offset(stdLinOffset + 3);
222 std::stringstream ss; ss <<
"(Linear Solver: " << m_spLinearSolver->name() <<
")";
223 m_spConvCheck->set_info(ss.str());
226 m_spConvCheck->start(*spD);
228 for(
size_t i = 0; i < m_stepUpdate.size(); ++i)
229 m_stepUpdate[i]->update();
232 while(!m_spConvCheck->iteration_ended())
234 m_lastNumSteps = loopCnt;
241 for(
size_t i = 0; i < m_innerStepUpdate.size(); ++i)
242 m_innerStepUpdate[i]->update();
246 if(m_reassembe_J_freq == 0 || loopCnt % m_reassembe_J_freq == 0)
252 }
UG_CATCH_THROW(
"NewtonSolver::apply: Initialization of Jacobian failed.");
255 if (this->debug_writer_valid())
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);
264 if(!m_spLinearSolver->init(m_J, u))
266 UG_LOG(
"ERROR in 'NewtonSolver::apply': Cannot init Inverse Linear "
267 "Operator for Jacobi-Operator.\n");
271 }
UG_CATCH_THROW(
"NewtonSolver::apply: Initialization of Linear Solver failed.");
276 if(!m_spLinearSolver->apply(*spC, *spD))
278 UG_LOG(
"ERROR in 'NewtonSolver::apply': Cannot apply Inverse Linear "
279 "Operator for Jacobi-Operator.\n");
283 }
UG_CATCH_THROW(
"NewtonSolver::apply: Application of Linear Solver failed.");
285 this->leave_debug_writer_section();
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();
298 if(m_spLineSearch.valid())
300 m_spLineSearch->set_offset(
" # ");
305 if( m_newtonUpdater !=
SPNULL )
306 m_spLineSearch->setNewtonUpdater(m_newtonUpdater);
309 if(!m_spLineSearch->search(m_N, u, *spC, *spD, m_spConvCheck->defect()))
311 UG_LOG(
"ERROR in 'NewtonSolver::apply': "
312 "Newton Solver did not converge.\n");
320 if( m_newtonUpdater !=
SPNULL )
324 if( ! m_newtonUpdater->updateSolution(u,*spC) )
326 UG_LOG(
"ERROR in 'NewtonSolver::apply': "
327 "Newton Update did not work.\n");
332 if( ! m_newtonUpdater->tellAndFixUpdateEvents(u) )
334 UG_LOG(
"unable to fix local Newton updates" << std::endl );
353 }
UG_CATCH_THROW(
"NewtonSolver::apply: Line Search update failed.");
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();
365 if (this->debug_writer_valid())
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);
375 m_spLinearSolver->convergence_check()->set_offset(stdLinOffset);
377 return m_spConvCheck->post();
380template <
typename TAlgebra>
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)
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]);
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));
410template <
typename TAlgebra>
413 return m_vLinSolverCalls.size();
416template <
typename TAlgebra>
419 return m_vLinSolverCalls[call];
422template <
typename TAlgebra>
425 return m_vTotalLinSolverSteps[call];
428template <
typename TAlgebra>
431 return m_vTotalLinSolverSteps[call] / ((double)m_vLinSolverCalls[call]);
434template <
typename TAlgebra>
438 for(
size_t call = 0; call < m_vLinSolverCalls.size(); ++call)
439 allCalls += m_vLinSolverCalls[call];
443template <
typename TAlgebra>
447 for(
size_t call = 0; call < m_vLinSolverCalls.size(); ++call)
448 allSteps += m_vTotalLinSolverSteps[call];
452template <
typename TAlgebra>
455 return total_linsolver_steps()/((double)total_linsolver_calls());
459template <
typename TAlgebra>
462 m_vLinSolverRates.clear();
463 m_vNonLinSolverRates.clear();
464 m_vLinSolverCalls.clear();
465 m_vTotalLinSolverSteps.clear();
468template <
typename TAlgebra>
472 char ext[20]; snprintf(ext, 20,
"_call%03d", m_dgbCall);
476 base_writer_type::write_debug(vec,
name + ext);
479template <
typename TAlgebra>
483 char ext[20]; snprintf(ext, 20,
"_call%03d", m_dgbCall);
487 base_writer_type::write_debug(mat,
name + ext);
490template <
typename TAlgebra>
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";
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
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
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