LCOV - code coverage report
Current view: top level - include/solvers - nonlinear_solver.h (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4229 (6a9aeb) with base 727f46 Lines: 46 54 85.2 %
Date: 2025-08-19 19:27:09 Functions: 5 22 22.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // The libMesh Finite Element Library.
       2             : // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
       3             : 
       4             : // This library is free software; you can redistribute it and/or
       5             : // modify it under the terms of the GNU Lesser General Public
       6             : // License as published by the Free Software Foundation; either
       7             : // version 2.1 of the License, or (at your option) any later version.
       8             : 
       9             : // This library is distributed in the hope that it will be useful,
      10             : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12             : // Lesser General Public License for more details.
      13             : 
      14             : // You should have received a copy of the GNU Lesser General Public
      15             : // License along with this library; if not, write to the Free Software
      16             : // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
      17             : 
      18             : 
      19             : 
      20             : #ifndef LIBMESH_NONLINEAR_SOLVER_H
      21             : #define LIBMESH_NONLINEAR_SOLVER_H
      22             : 
      23             : // Local includes
      24             : #include "libmesh/libmesh_common.h"
      25             : #include "libmesh/reference_counted_object.h"
      26             : #include "libmesh/nonlinear_implicit_system.h"
      27             : #include "libmesh/libmesh.h"
      28             : #include "libmesh/parallel_object.h"
      29             : 
      30             : // C++ includes
      31             : #include <cstddef>
      32             : #include <memory>
      33             : 
      34             : namespace libMesh
      35             : {
      36             : 
      37             : // forward declarations
      38             : template <typename T> class SparseMatrix;
      39             : template <typename T> class NumericVector;
      40             : template <typename T> class Preconditioner;
      41             : class SolverConfiguration;
      42             : enum SolverPackage : int;
      43             : 
      44             : /**
      45             :  * This base class can be inherited from to provide interfaces to
      46             :  * nonlinear solvers from different packages like PETSc and Trilinos.
      47             :  *
      48             :  * \author Benjamin Kirk
      49             :  * \date 2005
      50             :  */
      51             : template <typename T>
      52             : class NonlinearSolver : public ReferenceCountedObject<NonlinearSolver<T>>,
      53             :                         public ParallelObject
      54             : {
      55             : public:
      56             :   /**
      57             :    * The type of system
      58             :    */
      59             :   typedef NonlinearImplicitSystem sys_type;
      60             : 
      61             :   /**
      62             :    *  Constructor. Initializes Solver data structures
      63             :    */
      64             :   explicit
      65             :   NonlinearSolver (sys_type & s);
      66             : 
      67             :   /**
      68             :    * Destructor.
      69             :    */
      70             :   virtual ~NonlinearSolver ();
      71             : 
      72             :   /**
      73             :    * Builds a \p NonlinearSolver using the nonlinear solver package specified by
      74             :    * \p solver_package
      75             :    */
      76             :   static std::unique_ptr<NonlinearSolver<T>> build(sys_type & s,
      77             :                                                    const SolverPackage solver_package = libMesh::default_solver_package());
      78             : 
      79             :   /**
      80             :    * \returns \p true if the data structures are
      81             :    * initialized, false otherwise.
      82             :    */
      83      206214 :   bool initialized () const { return _is_initialized; }
      84             : 
      85             :   /**
      86             :    * Release all memory and clear data structures.
      87             :    */
      88          42 :   virtual void clear () {}
      89             : 
      90             :   /**
      91             :    * Initialize data structures if not done so already.
      92             :    * May assign a name to the solver in some implementations
      93             :    */
      94             :   virtual void init (const char * name = nullptr) = 0;
      95             : 
      96             :   /**
      97             :    * Solves the nonlinear system.
      98             :    */
      99             :   virtual std::pair<unsigned int, Real> solve (SparseMatrix<T> &,  // System Jacobian Matrix
     100             :                                                NumericVector<T> &, // Solution vector
     101             :                                                NumericVector<T> &, // Residual vector
     102             :                                                const double,      // Stopping tolerance
     103             :                                                const unsigned int) = 0; // N. Iterations
     104             : 
     105             :   /**
     106             :    * Prints a useful message about why the latest nonlinear solve
     107             :    * con(di)verged.
     108             :    */
     109           0 :   virtual void print_converged_reason() { libmesh_not_implemented(); }
     110             : 
     111             :   /**
     112             :    * Get the total number of linear iterations done in the last solve
     113             :    */
     114             :   virtual int get_total_linear_iterations() = 0;
     115             : 
     116             :   /**
     117             :    * \returns The current nonlinear iteration number if called
     118             :    * *during* the solve(), for example by the user-specified residual
     119             :    * or Jacobian function.
     120             :    *
     121             :    * Must be overridden in derived classes.
     122             :    */
     123             :   virtual unsigned get_current_nonlinear_iteration_number() const = 0;
     124             : 
     125             :   /**
     126             :    * Function that computes the residual \p R(X) of the nonlinear system
     127             :    * at the input iterate \p X.
     128             :    */
     129             :   void (* residual) (const NumericVector<Number> & X,
     130             :                      NumericVector<Number> & R,
     131             :                      sys_type & S);
     132             : 
     133             :   /**
     134             :    * Object that computes the residual \p R(X) of the nonlinear system
     135             :    * at the input iterate \p X.
     136             :    */
     137             :   NonlinearImplicitSystem::ComputeResidual * residual_object;
     138             : 
     139             :   /**
     140             :    * Object that computes the residual \p R(X) of the nonlinear system
     141             :    * at the input iterate \p X for the purpose of forming a finite-differenced Jacobian.
     142             :    */
     143             :   NonlinearImplicitSystem::ComputeResidual * fd_residual_object;
     144             : 
     145             :   /**
     146             :    * Object that computes the residual \p R(X) of the nonlinear system
     147             :    * at the input iterate \p X for the purpose of forming Jacobian-vector products
     148             :    * via finite differencing.
     149             :    */
     150             :   NonlinearImplicitSystem::ComputeResidual * mffd_residual_object;
     151             : 
     152             :   /**
     153             :    * Function that computes the Jacobian \p J(X) of the nonlinear system
     154             :    * at the input iterate \p X.
     155             :    */
     156             :   void (* jacobian) (const NumericVector<Number> & X,
     157             :                      SparseMatrix<Number> & J,
     158             :                      sys_type & S);
     159             : 
     160             :   /**
     161             :    * Object that computes the Jacobian \p J(X) of the nonlinear system
     162             :    * at the input iterate \p X.
     163             :    */
     164             :   NonlinearImplicitSystem::ComputeJacobian * jacobian_object;
     165             : 
     166             :   /**
     167             :    * Function that computes either the residual \f$ R(X) \f$ or the
     168             :    * Jacobian \f$ J(X) \f$ of the nonlinear system at the input
     169             :    * iterate \f$ X \f$.
     170             :    *
     171             :    * \note Either \p R or \p J could be \p nullptr.
     172             :    */
     173             :   void (* matvec) (const NumericVector<Number> & X,
     174             :                    NumericVector<Number> * R,
     175             :                    SparseMatrix<Number> * J,
     176             :                    sys_type & S);
     177             : 
     178             :   /**
     179             :    * Object that computes either the residual \f$ R(X) \f$ or the
     180             :    * Jacobian \f$ J(X) \f$ of the nonlinear system at the input
     181             :    * iterate \f$ X \f$.
     182             :    *
     183             :    * \note Either \p R or \p J could be \p nullptr.
     184             :    */
     185             :   NonlinearImplicitSystem::ComputeResidualandJacobian * residual_and_jacobian_object;
     186             : 
     187             :   /**
     188             :    * Function that computes the lower and upper bounds \p XL and \p XU on the solution of the nonlinear system.
     189             :    */
     190             :   void (* bounds) (NumericVector<Number> & XL,
     191             :                    NumericVector<Number> & XU,
     192             :                    sys_type & S);
     193             :   /**
     194             :    * Object that computes the bounds vectors  \f$ XL \f$ and \f$ XU \f$.
     195             :    */
     196             :   NonlinearImplicitSystem::ComputeBounds * bounds_object;
     197             : 
     198             :   /**
     199             :    * Function that computes a basis for the Jacobian's nullspace --
     200             :    * the kernel or the "zero energy modes" -- that can be used in
     201             :    * solving a degenerate problem iteratively, if the solver supports it
     202             :    * (e.g., PETSc's KSP).
     203             :    */
     204             :   void (* nullspace) (std::vector<NumericVector<Number> *> & sp, sys_type & S);
     205             : 
     206             :   /**
     207             :    * A callable object that computes a basis for the Jacobian's nullspace --
     208             :    * the kernel or the "zero energy modes" -- that can be used in
     209             :    * solving a degenerate problem iteratively, if the solver supports it
     210             :    * (e.g., PETSc's KSP).
     211             :    */
     212             :   NonlinearImplicitSystem::ComputeVectorSubspace * nullspace_object;
     213             : 
     214             :   /**
     215             :    * Function that computes a basis for the transpose Jacobian's nullspace --
     216             :    * when solving a degenerate problem iteratively, if the solver supports it
     217             :    * (e.g., PETSc's KSP), it is used to remove contributions outside of R(jac)
     218             :    */
     219             :   void (* transpose_nullspace) (std::vector<NumericVector<Number> *> & sp, sys_type & S);
     220             : 
     221             :   /**
     222             :    * A callable object that computes a basis for the transpose Jacobian's nullspace --
     223             :    * when solving a degenerate problem iteratively, if the solver supports it
     224             :    * (e.g., PETSc's KSP), it is used to remove contributions outside of R(jac)
     225             :    */
     226             :   NonlinearImplicitSystem::ComputeVectorSubspace * transpose_nullspace_object;
     227             : 
     228             :   /**
     229             :    * Function that computes a basis for the Jacobian's near nullspace --
     230             :    * the set of "low energy modes" -- that can be used for AMG coarsening,
     231             :    * if the solver supports it (e.g., ML, PETSc's GAMG).
     232             :    */
     233             :   void (* nearnullspace) (std::vector<NumericVector<Number> *> & sp, sys_type & S);
     234             : 
     235             :   /**
     236             :    * A callable object that computes a basis for the Jacobian's near nullspace --
     237             :    * the set of "low energy modes" -- that can be used for AMG coarsening,
     238             :    * if the solver supports it (e.g., ML, PETSc's GAMG).
     239             :    */
     240             :   NonlinearImplicitSystem::ComputeVectorSubspace * nearnullspace_object;
     241             : 
     242             :   /**
     243             :    * Customizable function pointer which users can attach to the
     244             :    * solver.  Gets called prior to every call to solve().
     245             :    */
     246             :   void (* user_presolve)(sys_type & S);
     247             : 
     248             :   /**
     249             :    * Function that performs a "check" on the Newton search direction
     250             :    * and solution after each nonlinear step. See documentation for the
     251             :    * NonlinearImplicitSystem::ComputePostCheck object for more
     252             :    * information about the calling sequence.
     253             :    */
     254             :   void (* postcheck) (const NumericVector<Number> & old_soln,
     255             :                       NumericVector<Number> & search_direction,
     256             :                       NumericVector<Number> & new_soln,
     257             :                       bool & changed_search_direction,
     258             :                       bool & changed_new_soln,
     259             :                       sys_type & S);
     260             : 
     261             :   /**
     262             :    * A callable object that is executed after each nonlinear
     263             :    * iteration. Allows the user to modify both the search direction
     264             :    * and the solution vector in an application-specific way.
     265             :    */
     266             :   NonlinearImplicitSystem::ComputePostCheck * postcheck_object;
     267             : 
     268             :   NonlinearImplicitSystem::ComputePreCheck * precheck_object;
     269             : 
     270             :   /**
     271             :    * \returns A constant reference to the system we are solving.
     272             :    */
     273           0 :   const sys_type & system () const { return _system; }
     274             : 
     275             :   /**
     276             :    * \returns A writable reference to the system we are solving.
     277             :    */
     278      378633 :   sys_type & system () { return _system; }
     279             : 
     280             :   /**
     281             :    * Attaches a Preconditioner object to be used during the linear solves.
     282             :    */
     283             :   void attach_preconditioner(Preconditioner<T> * preconditioner);
     284             : 
     285             :   /**
     286             :    * Maximum number of non-linear iterations.
     287             :    */
     288             :   unsigned int max_nonlinear_iterations;
     289             : 
     290             :   /**
     291             :    * Maximum number of function evaluations.
     292             :    */
     293             :   unsigned int max_function_evaluations;
     294             : 
     295             :   /**
     296             :    * The NonlinearSolver should exit after the residual is
     297             :    * reduced to either less than absolute_residual_tolerance
     298             :    * or less than relative_residual_tolerance times the
     299             :    * initial residual.
     300             :    *
     301             :    * Users should increase any of these tolerances that they want to use for a
     302             :    * stopping condition.
     303             :    *
     304             :    */
     305             :   double absolute_residual_tolerance;
     306             :   double relative_residual_tolerance;
     307             : 
     308             :   /**
     309             :    * The NonlinearSolver should exit if the residual becomes greater
     310             :    * than the initial residual times the divergence_tolerance.
     311             :    *
     312             :    * Users should adjust this tolerances to prevent divergence of the
     313             :    * NonlinearSolver.
     314             :    */
     315             :   double divergence_tolerance;
     316             : 
     317             :   /**
     318             :    * The NonlinearSolver should exit after the full nonlinear step norm is
     319             :    * reduced to either less than absolute_step_tolerance
     320             :    * or less than relative_step_tolerance times the largest
     321             :    * nonlinear solution which has been seen so far.
     322             :    *
     323             :    * Users should increase any of these tolerances that they want to use for a
     324             :    * stopping condition.
     325             :    *
     326             :    * \note Not all NonlinearSolvers support \p relative_step_tolerance!
     327             :    */
     328             :   double absolute_step_tolerance;
     329             :   double relative_step_tolerance;
     330             : 
     331             :   /**
     332             :    * Each linear solver step should exit after \p max_linear_iterations
     333             :    * is exceeded.
     334             :    */
     335             :   unsigned int max_linear_iterations;
     336             : 
     337             :   /**
     338             :    * Any required linear solves will at first be done with this tolerance;
     339             :    * the NonlinearSolver may tighten the tolerance for later solves.
     340             :    */
     341             :   double initial_linear_tolerance;
     342             : 
     343             :   /**
     344             :    * The tolerance for linear solves is kept above this minimum
     345             :    */
     346             :   double minimum_linear_tolerance;
     347             : 
     348             :   /**
     349             :    * After a call to solve this will reflect whether or not the nonlinear
     350             :    * solve was successful.
     351             :    */
     352             :   bool converged;
     353             : 
     354             :   /**
     355             :    * Set the solver configuration object.
     356             :    */
     357             :   void set_solver_configuration(SolverConfiguration & solver_configuration);
     358             : 
     359             :   /**
     360             :    *  Get the reuse_preconditioner flag
     361             :    */
     362             :   virtual bool reuse_preconditioner() const;
     363             : 
     364             :   /**
     365             :    *  Set the reuse preconditioner flag
     366             :    */
     367             :   virtual void set_reuse_preconditioner(bool reuse);
     368             : 
     369             :   /**
     370             :    *  Get the reuse_preconditioner_max_linear_its parameter
     371             :    */
     372             :   virtual unsigned int reuse_preconditioner_max_linear_its() const;
     373             : 
     374             :   /**
     375             :    *  Set the reuse_preconditioner_max_linear_its parameter
     376             :    */
     377             :   virtual void set_reuse_preconditioner_max_linear_its(unsigned int i);
     378             : 
     379             :   /**
     380             :    * Immediately force a new preconditioner
     381             :    */
     382           0 :   virtual void force_new_preconditioner() {};
     383             : 
     384             :   /**
     385             :    * Enable (or disable; it is \p true by default) exact enforcement
     386             :    * of constraints at the solver level, correcting any constrained
     387             :    * DoF coefficients in \p current_local_solution as well as applying
     388             :    * nonlinear residual and Jacobian terms based on constraint
     389             :    * equations.
     390             :    *
     391             :    * This is probably only safe to disable if user code is setting
     392             :    * nonlinear residual and Jacobian terms based on constraint
     393             :    * equations at an element-by-element level, by combining the
     394             :    * \p asymmetric_constraint_rows option with the
     395             :    * \p residual_constrain_element_vector processing option in
     396             :    * \p DofMap.
     397             :    */
     398           0 :   virtual void set_exact_constraint_enforcement(bool enable)
     399             :   {
     400           0 :     _exact_constraint_enforcement = enable;
     401           0 :   }
     402             : 
     403           0 :   bool exact_constraint_enforcement()
     404             :   {
     405           0 :     return _exact_constraint_enforcement;
     406             :   }
     407             : 
     408             : protected:
     409             :   /**
     410             :    * Whether we should reuse the linear preconditioner
     411             :    */
     412             :   bool _reuse_preconditioner;
     413             : 
     414             :   /**
     415             :    * Whether we should enforce exact constraints globally during a
     416             :    * solve.
     417             :    */
     418             :   bool _exact_constraint_enforcement;
     419             : 
     420             :   /**
     421             :    * Number of linear iterations to retain the preconditioner
     422             :    */
     423             :   unsigned int _reuse_preconditioner_max_linear_its;
     424             : 
     425             :   /**
     426             :    * A reference to the system we are solving.
     427             :    */
     428             :   sys_type & _system;
     429             : 
     430             :   /**
     431             :    * Flag indicating if the data structures have been initialized.
     432             :    */
     433             :   bool _is_initialized;
     434             : 
     435             :   /**
     436             :    * Holds the Preconditioner object to be used for the linear solves.
     437             :    */
     438             :   Preconditioner<T> * _preconditioner;
     439             : 
     440             :   /**
     441             :    * Optionally store a SolverOptions object that can be used
     442             :    * to set parameters like solver type, tolerances and iteration limits.
     443             :    */
     444             :   SolverConfiguration * _solver_configuration;
     445             : };
     446             : 
     447             : 
     448             : 
     449             : 
     450             : /*----------------------- inline functions ----------------------------------*/
     451             : template <typename T>
     452             : inline
     453        1470 : NonlinearSolver<T>::NonlinearSolver (sys_type & s) :
     454             :   ParallelObject               (s),
     455        1386 :   residual                     (nullptr),
     456        1386 :   residual_object              (nullptr),
     457        1386 :   fd_residual_object           (nullptr),
     458        1386 :   mffd_residual_object         (nullptr),
     459        1386 :   jacobian                     (nullptr),
     460        1386 :   jacobian_object              (nullptr),
     461        1386 :   matvec                       (nullptr),
     462        1386 :   residual_and_jacobian_object (nullptr),
     463        1386 :   bounds                       (nullptr),
     464        1386 :   bounds_object                (nullptr),
     465        1386 :   nullspace                    (nullptr),
     466        1386 :   nullspace_object             (nullptr),
     467        1386 :   transpose_nullspace          (nullptr),
     468        1386 :   transpose_nullspace_object   (nullptr),
     469        1386 :   nearnullspace                (nullptr),
     470        1386 :   nearnullspace_object         (nullptr),
     471        1386 :   user_presolve                (nullptr),
     472        1386 :   postcheck                    (nullptr),
     473        1386 :   postcheck_object             (nullptr),
     474        1386 :   precheck_object              (nullptr),
     475        1386 :   max_nonlinear_iterations(0),
     476        1386 :   max_function_evaluations(0),
     477        1386 :   absolute_residual_tolerance(0),
     478        1386 :   relative_residual_tolerance(0),
     479        1386 :   divergence_tolerance(0),
     480        1386 :   absolute_step_tolerance(0),
     481        1386 :   relative_step_tolerance(0),
     482        1386 :   max_linear_iterations(0),
     483        1386 :   initial_linear_tolerance(0),
     484        1386 :   minimum_linear_tolerance(0),
     485        1386 :   converged(false),
     486        1386 :   _reuse_preconditioner(false),
     487        1386 :   _exact_constraint_enforcement(true),
     488        1386 :   _reuse_preconditioner_max_linear_its(0),
     489        1386 :   _system(s),
     490        1386 :   _is_initialized (false),
     491        1386 :   _preconditioner (nullptr),
     492        1470 :   _solver_configuration(nullptr)
     493             : {
     494        1470 : }
     495             : 
     496             : 
     497             : 
     498             : template <typename T>
     499             : inline
     500          42 : NonlinearSolver<T>::~NonlinearSolver ()
     501             : {
     502          42 :   this->NonlinearSolver::clear ();
     503          42 : }
     504             : 
     505             : 
     506             : } // namespace libMesh
     507             : 
     508             : 
     509             : #endif // LIBMESH_NONLINEAR_SOLVER_H

Generated by: LCOV version 1.14