|
Rythmos - Transient Integration for Differential Equations Version of the Day
|
00001 //@HEADER 00002 // *********************************************************************** 00003 // 00004 // Rythmos Package 00005 // Copyright (2006) Sandia Corporation 00006 // 00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive 00008 // license for use of this work by or on behalf of the U.S. Government. 00009 // 00010 // This library is free software; you can redistribute it and/or modify 00011 // it under the terms of the GNU Lesser General Public License as 00012 // published by the Free Software Foundation; either version 2.1 of the 00013 // License, or (at your option) any later version. 00014 // 00015 // This library is distributed in the hope that it will be useful, but 00016 // WITHOUT ANY WARRANTY; without even the implied warranty of 00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00018 // Lesser General Public License for more details. 00019 // 00020 // You should have received a copy of the GNU Lesser General Public 00021 // License along with this library; if not, write to the Free Software 00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 00023 // USA 00024 // Questions? Contact Todd S. Coffey (tscoffe@sandia.gov) 00025 // 00026 // *********************************************************************** 00027 //@HEADER 00028 00029 00030 #ifndef RYTHMOS_TIME_STEP_NONLINEAR_SOLVER_DEF_HPP 00031 #define RYTHMOS_TIME_STEP_NONLINEAR_SOLVER_DEF_HPP 00032 00033 #include "Rythmos_TimeStepNonlinearSolver_decl.hpp" 00034 00035 #include "Thyra_TestingTools.hpp" 00036 #include "Thyra_ModelEvaluatorHelpers.hpp" 00037 #include "Teuchos_VerboseObjectParameterListHelpers.hpp" 00038 #include "Teuchos_StandardParameterEntryValidators.hpp" 00039 #include "Teuchos_as.hpp" 00040 00041 namespace Rythmos { 00042 00043 00044 // //////////////////////// 00045 // Defintions 00046 00047 00048 // Static members 00049 00050 00051 template<class Scalar> 00052 const std::string 00053 TimeStepNonlinearSolver<Scalar>::DefaultTol_name_ = "Default Tol"; 00054 00055 template<class Scalar> 00056 const double 00057 TimeStepNonlinearSolver<Scalar>::DefaultTol_default_ = 1e-2; 00058 00059 00060 template<class Scalar> 00061 const std::string 00062 TimeStepNonlinearSolver<Scalar>::DefaultMaxIters_name_ = "Default Max Iters"; 00063 00064 template<class Scalar> 00065 const int 00066 TimeStepNonlinearSolver<Scalar>::DefaultMaxIters_default_ = 3; 00067 00068 00069 template<class Scalar> 00070 const std::string 00071 TimeStepNonlinearSolver<Scalar>::NonlinearSafetyFactor_name_ 00072 = "Nonlinear Safety Factor"; 00073 00074 template<class Scalar> 00075 const double 00076 TimeStepNonlinearSolver<Scalar>::NonlinearSafetyFactor_default_ = 0.1; 00077 00078 00079 template<class Scalar> 00080 const std::string 00081 TimeStepNonlinearSolver<Scalar>::LinearSafetyFactor_name_ = "Linear Safety Factor"; 00082 00083 template<class Scalar> 00084 const double 00085 TimeStepNonlinearSolver<Scalar>::LinearSafetyFactor_default_ = 0.05; 00086 00087 00088 template<class Scalar> 00089 const std::string 00090 TimeStepNonlinearSolver<Scalar>::RMinFraction_name_ = "R Min Fraction"; 00091 00092 template<class Scalar> 00093 const double 00094 TimeStepNonlinearSolver<Scalar>::RMinFraction_default_ = 0.3; 00095 00096 00097 template<class Scalar> 00098 const std::string 00099 TimeStepNonlinearSolver<Scalar>::ThrownOnLinearSolveFailure_name_ 00100 = "Thrown on Linear Solve Failure"; 00101 00102 template<class Scalar> 00103 const bool 00104 TimeStepNonlinearSolver<Scalar>::ThrownOnLinearSolveFailure_default_ = false; 00105 00106 00107 // Constructors/Intializers/Misc 00108 00109 00110 template <class Scalar> 00111 TimeStepNonlinearSolver<Scalar>::TimeStepNonlinearSolver() 00112 :J_is_current_(false), 00113 defaultTol_(DefaultTol_default_), 00114 defaultMaxIters_(DefaultMaxIters_default_), 00115 nonlinearSafetyFactor_(NonlinearSafetyFactor_default_), 00116 linearSafetyFactor_(LinearSafetyFactor_default_), 00117 RMinFraction_(RMinFraction_default_), 00118 throwOnLinearSolveFailure_(ThrownOnLinearSolveFailure_default_) 00119 {} 00120 00121 00122 // Overridden from ParameterListAcceptor 00123 00124 00125 template<class Scalar> 00126 void TimeStepNonlinearSolver<Scalar>::setParameterList( 00127 RCP<ParameterList> const& paramList 00128 ) 00129 { 00130 using Teuchos::get; 00131 TEST_FOR_EXCEPT(is_null(paramList)); 00132 paramList->validateParametersAndSetDefaults(*getValidParameters(),0); 00133 paramList_ = paramList; 00134 defaultTol_ = get<double>(*paramList_,DefaultTol_name_); 00135 defaultMaxIters_ = get<int>(*paramList_,DefaultMaxIters_name_); 00136 nonlinearSafetyFactor_ = get<double>(*paramList_,NonlinearSafetyFactor_name_); 00137 linearSafetyFactor_ = get<double>(*paramList_,LinearSafetyFactor_name_); 00138 RMinFraction_ = get<double>(*paramList_,RMinFraction_name_); 00139 throwOnLinearSolveFailure_ = get<bool>( 00140 *paramList_,ThrownOnLinearSolveFailure_name_); 00141 Teuchos::readVerboseObjectSublist(&*paramList_,this); 00142 #ifdef RYTHMOS_DEBUG 00143 paramList_->validateParameters(*getValidParameters(),0); 00144 #endif // RYTHMOS_DEBUG 00145 } 00146 00147 00148 template<class Scalar> 00149 RCP<ParameterList> 00150 TimeStepNonlinearSolver<Scalar>::getNonconstParameterList() 00151 { 00152 return paramList_; 00153 } 00154 00155 00156 template<class Scalar> 00157 RCP<ParameterList> 00158 TimeStepNonlinearSolver<Scalar>::unsetParameterList() 00159 { 00160 RCP<ParameterList> _paramList = paramList_; 00161 paramList_ = Teuchos::null; 00162 return _paramList; 00163 } 00164 00165 00166 template<class Scalar> 00167 RCP<const ParameterList> 00168 TimeStepNonlinearSolver<Scalar>::getParameterList() const 00169 { 00170 return paramList_; 00171 } 00172 00173 00174 template<class Scalar> 00175 RCP<const ParameterList> 00176 TimeStepNonlinearSolver<Scalar>::getValidParameters() const 00177 { 00178 using Teuchos::setDoubleParameter; using Teuchos::setIntParameter; 00179 static RCP<const ParameterList> validPL; 00180 if (is_null(validPL)) { 00181 RCP<ParameterList> pl = Teuchos::parameterList(); 00182 setDoubleParameter( 00183 DefaultTol_name_, DefaultTol_default_, 00184 "The default base tolerance for the nonlinear timestep solve.\n" 00185 "This tolerance can be overridden ???", 00186 &*pl ); 00187 setIntParameter( 00188 DefaultMaxIters_name_, DefaultMaxIters_default_, 00189 "The default maximum number of Newton iterations to perform.\n" 00190 "This default can be overridden ???", 00191 &*pl ); 00192 setDoubleParameter( 00193 NonlinearSafetyFactor_name_, NonlinearSafetyFactor_default_, 00194 "The factor (< 1.0) to multiply tol to bound R*||dx|||.\n" 00195 "The exact nonlinear convergence test is:\n" 00196 " R*||dx|| <= \"" + NonlinearSafetyFactor_name_ + "\" * tol.", 00197 &*pl ); 00198 setDoubleParameter( 00199 LinearSafetyFactor_name_, LinearSafetyFactor_default_, 00200 "This factor multiplies the nonlinear safety factor which multiplies\n" 00201 "tol when determining the linear solve tolerence.\n" 00202 "The exact linear convergence tolerance is:\n" 00203 " ||J*dx+f||/||f|| <= \"" + LinearSafetyFactor_name_ + "\" * " 00204 "\"" + NonlinearSafetyFactor_name_ + "\" * tol.", 00205 &*pl ); 00206 setDoubleParameter( 00207 RMinFraction_name_, RMinFraction_default_, 00208 "The faction below which the R factor is not allowed to drop\n" 00209 "below each Newton iteration. The R factor is related to the\n" 00210 "ratio of ||dx||/||dx_last|| between nonlinear iterations.", 00211 &*pl ); 00212 pl->set( 00213 ThrownOnLinearSolveFailure_name_, ThrownOnLinearSolveFailure_default_, 00214 "If set to true (\"1\"), then an Thyra::CatastrophicSolveFailure\n" 00215 "exception will be thrown when a linear solve fails to meet it's tolerance." 00216 ); 00217 Teuchos::setupVerboseObjectSublist(&*pl); 00218 validPL = pl; 00219 } 00220 return validPL; 00221 } 00222 00223 00224 // Overridden from NonlinearSolverBase 00225 00226 00227 template <class Scalar> 00228 void TimeStepNonlinearSolver<Scalar>::setModel( 00229 const RCP<const Thyra::ModelEvaluator<Scalar> > &model 00230 ) 00231 { 00232 TEST_FOR_EXCEPT(model.get()==NULL); 00233 model_ = model; 00234 J_ = Teuchos::null; 00235 current_x_ = Teuchos::null; 00236 J_is_current_ = false; 00237 } 00238 00239 00240 template <class Scalar> 00241 RCP<const Thyra::ModelEvaluator<Scalar> > 00242 TimeStepNonlinearSolver<Scalar>::getModel() const 00243 { 00244 return model_; 00245 } 00246 00247 template <class Scalar> 00248 Thyra::SolveStatus<Scalar> 00249 TimeStepNonlinearSolver<Scalar>::solve( 00250 Thyra::VectorBase<Scalar> *x, 00251 const Thyra::SolveCriteria<Scalar> *solveCriteria, 00252 Thyra::VectorBase<Scalar> *delta 00253 ) 00254 { 00255 00256 #ifdef ENABLE_RYTHMOS_TIMERS 00257 TEUCHOS_FUNC_TIME_MONITOR("Rythmos:TimeStepNonlinearSolver::solve"); 00258 #endif 00259 00260 using std::endl; 00261 using Teuchos::incrVerbLevel; 00262 using Teuchos::describe; 00263 using Teuchos::as; 00264 using Teuchos::rcp; 00265 using Teuchos::OSTab; 00266 using Teuchos::getFancyOStream; 00267 typedef Thyra::ModelEvaluatorBase MEB; 00268 typedef Teuchos::VerboseObjectTempState<MEB> VOTSME; 00269 typedef Thyra::LinearOpWithSolveBase<Scalar> LOWSB; 00270 typedef Teuchos::VerboseObjectTempState<LOWSB> VOTSLOWSB; 00271 00272 #ifdef RYTHMOS_DEBUG 00273 TEST_FOR_EXCEPT(0==x); 00274 THYRA_ASSERT_VEC_SPACES( 00275 "TimeStepNonlinearSolver<Scalar>::solve(...)", 00276 *x->space(),*model_->get_x_space() ); 00277 TEST_FOR_EXCEPT( 00278 0!=solveCriteria && "ToDo: Support passed in solve criteria!" ); 00279 #endif 00280 00281 const RCP<Teuchos::FancyOStream> out = this->getOStream(); 00282 const Teuchos::EVerbosityLevel verbLevel = this->getVerbLevel(); 00283 const bool showNewtonDetails = 00284 (!is_null(out) && (as<int>(verbLevel) >= as<int>(Teuchos::VERB_MEDIUM))); 00285 const bool dumpAll = 00286 (!is_null(out) && (as<int>(verbLevel) == as<int>(Teuchos::VERB_EXTREME))); 00287 TEUCHOS_OSTAB; 00288 VOTSME stateModel_outputTempState(model_,out,incrVerbLevel(verbLevel,-1)); 00289 00290 if (showNewtonDetails) 00291 *out 00292 << "\nEntering TimeStepNonlinearSolver::solve(...) ...\n" 00293 << "\nmodel = " << Teuchos::describe(*model_,verbLevel); 00294 00295 if(dumpAll) { 00296 *out << "\nInitial guess:\n"; 00297 *out << "\nx = " << *x; 00298 } 00299 00300 // Initialize storage for algorithm 00301 if(!J_.get()) J_ = model_->create_W(); 00302 TEST_FOR_EXCEPTION( Teuchos::is_null(J_), std::logic_error, 00303 "Error! model->create_W() returned a null pointer!\n" 00304 ); 00305 RCP<Thyra::VectorBase<Scalar> > f = createMember(model_->get_f_space()); 00306 RCP<Thyra::VectorBase<Scalar> > dx = createMember(model_->get_x_space()); 00307 RCP<Thyra::VectorBase<Scalar> > dx_last = createMember(model_->get_x_space()); 00308 RCP<Thyra::VectorBase<Scalar> > x_curr = createMember(model_->get_x_space()); 00309 if (delta != NULL) 00310 Thyra::V_S(ptr(delta),ST::zero()); // delta stores the cumulative update to x over the whole Newton solve. 00311 Thyra::assign(x_curr.ptr(),*x); 00312 J_is_current_ = false; 00313 current_x_ = Teuchos::null; 00314 00315 // Initialize convergence criteria 00316 ScalarMag R = SMT::one(); 00317 ScalarMag linearTolSafety = linearSafetyFactor_ * nonlinearSafetyFactor_; 00318 int maxIters = defaultMaxIters_; 00319 ScalarMag tol = defaultTol_; 00320 // ToDo: Get above from solveCriteria! 00321 00322 // Do the undampened Newton iterations 00323 bool converged = false; 00324 bool sawFailedLinearSolve = false; 00325 Thyra::SolveStatus<Scalar> failedLinearSolveStatus; 00326 ScalarMag nrm_dx = SMT::nan(); 00327 ScalarMag nrm_dx_last = SMT::nan(); 00328 int iter = 1; 00329 for( ; iter <= maxIters; ++iter ) { 00330 if (showNewtonDetails) 00331 *out << "\n*** newtonIter = " << iter << endl; 00332 if (showNewtonDetails) 00333 *out << "\nEvaluating the model f and W ...\n"; 00334 Thyra::eval_f_W( *model_, *x_curr, &*f, &*J_ ); 00335 if (showNewtonDetails) 00336 *out << "\nSolving the system J*dx = -f ...\n"; 00337 Thyra::V_S(dx.ptr(),ST::zero()); // Initial guess is needed! 00338 Thyra::SolveCriteria<Scalar> 00339 linearSolveCriteria( 00340 Thyra::SolveMeasureType( 00341 Thyra::SOLVE_MEASURE_NORM_RESIDUAL, Thyra::SOLVE_MEASURE_NORM_RHS 00342 ), 00343 linearTolSafety*tol 00344 ); 00345 VOTSLOWSB J_outputTempState(J_,out,incrVerbLevel(verbLevel,-1)); 00346 Thyra::SolveStatus<Scalar> linearSolveStatus 00347 = J_->solve(Thyra::NOTRANS, *f, dx.ptr(), Teuchos::ptr(&linearSolveCriteria) ); 00348 if (showNewtonDetails) 00349 *out << "\nLinear solve status:\n" << linearSolveStatus; 00350 Thyra::Vt_S(dx.ptr(),Scalar(-ST::one())); 00351 if (dumpAll) 00352 *out << "\ndx = " << Teuchos::describe(*dx,verbLevel); 00353 if (delta != NULL) { 00354 Thyra::Vp_V(ptr(delta),*dx); 00355 if (dumpAll) 00356 *out << "\ndelta = " << Teuchos::describe(*delta,verbLevel); 00357 } 00358 // Check the linear solve 00359 if(linearSolveStatus.solveStatus != Thyra::SOLVE_STATUS_CONVERGED) { 00360 sawFailedLinearSolve = true; 00361 failedLinearSolveStatus = linearSolveStatus; 00362 if (throwOnLinearSolveFailure_) { 00363 TEST_FOR_EXCEPTION( 00364 throwOnLinearSolveFailure_, Thyra::CatastrophicSolveFailure, 00365 "Error, the linear solver did not converge!" 00366 ); 00367 } 00368 if (showNewtonDetails) 00369 *out << "\nWarning, linear solve did not converge! Continuing anyway :-)\n"; 00370 } 00371 // Update the solution: x_curr = x_curr + dx 00372 Vp_V( x_curr.ptr(), *dx ); 00373 if (dumpAll) 00374 *out << "\nUpdated solution x = " << Teuchos::describe(*x_curr,verbLevel); 00375 // Convergence test 00376 nrm_dx = Thyra::norm(*dx); 00377 if ( R*nrm_dx <= nonlinearSafetyFactor_*tol ) 00378 converged = true; 00379 if (showNewtonDetails) 00380 *out 00381 << "\nConvergence test:\n" 00382 << " R*||dx|| = " << R << "*" << nrm_dx 00383 << " = " << (R*nrm_dx) << "\n" 00384 << " <= nonlinearSafetyFactor*tol = " << nonlinearSafetyFactor_ << "*" << tol 00385 << " = " << (nonlinearSafetyFactor_*tol) 00386 << " : " << ( converged ? "converged!" : " unconverged" ) 00387 << endl; 00388 if(converged) 00389 break; // We have converged!!! 00390 // Update convergence criteria for the next iteration ... 00391 if(iter > 1) { 00392 const Scalar 00393 MinR = RMinFraction_*R, 00394 nrm_dx_ratio = nrm_dx/nrm_dx_last; 00395 R = std::max(MinR,nrm_dx_ratio); 00396 if (showNewtonDetails) 00397 *out 00398 << "\nUpdated R\n" 00399 << " = max(RMinFraction*R,||dx||/||dx_last||)\n" 00400 << " = max("<<RMinFraction_<<"*"<<R<<","<<nrm_dx<<"/"<<nrm_dx_last<<")\n" 00401 << " = max("<<MinR<<","<<nrm_dx_ratio<<")\n" 00402 << " = " << R << endl; 00403 } 00404 // Save to old 00405 std::swap(dx_last,dx); 00406 nrm_dx_last = nrm_dx; 00407 } 00408 00409 // Set the solution 00410 Thyra::assign(ptr(x),*x_curr); 00411 00412 if (dumpAll) 00413 *out << "\nFinal solution x = " << Teuchos::describe(*x,verbLevel); 00414 00415 // Check the status 00416 00417 Thyra::SolveStatus<Scalar> solveStatus; 00418 00419 std::ostringstream oss; 00420 Teuchos::FancyOStream omsg(rcp(&oss,false)); 00421 00422 omsg << "Solver: " << this->description() << endl; 00423 00424 if(converged) { 00425 solveStatus.solveStatus = Thyra::SOLVE_STATUS_CONVERGED; 00426 omsg << "CVODE status test converged!\n"; 00427 } 00428 else { 00429 solveStatus.solveStatus = Thyra::SOLVE_STATUS_UNCONVERGED; 00430 omsg << "CVODE status test failed!\n"; 00431 } 00432 00433 if (sawFailedLinearSolve) { 00434 omsg << "Warning! A failed linear solve was encountered with status:\n"; 00435 OSTab tab(omsg); 00436 omsg << failedLinearSolveStatus; 00437 } 00438 00439 omsg 00440 << "R*||dx|| = " << R << "*" << nrm_dx 00441 << " <= nonlinearSafetyFactor*tol = " << nonlinearSafetyFactor_ << "*" << tol << " : " 00442 << ( converged ? "converged!" : " unconverged" ) << endl; 00443 00444 omsg 00445 << "Iterations = " << iter; 00446 // Above, we leave off the last newline since this is the convention for the 00447 // SolveStatus::message string! 00448 00449 solveStatus.message = oss.str(); 00450 00451 // Update the solution state for external clients 00452 current_x_ = x->clone_v(); 00453 J_is_current_ = false; 00454 // 2007/09/04: rabartl: Note, above the Jacobian J is always going to be out 00455 // of date since this algorithm computes x_curr = x_curr + dx for at least 00456 // one solve for dx = -inv(J)*f. Therefore, J is never at the updated 00457 // x_curr, only the old x_curr! 00458 00459 if (showNewtonDetails) 00460 *out << "\nLeaving TimeStepNonlinearSolver::solve(...) ...\n"; 00461 00462 return solveStatus; 00463 00464 } 00465 00466 00467 template <class Scalar> 00468 bool TimeStepNonlinearSolver<Scalar>::supportsCloning() const 00469 { 00470 return true; 00471 } 00472 00473 00474 template <class Scalar> 00475 RCP<Thyra::NonlinearSolverBase<Scalar> > 00476 TimeStepNonlinearSolver<Scalar>::cloneNonlinearSolver() const 00477 { 00478 RCP<TimeStepNonlinearSolver<Scalar> > 00479 nonlinearSolver = Teuchos::rcp(new TimeStepNonlinearSolver<Scalar>); 00480 nonlinearSolver->model_ = model_; // Shallow copy is okay, model is stateless 00481 nonlinearSolver->defaultTol_ = defaultTol_; 00482 nonlinearSolver->defaultMaxIters_ = defaultMaxIters_; 00483 nonlinearSolver->nonlinearSafetyFactor_ = nonlinearSafetyFactor_; 00484 nonlinearSolver->linearSafetyFactor_ = linearSafetyFactor_; 00485 nonlinearSolver->RMinFraction_ = RMinFraction_; 00486 nonlinearSolver->throwOnLinearSolveFailure_ = throwOnLinearSolveFailure_; 00487 // Note: The specification of this virtual function in the interface class 00488 // allows us to just copy the algorithm, not the entire state so we are 00489 // done! 00490 return nonlinearSolver; 00491 } 00492 00493 00494 template <class Scalar> 00495 RCP<const Thyra::VectorBase<Scalar> > 00496 TimeStepNonlinearSolver<Scalar>::get_current_x() const 00497 { 00498 return current_x_; 00499 } 00500 00501 00502 template <class Scalar> 00503 bool TimeStepNonlinearSolver<Scalar>::is_W_current() const 00504 { 00505 return J_is_current_; 00506 } 00507 00508 00509 template <class Scalar> 00510 RCP<Thyra::LinearOpWithSolveBase<Scalar> > 00511 TimeStepNonlinearSolver<Scalar>::get_nonconst_W(const bool forceUpToDate) 00512 { 00513 if (is_null(J_)) 00514 return Teuchos::null; 00515 if (forceUpToDate) { 00516 #ifdef RYTHMOS_DEBUG 00517 TEST_FOR_EXCEPT(is_null(current_x_)); 00518 #endif 00519 Thyra::eval_f_W<Scalar>( *model_, *current_x_, 0, &*J_ ); 00520 J_is_current_ = true; 00521 } 00522 return J_; 00523 } 00524 00525 00526 template <class Scalar> 00527 RCP<const Thyra::LinearOpWithSolveBase<Scalar> > 00528 TimeStepNonlinearSolver<Scalar>::get_W() const 00529 { 00530 return J_; 00531 } 00532 00533 00534 template <class Scalar> 00535 void TimeStepNonlinearSolver<Scalar>::set_W_is_current(bool W_is_current) 00536 { 00537 J_is_current_ = W_is_current; 00538 } 00539 00540 00541 } // namespace Rythmos 00542 00543 00544 // Nonmember constructors 00545 00546 00547 template <class Scalar> 00548 Teuchos::RCP<Rythmos::TimeStepNonlinearSolver<Scalar> > 00549 Rythmos::timeStepNonlinearSolver() 00550 { 00551 return Teuchos::rcp(new TimeStepNonlinearSolver<Scalar>); 00552 } 00553 00554 00555 template <class Scalar> 00556 Teuchos::RCP<Rythmos::TimeStepNonlinearSolver<Scalar> > 00557 Rythmos::timeStepNonlinearSolver(const RCP<ParameterList> &pl) 00558 { 00559 const RCP<Rythmos::TimeStepNonlinearSolver<Scalar> > 00560 solver = timeStepNonlinearSolver<Scalar>(); 00561 solver->setParameterList(pl); 00562 return solver; 00563 } 00564 00565 00566 // 00567 // Explicit Instantiation macro 00568 // 00569 // Must be expanded from within the Rythmos namespace! 00570 // 00571 00572 #define RYTHMOS_TIME_STEP_NONLINEAR_SOLVER_INSTANT(SCALAR) \ 00573 \ 00574 template class TimeStepNonlinearSolver< SCALAR >; \ 00575 \ 00576 template RCP<TimeStepNonlinearSolver< SCALAR > > timeStepNonlinearSolver(); \ 00577 \ 00578 template RCP<TimeStepNonlinearSolver<SCALAR > > \ 00579 timeStepNonlinearSolver(const RCP<ParameterList> &pl); 00580 00581 00582 00583 #endif // RYTHMOS_TIME_STEP_NONLINEAR_SOLVER_DEF_HPP
1.7.4