30 #include <oomph-lib-config.h>
41 namespace BlackBoxFDNewtonSolver
73 unsigned ndof = unknowns.size();
81 double half_residual_squared = 0.0;
82 double max_step = 0.0;
88 for (
unsigned iloop = 0; iloop <
Max_iter; iloop++)
91 residual_fct(params, unknowns, residuals);
97 half_residual_squared = 0.0;
99 for (
unsigned i = 0;
i < ndof;
i++)
101 sum += unknowns[
i] * unknowns[
i];
102 half_residual_squared += residuals[
i] * residuals[
i];
104 half_residual_squared *= 0.5;
105 max_step = 100.0 * std::max(sqrt(sum),
double(ndof));
110 double max_res = std::fabs(*std::max_element(
117 oomph_info <<
"\nNewton iteration iter=" << iloop
118 <<
"\ni residual[i] unknown[i] " << std::endl;
119 for (
unsigned i = 0;
i < ndof;
i++)
137 if (jacobian_fct == 0)
140 for (
unsigned i = 0;
i < ndof;
i++)
142 double backup = unknowns[
i];
146 residual_fct(params, unknowns, residuals_pls);
149 for (
unsigned j = 0; j < ndof; j++)
151 jacobian(j,
i) = (residuals_pls[j] - residuals[j]) /
FD_step;
155 unknowns[
i] = backup;
161 jacobian_fct(params, unknowns, jacobian);
175 for (
unsigned i = 0;
i < ndof;
i++)
178 for (
unsigned j = 0; j < ndof; j++)
180 sum += jacobian(j,
i) * residuals[j];
187 jacobian.
solve(residuals, newton_direction);
192 for (
unsigned i = 0;
i < ndof;
i++)
194 newton_direction[
i] *= -1.0;
198 double half_residual_squared_old = half_residual_squared;
200 half_residual_squared_old,
206 half_residual_squared,
212 for (
unsigned i = 0;
i < ndof;
i++)
214 unknowns[
i] -= newton_direction[
i];
221 std::ostringstream error_stream;
222 error_stream <<
"Newton solver did not converge in " <<
Max_iter
223 <<
" steps " << std::endl;
226 error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
234 const double half_residual_squared_old,
240 double& half_residual_squared,
241 const double& stpmax)
243 const double min_fct_decrease = 1.0e-4;
244 double convergence_tol_on_x = 1.0e-16;
246 double lambda_aux = 0.0;
247 double proposed_lambda = 0.0;
248 unsigned n = x_old.size();
250 for (
unsigned i = 0;
i < n;
i++)
252 sum += newton_dir[
i] * newton_dir[
i];
257 for (
unsigned i = 0;
i < n;
i++)
259 newton_dir[
i] *= stpmax / sum;
263 for (
unsigned i = 0;
i < n;
i++)
265 slope += gradient[
i] * newton_dir[
i];
269 std::ostringstream error_stream;
270 error_stream <<
"Roundoff problem in lnsrch: slope=" << slope <<
"\n";
272 error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
275 for (
unsigned i = 0;
i < n;
i++)
278 std::fabs(newton_dir[
i]) / std::max(std::fabs(x_old[
i]), 1.0);
279 if (temp > test) test = temp;
281 double lambda_min = convergence_tol_on_x / test;
285 for (
unsigned i = 0;
i < n;
i++)
287 x[
i] = x_old[
i] + lambda * newton_dir[
i];
292 residual_fct(params, x, residuals);
293 half_residual_squared = 0.0;
294 for (
unsigned i = 0;
i < n;
i++)
296 half_residual_squared += residuals[
i] * residuals[
i];
298 half_residual_squared *= 0.5;
300 if (lambda < lambda_min)
302 for (
unsigned i = 0;
i < n;
i++) x[
i] = x_old[
i];
306 "BlackBoxFDNewtonSolver::line_search()",
307 OOMPH_EXCEPTION_LOCATION);
310 else if (half_residual_squared <=
311 half_residual_squared_old + min_fct_decrease * lambda * slope)
320 -slope / (2.0 * (half_residual_squared -
321 half_residual_squared_old - slope));
325 double r1 = half_residual_squared - half_residual_squared_old -
327 double r2 = f_aux - half_residual_squared_old - lambda_aux * slope;
329 (r1 / (lambda * lambda) - r2 / (lambda_aux * lambda_aux)) /
330 (lambda - lambda_aux);
331 double b_poly = (-lambda_aux * r1 / (lambda * lambda) +
332 lambda * r2 / (lambda_aux * lambda_aux)) /
333 (lambda - lambda_aux);
336 proposed_lambda = -slope / (2.0 * b_poly);
340 double discriminant = b_poly * b_poly - 3.0 * a_poly * slope;
341 if (discriminant < 0.0)
343 proposed_lambda = 0.5 * lambda;
345 else if (b_poly <= 0.0)
348 (-b_poly + sqrt(discriminant)) / (3.0 * a_poly);
352 proposed_lambda = -slope / (b_poly + sqrt(discriminant));
355 if (proposed_lambda > 0.5 * lambda)
357 proposed_lambda = 0.5 * lambda;
362 f_aux = half_residual_squared;
363 lambda = std::max(proposed_lambda, 0.1 * lambda);
Function-type-object to perform absolute comparison of objects. Apparently this inlines better.
Class of matrices containing doubles, and stored as a DenseMatrix<double>, but with solving functiona...
void solve(DoubleVector &rhs)
Complete LU solve (replaces matrix by its LU decomposition and overwrites RHS with solution)....
void sparse_indexed_output(std::ostream &outfile, const unsigned &precision=0, const bool &output_bottom_right_zero=false) const
Indexed output function to print a matrix to the stream outfile as i,j,a(i,j) for a(i,...
std::ostream *& stream_pt()
Access function for the stream pointer.
An OomphLibError object which should be thrown when an run-time error is encountered....
An OomphLibWarning object which should be created as a temporary object to issue a warning....
unsigned Max_iter
Max. # of Newton iterations.
unsigned N_iter_taken
Number of Newton iterations taken in most recent invocation.
void line_search(const Vector< double > &x_old, const double half_residual_squared_old, const Vector< double > &gradient, ResidualFctPt residual_fct, const Vector< double > ¶ms, Vector< double > &newton_dir, Vector< double > &x, double &half_residual_squared, const double &stpmax)
Line search helper for globally convergent Newton method.
void(* JacobianFctPt)(const Vector< double > &, const Vector< double > &, DenseDoubleMatrix &jacobian)
bool Doc_Progress
Flag to indicate if progress of Newton iteration is to be documented (defaults to false)
void black_box_fd_newton_solve(ResidualFctPt residual_fct, const Vector< double > ¶ms, Vector< double > &unknowns, JacobianFctPt jacobian_fct)
Black-box FD Newton solver: Calling sequence for residual function is.
void(* ResidualFctPt)(const Vector< double > ¶meters, const Vector< double > &unknowns, Vector< double > &residuals)
bool Use_step_length_control
Use steplength control do make globally convergent (default false)
//////////////////////////////////////////////////////////////////// ////////////////////////////////...
OomphInfo oomph_info
Single (global) instantiation of the OomphInfo object – this is used throughout the library as a "rep...