@@ -224,6 +224,7 @@ namespace polysolve::nonlinear
224224
225225 gradient_fd_strategy = solver_params[" advanced" ][" apply_gradient_fd" ];
226226 gradient_fd_eps = solver_params[" advanced" ][" gradient_fd_eps" ];
227+ derivative_along_delta_x_tol = solver_params[" advanced" ][" derivative_along_delta_x_tol" ];
227228 }
228229
229230 void Solver::set_strategies_iterations (const json &solver_params)
@@ -357,8 +358,9 @@ namespace polysolve::nonlinear
357358 // Compute a Δx to update the variable
358359 //
359360 bool ok = compute_update_direction (objFunc, x, grad, delta_x);
361+ const double derivative_along_delta_x = delta_x.dot (grad);
360362
361- if (!ok || std::isnan (grad_norm) || (m_strategies[m_descent_strategy]->is_direction_descent () && grad_norm != 0 && delta_x. dot (grad) >= 0 ))
363+ if (!ok || std::isnan (grad_norm) || (m_strategies[m_descent_strategy]->is_direction_descent () && grad_norm != 0 && derivative_along_delta_x >= 0 ))
362364 {
363365 const auto current_name = descent_strategy_name ();
364366
@@ -369,13 +371,13 @@ namespace polysolve::nonlinear
369371 this ->m_status = cppoptlib::Status::UserDefined;
370372 log_and_throw_error (m_logger, " [{}][{}] direction is not a descent direction on last strategy (‖Δx‖={:g}; ‖g‖={:g}; Δx⋅g={:g}≥0); stopping" ,
371373 current_name, m_line_search->name (),
372- delta_x.norm (), compute_grad_norm (x, grad), delta_x. dot (grad) );
374+ delta_x.norm (), compute_grad_norm (x, grad), derivative_along_delta_x );
373375 }
374376
375377 m_logger.debug (
376378 " [{}][{}] direction is not a descent direction (‖Δx‖={:g}; ‖g‖={:g}; Δx⋅g={:g}≥0); reverting to {}" ,
377379 current_name, m_line_search->name (),
378- delta_x.norm (), compute_grad_norm (x, grad), delta_x. dot (grad) , descent_strategy_name ());
380+ delta_x.norm (), compute_grad_norm (x, grad), derivative_along_delta_x , descent_strategy_name ());
379381 this ->m_status = cppoptlib::Status::Continue;
380382 continue ;
381383 }
@@ -404,6 +406,8 @@ namespace polysolve::nonlinear
404406 this ->m_current .xDelta = delta_x_norm;
405407 xDelta = this ->m_current .xDelta ;
406408 this ->m_status = checkConvergence (this ->m_stop , this ->m_current );
409+ if (this ->m_status == cppoptlib::Status::Continue && derivative_along_delta_x > -derivative_along_delta_x_tol)
410+ this ->m_status = cppoptlib::Status::XDeltaTolerance;
407411 if (this ->m_status != cppoptlib::Status::Continue)
408412 break ;
409413
0 commit comments