"Do you know whether KINSOL returns different error codes based on
whether it just can't find a solution, or whether something is
conceptually wrong (i.e., a programming error)?"

I believe there are currently 19 possible return values when KINSol does 
not succeed:
https://github.com/LLNL/sundials/blob/e941546af1a5b5e492dcac0a1872540e9961c556/include/kinsol/kinsol.h#L35C1-L59C7
For instance,  'KIN_MAXITER_REACHED' or 'KIN_LINESEARCH_NONCONV' suggests 
KINSol could not find a solution, whereas errors like 
'KIN_FIRST_SYSFUNC_ERR' (and others) indicate recoverable errors. 
That said, I am not sure whether any of these error codes are intended to 
indicate actual programming errors 

"No, in this case the behavior has not changed -- but it should.

Would you be willing to create this test case for the current deal.II
sources as well? That would make it easier for me to come up with a patch."

Attached is the test case for the deal.II 9.6.0 release. 
I was also able to install version 9.6.0 and run the program myself.
Currently, the program throws a 
'StandardExceptions::RecoverableUserCallbackError',
which can be caught and handled as a recoverable error. However, I believe 
this is not sufficient. 
For example, if we limit the number of nonlinear iterations to two via the 
AdditionalData argument, 
we can easily trigger a 'KIN_MAXITER_REACHED' error -- still being ignored 
in release mode.

Best,
Simon




On Tuesday, April 29, 2025 at 7:41:54 PM UTC+2 Wolfgang Bangerth wrote:


On 4/28/25 00:45, Simon wrote: 
> 
> attached, I have adjusted your "kinsol_06" test to dealii 9.4.0 format 
> (callbacks return integers rather than throwing exceptions) 
> and forced it to report an evaluation failure five times in a row. In 
> that situation, KINSol cannot recover and returns a negative status 
value. 

Ah, I see -- the error in that case does not originate in a user 
callback, but instead is a legitimate error code of KINSOL not related 
to a programming mistake. Indeed that should result in an exception, not 
a program termination (or nothing at all, as currently in release mode). 


> I can only test the program in dealii 9.4.0, where the .solve() function 
> ignores in release mode whatever KINSol returns. 
> But if I understand ... 
> 
>      "This code has been rewritten a couple of years ago, and I think 
> that it now 
>       does exactly what you want it to do:" 
> 
> correctly, the attached program behaves differently in dealii 9.6.0 by 
> throwing an exception, thereby offering the possibility to handle those 
> errors? 

No, in this case the behavior has not changed -- but it should. 

Do you know whether KINSOL returns different error codes based on 
whether it just can't find a solution, or whether something is 
conceptually wrong (i.e., a programming error)? 

Would you be willing to create this test case for the current deal.II 
sources as well? That would make it easier for me to come up with a patch. 

Best 
W. 

-- 
The deal.II project is located at http://www.dealii.org/
For mailing list/forum options, see 
https://groups.google.com/d/forum/dealii?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"deal.II User Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion visit 
https://groups.google.com/d/msgid/dealii/e961170e-e000-4ad2-9501-a4b257ea6ccdn%40googlegroups.com.
// ------------------------------------------------------------------------
//
// SPDX-License-Identifier: LGPL-2.1-or-later
// Copyright (C) 2017 - 2023 by the deal.II authors
//
// This file is part of the deal.II library.
//
// Part of the source code is dual licensed under Apache-2.0 WITH
// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
// governing the source code and code contributions can be found in
// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
//
// ------------------------------------------------------------------------


#include <deal.II/lac/vector.h>

#include <deal.II/sundials/kinsol.h>

#include <ostream>


// Solve a nonlinear system with Newton's method in which we report
// recoverable failures when getting too far away from the solution,
// forcing KINSOL to do some backtracking before getting back into the
// region where we are willing to evaluate the residual.
//
// Specifically, we solve the nonlinear problem
//
// F(u) = atan(u)-0.5 = 0
//
// starting at u=10; This is a well-known problematic case because the
// tangent to the curve gets us far far too the left in the first
// iteration, and we use this to test the ability of KINSOL to deal
// with recoverable failures: We pretend that we can't evaluate the
// residual at that point, but the backtracking line search eventually
// gets us back to the region where things work just fine.


int
main()
{
  using VectorType = dealii::Vector<double>;

  // Size of the problem
  const unsigned int N = 1;

  dealii::SUNDIALS::KINSOL<VectorType> kinsol;

  kinsol.reinit_vector = [N](VectorType &v) { v.reinit(N); };

  kinsol.residual = [&](const VectorType &u, VectorType &F) {
    std::cout << "Computing residual at " << u[0] << std::endl;

    static int count = 0;
    if ((u[0] < -10) || (u[0] > 20) || count > 0) // Now, Kinsol will make five attempts, then give up
      {
        std::cout << "Reporting recoverable failure." << std::endl;
        throw dealii::StandardExceptions::RecoverableUserCallbackError();
      }
    count++;


    F.reinit(u);
    F[0] = std::atan(u[0]) - 0.5;
  };

  double J_inverse;

  kinsol.setup_jacobian = [&J_inverse](const VectorType &u,
                                       const VectorType &F) {
    std::cout << "Setting up Jacobian system at u=" << u[0] << std::endl;

    const double J = 1. / (1 + u[0] * u[0]);
    J_inverse      = 1. / J;
  };


  kinsol.solve_with_jacobian = [&](const VectorType &rhs,
                                   VectorType       &dst,
                                   double) { 
        dst[0] = J_inverse * rhs[0]; 

    };

  VectorType v(N);
  v[0] = 10;

  auto niter = kinsol.solve(v);

  std::cout << "Found solution at " << std::flush;
  std::cout << "Converged in " << niter << " iterations." << std::endl;
}

Reply via email to