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 .