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);
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);
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";