20 #include "libmesh/libmesh_common.h" 
   22 #if defined(LIBMESH_TRILINOS_HAVE_NOX) && defined(LIBMESH_TRILINOS_HAVE_EPETRA) 
   25 #include "libmesh/libmesh_logging.h" 
   26 #include "libmesh/dof_map.h" 
   27 #include "libmesh/nonlinear_implicit_system.h" 
   28 #include "libmesh/trilinos_nox_nonlinear_solver.h" 
   29 #include "libmesh/system.h" 
   30 #include "libmesh/trilinos_epetra_vector.h" 
   31 #include "libmesh/trilinos_epetra_matrix.h" 
   32 #include "libmesh/trilinos_preconditioner.h" 
   35 #include "libmesh/ignore_warnings.h" 
   36 #include "NOX_Epetra_MatrixFree.H" 
   37 #include "NOX_Epetra_LinearSystem_AztecOO.H" 
   38 #include "NOX_Epetra_Group.H" 
   39 #include "NOX_Epetra_Vector.H" 
   40 #include "libmesh/restore_warnings.h" 
   46                           public NOX::Epetra::Interface::Jacobian,
 
   47                           public NOX::Epetra::Interface::Preconditioner
 
   56   bool computeF(
const Epetra_Vector & x,
 
   58                 NOX::Epetra::Interface::Required::FillType fillType);
 
   62                        Epetra_Operator & Jac);
 
   71                          Epetra_RowMatrix & M);
 
   76                              Epetra_Operator & Prec,
 
   77                              Teuchos::ParameterList * p);
 
   97                                  NOX::Epetra::Interface::Required::FillType )
 
   99   LOG_SCOPE(
"residual()", 
"TrilinosNoxNonlinearSolver");
 
  108   X_global.
swap(X_sys);
 
  115   X_global.swap(X_sys);
 
  125     libmesh_error_msg(
"ERROR: cannot specify both a function and object to compute the Residual!");
 
  128     libmesh_error_msg(
"ERROR: cannot specify both a function and object to compute the combined Residual & Jacobian!");
 
  154                                         Epetra_Operator & jac)
 
  156   LOG_SCOPE(
"jacobian()", 
"TrilinosNoxNonlinearSolver");
 
  168   X_global.
swap(X_sys);
 
  173   X_global.swap(X_sys);
 
  179     libmesh_error_msg(
"ERROR: cannot specify both a function and object to compute the Jacobian!");
 
  182     libmesh_error_msg(
"ERROR: cannot specify both a function and object to compute the combined Residual & Jacobian!");
 
  197     libmesh_error_msg(
"Error! Unable to compute residual and/or Jacobian!");
 
  216                                               Epetra_Operator & prec,
 
  217                                               Teuchos::ParameterList * )
 
  219   LOG_SCOPE(
"preconditioner()", 
"TrilinosNoxNonlinearSolver");
 
  232   X_global.
swap(X_sys);
 
  237   X_global.swap(X_sys);
 
  243     libmesh_error_msg(
"ERROR: cannot specify both a function and object to compute the Jacobian!");
 
  246     libmesh_error_msg(
"ERROR: cannot specify both a function and object to compute the combined Residual & Jacobian!");
 
  261     libmesh_error_msg(
"Error! Unable to compute residual and/or Jacobian!");
 
  275 template <
typename T>
 
  282 template <
typename T>
 
  291 #include <libmesh/ignore_warnings.h>  
  293 template <
typename T>
 
  294 std::pair<unsigned int, Real>
 
  303   if (this->user_presolve)
 
  304     this->user_presolve(this->system());
 
  309   NOX::Epetra::Vector x(*x_epetra->
vec());
 
  311   Teuchos::RCP<Teuchos::ParameterList> nlParamsPtr = Teuchos::rcp(
new Teuchos::ParameterList);
 
  312   Teuchos::ParameterList & nlParams = *(nlParamsPtr.get());
 
  313   nlParams.set(
"Nonlinear Solver", 
"Line Search Based");
 
  316   Teuchos::ParameterList & printParams = nlParams.sublist(
"Printing");
 
  317   printParams.set(
"Output Precision", 3);
 
  318   printParams.set(
"Output Processor", 0);
 
  319   printParams.set(
"Output Information",
 
  320                   NOX::Utils::OuterIteration +
 
  321                   NOX::Utils::OuterIterationStatusTest +
 
  322                   NOX::Utils::InnerIteration +
 
  323                   NOX::Utils::LinearSolverDetails +
 
  324                   NOX::Utils::Parameters +
 
  325                   NOX::Utils::Details +
 
  326                   NOX::Utils::Warning);
 
  328   Teuchos::ParameterList & dirParams = nlParams.sublist(
"Direction");
 
  329   dirParams.set(
"Method", 
"Newton");
 
  330   Teuchos::ParameterList & newtonParams = dirParams.sublist(
"Newton");
 
  331   newtonParams.set(
"Forcing Term Method", 
"Constant");
 
  333   Teuchos::ParameterList & lsParams = newtonParams.sublist(
"Linear Solver");
 
  334   lsParams.set(
"Aztec Solver", 
"GMRES");
 
  335   lsParams.set(
"Max Iterations", static_cast<int>(this->max_linear_iterations));
 
  336   lsParams.set(
"Tolerance", this->initial_linear_tolerance);
 
  337   lsParams.set(
"Output Frequency", 1);
 
  338   lsParams.set(
"Size of Krylov Subspace", 1000);
 
  341   Teuchos::RCP<NOX::Epetra::Interface::Required> iReq(_interface);
 
  342   Teuchos::RCP<NOX::Epetra::LinearSystemAztecOO> linSys;
 
  343   Teuchos::RCP<Epetra_Operator> pc;
 
  345   if (this->jacobian || this->jacobian_object || this->residual_and_jacobian_object)
 
  347       if (this->_preconditioner)
 
  350           lsParams.set(
"Preconditioner", 
"User Defined");
 
  353             cast_ptr<TrilinosPreconditioner<Number> *>(this->_preconditioner);
 
  354           pc = Teuchos::rcp(trilinos_pc);
 
  356           Teuchos::RCP<NOX::Epetra::Interface::Preconditioner> iPrec(_interface);
 
  357           linSys = Teuchos::rcp(
new NOX::Epetra::LinearSystemAztecOO(printParams, lsParams, iReq, iPrec, pc, x));
 
  361           lsParams.set(
"Preconditioner", 
"None");
 
  368           Teuchos::RCP<Epetra_RowMatrix> jacMat = Teuchos::rcp(jacSys.
mat());
 
  370           Teuchos::RCP<NOX::Epetra::Interface::Jacobian> iJac(_interface);
 
  371           linSys = Teuchos::rcp(
new NOX::Epetra::LinearSystemAztecOO(printParams, lsParams, iReq, iJac, jacMat, x));
 
  377       Teuchos::RCP<NOX::Epetra::MatrixFree> MF = Teuchos::rcp(
new NOX::Epetra::MatrixFree(printParams, iReq, x));
 
  379       Teuchos::RCP<NOX::Epetra::Interface::Jacobian> iJac(MF);
 
  380       linSys = Teuchos::rcp(
new NOX::Epetra::LinearSystemAztecOO(printParams, lsParams, iReq, iJac, MF, x));
 
  384   Teuchos::RCP<NOX::Epetra::Group> grpPtr = Teuchos::rcp(
new NOX::Epetra::Group(printParams, iReq, x, linSys));
 
  385   NOX::Epetra::Group & grp = *(grpPtr.get());
 
  387   Teuchos::RCP<NOX::StatusTest::NormF> absresid =
 
  388     Teuchos::rcp(
new NOX::StatusTest::NormF(this->absolute_residual_tolerance, NOX::StatusTest::NormF::Unscaled));
 
  389   Teuchos::RCP<NOX::StatusTest::NormF> relresid =
 
  390     Teuchos::rcp(
new NOX::StatusTest::NormF(grp, this->relative_residual_tolerance));
 
  391   Teuchos::RCP<NOX::StatusTest::MaxIters> maxiters =
 
  392     Teuchos::rcp(
new NOX::StatusTest::MaxIters(this->max_nonlinear_iterations));
 
  393   Teuchos::RCP<NOX::StatusTest::FiniteValue> finiteval =
 
  394     Teuchos::rcp(
new NOX::StatusTest::FiniteValue());
 
  395   Teuchos::RCP<NOX::StatusTest::NormUpdate> normupdate =
 
  396     Teuchos::rcp(
new NOX::StatusTest::NormUpdate(this->absolute_step_tolerance));
 
  397   Teuchos::RCP<NOX::StatusTest::Combo> combo =
 
  398     Teuchos::rcp(
new NOX::StatusTest::Combo(NOX::StatusTest::Combo::OR));
 
  399   combo->addStatusTest(absresid);
 
  400   combo->addStatusTest(relresid);
 
  401   combo->addStatusTest(maxiters);
 
  402   combo->addStatusTest(finiteval);
 
  403   combo->addStatusTest(normupdate);
 
  405   Teuchos::RCP<Teuchos::ParameterList> finalPars = nlParamsPtr;
 
  407   Teuchos::RCP<NOX::Solver::Generic> solver = NOX::Solver::buildSolver(grpPtr, combo, nlParamsPtr);
 
  408   NOX::StatusTest::StatusType status = solver->solve();
 
  409   this->converged = (status == NOX::StatusTest::Converged);
 
  411   const NOX::Epetra::Group & finalGroup = dynamic_cast<const NOX::Epetra::Group &>(solver->getSolutionGroup());
 
  412   const NOX::Epetra::Vector & noxFinalSln = dynamic_cast<const NOX::Epetra::Vector &>(finalGroup.getX());
 
  414   *x_epetra->
vec() = noxFinalSln.getEpetraVector();
 
  417   Real residual_norm = finalGroup.getNormF();
 
  418   unsigned int total_iters = solver->getNumIterations();
 
  419   _n_linear_iterations = finalPars->sublist(
"Direction").sublist(
"Newton").sublist(
"Linear Solver").sublist(
"Output").get(
"Total Number of Linear Iterations", -1);
 
  425   return std::make_pair(total_iters, residual_norm);
 
  428 #include <libmesh/restore_warnings.h> 
  432 template <
typename T>
 
  436   return _n_linear_iterations;
 
  449 #endif // LIBMESH_TRILINOS_HAVE_NOX && LIBMESH_TRILINOS_HAVE_EPETRA