5
// ************************************************************************
7
// NOX: An Object-Oriented Nonlinear Solver Package
8
// Copyright (2002) Sandia Corporation
10
// LOCA: Library of Continuation Algorithms Package
11
// Copyright (2005) Sandia Corporation
13
// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
14
// license for use of this work by or on behalf of the U.S. Government.
16
// This library is free software; you can redistribute it and/or modify
17
// it under the terms of the GNU Lesser General Public License as
18
// published by the Free Software Foundation; either version 2.1 of the
19
// License, or (at your option) any later version.
21
// This library is distributed in the hope that it will be useful, but
22
// WITHOUT ANY WARRANTY; without even the implied warranty of
23
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24
// Lesser General Public License for more details.
26
// You should have received a copy of the GNU Lesser General Public
27
// License along with this library; if not, write to the Free Software
28
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
31
// Questions? Contact Roger Pawlowski (rppawlo@sandia.gov) or
32
// Eric Phipps (etphipp@sandia.gov), Sandia National Laboratories.
33
// ************************************************************************
39
// ************************************************************************
42
#include "NOX_Common.H"
44
#ifdef WITH_PRERELEASE
46
#include "NOX_Direction_ModifiedNewton.H" // class definition
47
#include "NOX_Abstract_Vector.H"
48
#include "NOX_Abstract_Group.H"
49
#include "NOX_Solver_Generic.H"
50
#include "NOX_Utils.H"
51
#include "NOX_GlobalData.H"
53
NOX::Direction::ModifiedNewton::
54
ModifiedNewton(const Teuchos::RCP<NOX::GlobalData>& gd,
55
Teuchos::ParameterList& p)
59
if (p.sublist("Modified-Newton").get("Max Age of Jacobian", 10) < 0)
60
p.sublist("Modified-Newton").set("Max Age of Jacobian", 0);
63
NOX::Direction::ModifiedNewton::~ModifiedNewton()
67
bool NOX::Direction::ModifiedNewton::
68
reset(const Teuchos::RCP<NOX::GlobalData>& gd,
69
Teuchos::ParameterList& params)
72
utils = gd->getUtils();
76
Teuchos::ParameterList& p = params.sublist("Modified-Newton");
78
doRescue = p.get("Rescue Bad Newton Solve", true);
79
if (!p.sublist("Linear Solver").isParameter("Tolerance"))
80
p.sublist("Linear Solver").get("Tolerance", 1.0e-10);
85
bool NOX::Direction::ModifiedNewton::
86
compute(NOX::Abstract::Vector& dir,
87
NOX::Abstract::Group& soln,
88
const NOX::Solver::Generic& solver)
90
NOX::Abstract::Group::ReturnType status;
92
// Compute F at current solution
93
status = soln.computeF();
94
if (status != NOX::Abstract::Group::Ok)
95
throwError("compute", "Unable to compute F");
97
maxAgeOfJacobian = paramsPtr->sublist("Modified-Newton").get("Max Age of Jacobian", 10);
99
if (Teuchos::is_null(oldJacobianGrpPtr)) {
100
oldJacobianGrpPtr = soln.clone(DeepCopy);
102
NOX::Abstract::Group& oldJacobianGrp = *oldJacobianGrpPtr;
104
status = NOX::Abstract::Group::Failed;
105
while (status != NOX::Abstract::Group::Ok) {
106
// Conditionally compute Jacobian at current solution.
107
if ( (ageOfJacobian == -1) || (ageOfJacobian == maxAgeOfJacobian) ) {
109
if (ageOfJacobian > 0)
110
oldJacobianGrp = soln;
111
status = oldJacobianGrp.computeJacobian();
112
if (status != NOX::Abstract::Group::Ok)
113
throwError("compute", "Unable to compute Jacobian");
119
// Compute the Modified Newton direction
120
status = oldJacobianGrp.applyJacobianInverse(paramsPtr->sublist("Modified-Newton").sublist("Linear Solver"), soln.getF(), dir);
123
// It didn't converge, but maybe we can recover.
124
if ((status != NOX::Abstract::Group::Ok) &&
125
(doRescue == false)) {
126
throwError("compute", "Unable to solve Newton system");
128
else if ((status != NOX::Abstract::Group::Ok) &&
129
(doRescue == true)) {
130
if (utils->isPrintType(NOX::Utils::Warning))
131
utils->out() << "WARNING: NOX::Direction::ModifiedNewton::compute() - "
132
<< "Linear solve failed to achieve convergence - "
133
<< "using the step anyway since \"Rescue Bad Newton Solve\" "
134
<< "is true. Also, flagging recompute of Jacobian." << std::endl;
135
ageOfJacobian = maxAgeOfJacobian;
136
status = NOX::Abstract::Group::Ok;
143
bool NOX::Direction::ModifiedNewton::compute(NOX::Abstract::Vector& dir,
144
NOX::Abstract::Group& soln,
145
const NOX::Solver::LineSearchBased& solver)
147
return NOX::Direction::Generic::compute( dir, soln, solver );
150
bool NOX::Direction::ModifiedNewton::rescueBadNewtonSolve(const NOX::Abstract::Group& grp) const
152
//! Check if the "rescue" option has been selected
156
//! See if the group has compute the accuracy
158
NOX::Abstract::Group::ReturnType status = oldJacobianGrpPtr->getNormLastLinearSolveResidual(accuracy);
160
// If this functionality is not supported in the group, return false
161
/* NOTE FROM TAMMY: We could later modify this to acutally caluclate
162
the error itself if it's just a matter of the status being
164
if (status != NOX::Abstract::Group::Ok)
167
// Check if there is any improvement in the relative residual
168
double normF = grp.getNormF();
170
// If we can't reduce the relative norm at all, we're not happy
171
if (accuracy >= normF)
174
// Otherwise, we just print a warning and keep going
175
if (utils->isPrintType(NOX::Utils::Warning))
176
utils->out() << "WARNING: NOX::Direction::ModifiedNewton::compute - Unable to achieve desired linear solve accuracy." << endl;
181
void NOX::Direction::ModifiedNewton::throwError(const string& functionName, const string& errorMsg)
183
if (utils->isPrintType(NOX::Utils::Error))
184
utils->err() << "NOX::Direction::ModifiedNewton::" << functionName << " - " << errorMsg << endl;
188
#endif // WITH_PRERELEASE