1
// Copyright (C) 2005-2007 Garth N. Wells.
2
// Licensed under the GNU LGPL Version 2.1.
4
// Modified by Anders Logg, 2005-2006.
6
// First added: 2005-10-23
7
// Last changed: 2007-05-15
9
#include <dolfin/NewtonSolver.h>
10
#include <dolfin/NonlinearProblem.h>
11
#include <dolfin/LUSolver.h>
12
#include <dolfin/KrylovSolver.h>
15
using namespace dolfin;
17
//-----------------------------------------------------------------------------
18
NewtonSolver::NewtonSolver() : Parametrized()
20
solver = new LUSolver();
22
//-----------------------------------------------------------------------------
25
NewtonSolver::NewtonSolver(Matrix::Type matrix_type) : Parametrized()
27
solver = new LUSolver();
28
// FIXME: Need to select appropriate PETSc matrix
29
//A = new Matrix(matrix_type);
34
//-----------------------------------------------------------------------------
35
NewtonSolver::NewtonSolver(KrylovMethod method, Preconditioner pc)
38
solver = new KrylovSolver(method, pc);
40
//-----------------------------------------------------------------------------
41
NewtonSolver::~NewtonSolver()
45
//-----------------------------------------------------------------------------
46
dolfin::uint NewtonSolver::solve(NonlinearProblem& nonlinear_problem, Vector& x)
48
const uint maxit= get("Newton maximum iterations");
50
// FIXME: add option to compute F(u) anf J together or separately
52
begin("Starting Newton solve.");
55
set("output destination", "silent");
56
nonlinear_problem.form(A, b, x);
58
uint krylov_iterations = 0;
60
bool newton_converged = false;
63
while( !newton_converged && newton_iteration < maxit )
66
set("output destination", "silent");
67
// Perform linear solve and update total number of Krylov iterations
68
krylov_iterations += solver->solve(A, dx, b);
69
set("output destination", "terminal");
71
// Compute initial residual
72
if(newton_iteration == 0)
73
newton_converged = converged(b, dx, nonlinear_problem);
80
set("output destination", "silent");
81
//FIXME: this step is not needed if residual is based on dx and this has converged.
83
nonlinear_problem.form(A, b, x);
85
set("output destination", "terminal");
87
// Test for convergence
88
newton_converged = converged(b, dx, nonlinear_problem);
92
message("Newton solver finished in %d iterations and %d linear solver iterations.",
93
newton_iteration, krylov_iterations);
95
warning("Newton solver did not converge.");
99
return newton_iteration;
101
//-----------------------------------------------------------------------------
102
dolfin::uint NewtonSolver::getIteration() const
104
return newton_iteration;
106
//-----------------------------------------------------------------------------
107
bool NewtonSolver::converged(const Vector& b, const Vector& dx,
108
const NonlinearProblem& nonlinear_problem)
110
const std::string convergence_criterion = get("Newton convergence criterion");
111
const real rtol = get("Newton relative tolerance");
112
const real atol = get("Newton absolute tolerance");
113
const bool report = get("Newton report");
118
if(convergence_criterion == "residual")
120
else if (convergence_criterion == "incremental")
121
residual = dx.norm();
123
error("Unknown Newton convergence criterion");
125
// If this is the first iteration step, set initial residual
126
if(newton_iteration == 0)
127
residual0 = residual;
130
real relative_residual = residual/residual0;
132
// Output iteration number and residual
133
//FIXME: allow precision to be set for dolfin::cout<<
134
std::cout.precision(3);
135
if(report && newton_iteration >0)
136
std::cout<< " Iteration = " << newton_iteration << ", Absolute, relative residual ("
137
<< convergence_criterion << " criterion) = " << std::scientific << residual
138
<< ", "<< std::scientific << relative_residual << std::endl;
140
// Return true of convergence criterion is met
141
if(relative_residual < rtol || residual < atol)
144
// Otherwise return false
147
//-----------------------------------------------------------------------------