30 #ifndef RYTHMOS_TIME_STEP_NONLINEAR_SOLVER_DEF_HPP
31 #define RYTHMOS_TIME_STEP_NONLINEAR_SOLVER_DEF_HPP
33 #include "Rythmos_TimeStepNonlinearSolver_decl.hpp"
35 #include "Thyra_TestingTools.hpp"
36 #include "Thyra_ModelEvaluatorHelpers.hpp"
37 #include "Teuchos_VerboseObjectParameterListHelpers.hpp"
38 #include "Teuchos_StandardParameterEntryValidators.hpp"
39 #include "Teuchos_as.hpp"
51 template<
class Scalar>
53 TimeStepNonlinearSolver<Scalar>::DefaultTol_name_ =
"Default Tol";
55 template<
class Scalar>
57 TimeStepNonlinearSolver<Scalar>::DefaultTol_default_ = 1e-2;
60 template<
class Scalar>
62 TimeStepNonlinearSolver<Scalar>::DefaultMaxIters_name_ =
"Default Max Iters";
64 template<
class Scalar>
66 TimeStepNonlinearSolver<Scalar>::DefaultMaxIters_default_ = 3;
69 template<
class Scalar>
71 TimeStepNonlinearSolver<Scalar>::NonlinearSafetyFactor_name_
72 =
"Nonlinear Safety Factor";
74 template<
class Scalar>
76 TimeStepNonlinearSolver<Scalar>::NonlinearSafetyFactor_default_ = 0.1;
79 template<
class Scalar>
81 TimeStepNonlinearSolver<Scalar>::LinearSafetyFactor_name_ =
"Linear Safety Factor";
83 template<
class Scalar>
85 TimeStepNonlinearSolver<Scalar>::LinearSafetyFactor_default_ = 0.05;
88 template<
class Scalar>
90 TimeStepNonlinearSolver<Scalar>::RMinFraction_name_ =
"R Min Fraction";
92 template<
class Scalar>
94 TimeStepNonlinearSolver<Scalar>::RMinFraction_default_ = 0.3;
97 template<
class Scalar>
99 TimeStepNonlinearSolver<Scalar>::ThrownOnLinearSolveFailure_name_
100 =
"Thrown on Linear Solve Failure";
102 template<
class Scalar>
104 TimeStepNonlinearSolver<Scalar>::ThrownOnLinearSolveFailure_default_ =
false;
110 template <
class Scalar>
112 :J_is_current_(false),
113 defaultTol_(DefaultTol_default_),
114 defaultMaxIters_(DefaultMaxIters_default_),
115 nonlinearSafetyFactor_(NonlinearSafetyFactor_default_),
116 linearSafetyFactor_(LinearSafetyFactor_default_),
117 RMinFraction_(RMinFraction_default_),
118 throwOnLinearSolveFailure_(ThrownOnLinearSolveFailure_default_)
125 template<
class Scalar>
127 RCP<ParameterList>
const& paramList
131 TEUCHOS_TEST_FOR_EXCEPT(is_null(paramList));
132 paramList->validateParametersAndSetDefaults(*getValidParameters(),0);
133 paramList_ = paramList;
134 defaultTol_ = get<double>(*paramList_,DefaultTol_name_);
135 defaultMaxIters_ = get<int>(*paramList_,DefaultMaxIters_name_);
136 nonlinearSafetyFactor_ = get<double>(*paramList_,NonlinearSafetyFactor_name_);
137 linearSafetyFactor_ = get<double>(*paramList_,LinearSafetyFactor_name_);
138 RMinFraction_ = get<double>(*paramList_,RMinFraction_name_);
139 throwOnLinearSolveFailure_ = get<bool>(
140 *paramList_,ThrownOnLinearSolveFailure_name_);
141 Teuchos::readVerboseObjectSublist(&*paramList_,
this);
142 #ifdef HAVE_RYTHMOS_DEBUG
143 paramList_->validateParameters(*getValidParameters(),0);
144 #endif // HAVE_RYTHMOS_DEBUG
148 template<
class Scalar>
156 template<
class Scalar>
160 RCP<ParameterList> _paramList = paramList_;
161 paramList_ = Teuchos::null;
166 template<
class Scalar>
167 RCP<const ParameterList>
174 template<
class Scalar>
175 RCP<const ParameterList>
178 using Teuchos::setDoubleParameter;
using Teuchos::setIntParameter;
179 static RCP<const ParameterList> validPL;
180 if (is_null(validPL)) {
181 RCP<ParameterList> pl = Teuchos::parameterList();
183 DefaultTol_name_, DefaultTol_default_,
184 "The default base tolerance for the nonlinear timestep solve.\n"
185 "This tolerance can be overridden ???",
188 DefaultMaxIters_name_, DefaultMaxIters_default_,
189 "The default maximum number of Newton iterations to perform.\n"
190 "This default can be overridden ???",
193 NonlinearSafetyFactor_name_, NonlinearSafetyFactor_default_,
194 "The factor (< 1.0) to multiply tol to bound R*||dx|||.\n"
195 "The exact nonlinear convergence test is:\n"
196 " R*||dx|| <= \"" + NonlinearSafetyFactor_name_ +
"\" * tol.",
199 LinearSafetyFactor_name_, LinearSafetyFactor_default_,
200 "This factor multiplies the nonlinear safety factor which multiplies\n"
201 "tol when determining the linear solve tolerence.\n"
202 "The exact linear convergence tolerance is:\n"
203 " ||J*dx+f||/||f|| <= \"" + LinearSafetyFactor_name_ +
"\" * "
204 "\"" + NonlinearSafetyFactor_name_ +
"\" * tol.",
207 RMinFraction_name_, RMinFraction_default_,
208 "The faction below which the R factor is not allowed to drop\n"
209 "below each Newton iteration. The R factor is related to the\n"
210 "ratio of ||dx||/||dx_last|| between nonlinear iterations.",
213 ThrownOnLinearSolveFailure_name_, ThrownOnLinearSolveFailure_default_,
214 "If set to true (\"1\"), then an Thyra::CatastrophicSolveFailure\n"
215 "exception will be thrown when a linear solve fails to meet it's tolerance."
217 Teuchos::setupVerboseObjectSublist(&*pl);
227 template <
class Scalar>
229 const RCP<
const Thyra::ModelEvaluator<Scalar> > &model
232 TEUCHOS_TEST_FOR_EXCEPT(model.get()==NULL);
235 current_x_ = Teuchos::null;
236 J_is_current_ =
false;
240 template <
class Scalar>
241 RCP<const Thyra::ModelEvaluator<Scalar> >
247 template <
class Scalar>
248 Thyra::SolveStatus<Scalar>
250 Thyra::VectorBase<Scalar> *x,
251 const Thyra::SolveCriteria<Scalar> *solveCriteria,
252 Thyra::VectorBase<Scalar> *delta
256 RYTHMOS_FUNC_TIME_MONITOR(
"Rythmos:TimeStepNonlinearSolver::solve");
259 using Teuchos::incrVerbLevel;
260 using Teuchos::describe;
263 using Teuchos::OSTab;
264 using Teuchos::getFancyOStream;
265 typedef Thyra::ModelEvaluatorBase MEB;
266 typedef Teuchos::VerboseObjectTempState<MEB> VOTSME;
267 typedef Thyra::LinearOpWithSolveBase<Scalar> LOWSB;
268 typedef Teuchos::VerboseObjectTempState<LOWSB> VOTSLOWSB;
270 #ifdef HAVE_RYTHMOS_DEBUG
271 TEUCHOS_TEST_FOR_EXCEPT(0==x);
272 THYRA_ASSERT_VEC_SPACES(
273 "TimeStepNonlinearSolver<Scalar>::solve(...)",
274 *x->space(),*model_->get_x_space() );
275 TEUCHOS_TEST_FOR_EXCEPT(
276 0!=solveCriteria &&
"ToDo: Support passed in solve criteria!" );
281 const RCP<Teuchos::FancyOStream> out = this->getOStream();
282 const Teuchos::EVerbosityLevel verbLevel = this->getVerbLevel();
283 const bool showNewtonDetails =
284 (!is_null(out) && (as<int>(verbLevel) >= as<int>(Teuchos::VERB_MEDIUM)));
286 (!is_null(out) && (as<int>(verbLevel) == as<int>(Teuchos::VERB_EXTREME)));
288 VOTSME stateModel_outputTempState(model_,out,incrVerbLevel(verbLevel,-1));
290 if (showNewtonDetails)
292 <<
"\nEntering TimeStepNonlinearSolver::solve(...) ...\n"
293 <<
"\nmodel = " << Teuchos::describe(*model_,verbLevel);
296 *out <<
"\nInitial guess:\n";
297 *out <<
"\nx = " << *x;
301 if(!J_.get()) J_ = model_->create_W();
302 TEUCHOS_TEST_FOR_EXCEPTION( Teuchos::is_null(J_), std::logic_error,
303 "Error! model->create_W() returned a null pointer!\n"
305 RCP<Thyra::VectorBase<Scalar> > f = createMember(model_->get_f_space());
306 RCP<Thyra::VectorBase<Scalar> > dx = createMember(model_->get_x_space());
307 RCP<Thyra::VectorBase<Scalar> > dx_last = createMember(model_->get_x_space());
308 RCP<Thyra::VectorBase<Scalar> > x_curr = createMember(model_->get_x_space());
310 Thyra::V_S(ptr(delta),ST::zero());
311 Thyra::assign(x_curr.ptr(),*x);
312 J_is_current_ =
false;
313 current_x_ = Teuchos::null;
317 ScalarMag linearTolSafety = linearSafetyFactor_ * nonlinearSafetyFactor_;
318 int maxIters = defaultMaxIters_;
323 bool converged =
false;
324 bool sawFailedLinearSolve =
false;
325 Thyra::SolveStatus<Scalar> failedLinearSolveStatus;
329 for( ; iter <= maxIters; ++iter ) {
330 if (showNewtonDetails)
331 *out <<
"\n*** newtonIter = " << iter << endl;
332 if (showNewtonDetails)
333 *out <<
"\nEvaluating the model f and W ...\n";
334 Thyra::eval_f_W( *model_, *x_curr, &*f, &*J_ );
335 if (showNewtonDetails)
336 *out <<
"\nSolving the system J*dx = -f ...\n";
337 Thyra::V_S(dx.ptr(),ST::zero());
338 Thyra::SolveCriteria<Scalar>
340 Thyra::SolveMeasureType(
341 Thyra::SOLVE_MEASURE_NORM_RESIDUAL, Thyra::SOLVE_MEASURE_NORM_RHS
345 VOTSLOWSB J_outputTempState(J_,out,incrVerbLevel(verbLevel,-1));
346 Thyra::SolveStatus<Scalar> linearSolveStatus
347 = J_->solve(Thyra::NOTRANS, *f, dx.ptr(), Teuchos::ptr(&linearSolveCriteria) );
348 if (showNewtonDetails)
349 *out <<
"\nLinear solve status:\n" << linearSolveStatus;
350 Thyra::Vt_S(dx.ptr(),Scalar(-ST::one()));
352 *out <<
"\ndx = " << Teuchos::describe(*dx,verbLevel);
354 Thyra::Vp_V(ptr(delta),*dx);
356 *out <<
"\ndelta = " << Teuchos::describe(*delta,verbLevel);
359 if(linearSolveStatus.solveStatus != Thyra::SOLVE_STATUS_CONVERGED) {
360 sawFailedLinearSolve =
true;
361 failedLinearSolveStatus = linearSolveStatus;
362 if (throwOnLinearSolveFailure_) {
363 TEUCHOS_TEST_FOR_EXCEPTION(
364 throwOnLinearSolveFailure_, Thyra::CatastrophicSolveFailure,
365 "Error, the linear solver did not converge!"
368 if (showNewtonDetails)
369 *out <<
"\nWarning, linear solve did not converge! Continuing anyway :-)\n";
372 Vp_V( x_curr.ptr(), *dx );
374 *out <<
"\nUpdated solution x = " << Teuchos::describe(*x_curr,verbLevel);
376 nrm_dx = Thyra::norm(*dx);
377 if ( R*nrm_dx <= nonlinearSafetyFactor_*tol )
379 if (showNewtonDetails)
381 <<
"\nConvergence test:\n"
382 <<
" R*||dx|| = " << R <<
"*" << nrm_dx
383 <<
" = " << (R*nrm_dx) <<
"\n"
384 <<
" <= nonlinearSafetyFactor*tol = " << nonlinearSafetyFactor_ <<
"*" << tol
385 <<
" = " << (nonlinearSafetyFactor_*tol)
386 <<
" : " << ( converged ?
"converged!" :
" unconverged" )
393 MinR = RMinFraction_*R,
394 nrm_dx_ratio = nrm_dx/nrm_dx_last;
395 R = std::max(MinR,nrm_dx_ratio);
396 if (showNewtonDetails)
399 <<
" = max(RMinFraction*R,||dx||/||dx_last||)\n"
400 <<
" = max("<<RMinFraction_<<
"*"<<R<<
","<<nrm_dx<<
"/"<<nrm_dx_last<<
")\n"
401 <<
" = max("<<MinR<<
","<<nrm_dx_ratio<<
")\n"
402 <<
" = " << R << endl;
405 std::swap(dx_last,dx);
406 nrm_dx_last = nrm_dx;
410 Thyra::assign(ptr(x),*x_curr);
413 *out <<
"\nFinal solution x = " << Teuchos::describe(*x,verbLevel);
417 Thyra::SolveStatus<Scalar> solveStatus;
419 std::ostringstream oss;
420 Teuchos::FancyOStream omsg(rcp(&oss,
false));
422 omsg <<
"Solver: " << this->description() << endl;
425 solveStatus.solveStatus = Thyra::SOLVE_STATUS_CONVERGED;
426 omsg <<
"CVODE status test converged!\n";
429 solveStatus.solveStatus = Thyra::SOLVE_STATUS_UNCONVERGED;
430 omsg <<
"CVODE status test failed!\n";
433 if (sawFailedLinearSolve) {
434 omsg <<
"Warning! A failed linear solve was encountered with status:\n";
436 omsg << failedLinearSolveStatus;
440 <<
"R*||dx|| = " << R <<
"*" << nrm_dx
441 <<
" <= nonlinearSafetyFactor*tol = " << nonlinearSafetyFactor_ <<
"*" << tol <<
" : "
442 << ( converged ?
"converged!" :
" unconverged" ) << endl;
445 <<
"Iterations = " << iter;
449 solveStatus.message = oss.str();
452 current_x_ = x->clone_v();
453 J_is_current_ =
false;
459 if (showNewtonDetails)
460 *out <<
"\nLeaving TimeStepNonlinearSolver::solve(...) ...\n";
467 template <
class Scalar>
474 template <
class Scalar>
475 RCP<Thyra::NonlinearSolverBase<Scalar> >
478 RCP<TimeStepNonlinearSolver<Scalar> >
480 nonlinearSolver->model_ = model_;
481 nonlinearSolver->defaultTol_ = defaultTol_;
482 nonlinearSolver->defaultMaxIters_ = defaultMaxIters_;
483 nonlinearSolver->nonlinearSafetyFactor_ = nonlinearSafetyFactor_;
484 nonlinearSolver->linearSafetyFactor_ = linearSafetyFactor_;
485 nonlinearSolver->RMinFraction_ = RMinFraction_;
486 nonlinearSolver->throwOnLinearSolveFailure_ = throwOnLinearSolveFailure_;
490 return nonlinearSolver;
494 template <
class Scalar>
495 RCP<const Thyra::VectorBase<Scalar> >
502 template <
class Scalar>
505 return J_is_current_;
509 template <
class Scalar>
510 RCP<Thyra::LinearOpWithSolveBase<Scalar> >
514 return Teuchos::null;
516 #ifdef HAVE_RYTHMOS_DEBUG
517 TEUCHOS_TEST_FOR_EXCEPT(is_null(current_x_));
519 Thyra::eval_f_W<Scalar>( *model_, *current_x_, 0, &*J_ );
520 J_is_current_ =
true;
526 template <
class Scalar>
527 RCP<const Thyra::LinearOpWithSolveBase<Scalar> >
534 template <
class Scalar>
537 J_is_current_ = W_is_current;
547 template <
class Scalar>
548 Teuchos::RCP<Rythmos::TimeStepNonlinearSolver<Scalar> >
549 Rythmos::timeStepNonlinearSolver()
551 return Teuchos::rcp(
new TimeStepNonlinearSolver<Scalar>);
555 template <
class Scalar>
556 Teuchos::RCP<Rythmos::TimeStepNonlinearSolver<Scalar> >
557 Rythmos::timeStepNonlinearSolver(
const RCP<ParameterList> &pl)
559 const RCP<Rythmos::TimeStepNonlinearSolver<Scalar> >
560 solver = timeStepNonlinearSolver<Scalar>();
561 solver->setParameterList(pl);
572 #define RYTHMOS_TIME_STEP_NONLINEAR_SOLVER_INSTANT(SCALAR) \
574 template class TimeStepNonlinearSolver< SCALAR >; \
576 template RCP<TimeStepNonlinearSolver< SCALAR > > timeStepNonlinearSolver(); \
578 template RCP<TimeStepNonlinearSolver<SCALAR > > \
579 timeStepNonlinearSolver(const RCP<ParameterList> &pl);
583 #endif // RYTHMOS_TIME_STEP_NONLINEAR_SOLVER_DEF_HPP
Simple undampended Newton solver designed to solve time step equations in accurate times-tepping meth...
RCP< const Thyra::LinearOpWithSolveBase< Scalar > > get_W() const
RCP< ParameterList > getNonconstParameterList()
void setModel(const RCP< const Thyra::ModelEvaluator< Scalar > > &model)
RCP< const Thyra::VectorBase< Scalar > > get_current_x() const
void set_W_is_current(bool W_is_current)
bool is_W_current() const
RCP< ParameterList > unsetParameterList()
ST::magnitudeType ScalarMag
RCP< const Thyra::ModelEvaluator< Scalar > > getModel() const
RCP< Thyra::NonlinearSolverBase< Scalar > > cloneNonlinearSolver() const
Thyra::SolveStatus< Scalar > solve(Thyra::VectorBase< Scalar > *x, const Thyra::SolveCriteria< Scalar > *solveCriteria, Thyra::VectorBase< Scalar > *delta=NULL)
RCP< const ParameterList > getParameterList() const
RCP< Thyra::LinearOpWithSolveBase< Scalar > > get_nonconst_W(const bool forceUpToDate)
RCP< const ParameterList > getValidParameters() const
void setParameterList(RCP< ParameterList > const ¶mList)
bool supportsCloning() const
TimeStepNonlinearSolver()
Sets parameter defaults .