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