LCOV - code coverage report
Current view: top level - include/solvers - petsc_nonlinear_solver.h (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4624 (b6265e) with base 1fb77f Lines: 5 14 35.7 %
Date: 2026-11-03 16:49:57 Functions: 6 14 42.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // The libMesh Finite Element Library.
       2             : // Copyright (C) 2002-2026 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_PETSC_NONLINEAR_SOLVER_H
      21             : #define LIBMESH_PETSC_NONLINEAR_SOLVER_H
      22             : 
      23             : #include "libmesh/libmesh_config.h"
      24             : 
      25             : // Petsc include files.
      26             : #ifdef LIBMESH_HAVE_PETSC
      27             : 
      28             : // Local includes
      29             : #include "libmesh/nonlinear_solver.h"
      30             : #include "libmesh/petsc_macro.h"
      31             : #include "libmesh/wrapped_petsc.h"
      32             : #include "libmesh/petsc_dm_wrapper.h"
      33             : #include "libmesh/petsc_mffd_matrix.h"
      34             : 
      35             : // PETSc includes
      36             : #ifdef I
      37             : # define LIBMESH_SAW_I
      38             : #endif
      39             : #include <petscsnes.h>
      40             : #ifndef LIBMESH_SAW_I
      41             : # undef I // Avoid complex.h contamination
      42             : #endif
      43             : 
      44             : namespace libMesh
      45             : {
      46             : class ResidualContext;
      47             : template <typename T>
      48             : class NumericVector;
      49             : void libmesh_petsc_snes_finish_residual (ResidualContext & rc,
      50             :                                          Vec x,
      51             :                                          Vec r,
      52             :                                          NumericVector<Number> & R);
      53             : 
      54             : // Allow users access to these functions in case they want to reuse them.  Users shouldn't
      55             : // need access to these most of the time as they are used internally by this object.
      56             : extern "C"
      57             : {
      58             :   PetscErrorCode libmesh_petsc_recalculate_monitor(SNES snes, PetscInt it, PetscReal norm, void* mctx);
      59             :   PetscErrorCode libmesh_petsc_snes_monitor (SNES, PetscInt its, PetscReal fnorm, void *);
      60             :   PetscErrorCode libmesh_petsc_snes_residual (SNES, Vec x, Vec r, void * ctx);
      61             :   PetscErrorCode libmesh_petsc_snes_fd_residual (SNES, Vec x, Vec r, void * ctx);
      62             :   PetscErrorCode libmesh_petsc_snes_mffd_residual (SNES snes, Vec x, Vec r, void * ctx);
      63             :   PetscErrorCode libmesh_petsc_snes_mffd_interface (void * ctx, Vec x, Vec r);
      64             :   PetscErrorCode libmesh_petsc_snes_jacobian (SNES, Vec x, Mat jac, Mat pc, void * ctx);
      65             :   PetscErrorCode libmesh_petsc_snes_precheck(SNESLineSearch, Vec X, Vec Y, PetscBool * changed, void * context);
      66             :   PetscErrorCode libmesh_petsc_snes_postcheck(SNESLineSearch, Vec x, Vec y, Vec w, PetscBool * changed_y, PetscBool * changed_w, void * context);
      67             :   PetscErrorCode libmesh_petsc_linesearch_shellfunc(SNESLineSearch linesearch, void * ctx);
      68             : }
      69             : 
      70             : /**
      71             :  * This class provides an interface to PETSc
      72             :  * iterative solvers that is compatible with the \p libMesh
      73             :  * \p NonlinearSolver<>
      74             :  *
      75             :  * \author Benjamin Kirk
      76             :  * \date 2002-2007
      77             :  */
      78             : template <typename T>
      79         330 : class PetscNonlinearSolver : public NonlinearSolver<T>
      80             : {
      81             : public:
      82             :   /**
      83             :    * The type of system
      84             :    */
      85             :   typedef NonlinearImplicitSystem sys_type;
      86             : 
      87             :   /**
      88             :    *  Constructor. Initializes Petsc data structures
      89             :    */
      90             :   explicit
      91             :   PetscNonlinearSolver (sys_type & system);
      92             : 
      93             :   /**
      94             :    * Destructor.
      95             :    */
      96             :   ~PetscNonlinearSolver ();
      97             : 
      98             :   /**
      99             :    * Release all memory and clear data structures.
     100             :    */
     101             :   virtual void clear () override;
     102             : 
     103             :   /**
     104             :    * Initialize data structures if not done so already.
     105             :    * May assign a name to the solver in some implementations
     106             :    */
     107             :   virtual void init (const char * name = nullptr) override;
     108             : 
     109             :   /**
     110             :    * \returns The raw PETSc snes context pointer. This method calls init() so in that vein, we have
     111             :    * an optional name prefix argument that if provided will be given to the SNES context
     112             :    */
     113             :   SNES snes(const char * name = nullptr);
     114             : 
     115             :   /**
     116             :    * Call the Petsc solver, using the same matrix for the system and preconditioner matrices. Calls
     117             :    * the two-matrix overload below with \p pre_in for both.
     118             :    */
     119             :   virtual std::pair<unsigned int, Real>
     120             :   solve (SparseMatrix<T> & pre_in,               // System Preconditioning Matrix
     121             :          NumericVector<T> &,                    // Solution vector
     122             :          NumericVector<T> &,                    // Residual vector
     123             :          const double,                         // Stopping tolerance
     124             :          const unsigned int) override; // N. Iterations
     125             : 
     126             :   /**
     127             :    * Call the Petsc solver, using \p jac_in as the actual SNES Jacobian operator (Amat) and
     128             :    * \p pre_in as the preconditioning matrix (Pmat).
     129             :    */
     130             :   virtual std::pair<unsigned int, Real>
     131             :   solve (SparseMatrix<T> & jac_in,               // Jacobian operator matrix (Amat)
     132             :          SparseMatrix<T> & pre_in,               // Preconditioning matrix (Pmat)
     133             :          NumericVector<T> &,                    // Solution vector
     134             :          NumericVector<T> &,                    // Residual vector
     135             :          const double,                         // Stopping tolerance
     136             :          const unsigned int) override; // N. Iterations
     137             : 
     138             :   /**
     139             :    * Prints a useful message about why the latest nonlinear solve
     140             :    * con(di)verged.
     141             :    */
     142             :   virtual void print_converged_reason() override;
     143             : 
     144             :   /**
     145             :    * \returns The currently-available (or most recently obtained, if
     146             :    * the SNES object has been destroyed) convergence reason.
     147             :    *
     148             :    * Refer to PETSc docs for the meaning of different
     149             :    * SNESConvergedReasons.
     150             :    */
     151             :   SNESConvergedReason get_converged_reason();
     152             : 
     153             :   /**
     154             :    * Get the total number of linear iterations done in the last solve
     155             :    */
     156             :   virtual int get_total_linear_iterations() override;
     157             : 
     158             :   /**
     159             :    * \returns The current nonlinear iteration number if called
     160             :    * *during* the solve(), for example by the user-specified residual
     161             :    * or Jacobian function.
     162             :    */
     163           0 :   virtual unsigned get_current_nonlinear_iteration_number() const override
     164           0 :   { return _current_nonlinear_iteration_number; }
     165             : 
     166             :   /**
     167             :    * Set if the residual should be zeroed out in the callback
     168             :    */
     169           0 :   void set_residual_zero_out(bool state) { _zero_out_residual = state; }
     170             : 
     171             :   /**
     172             :    * Set if the jacobian should be zeroed out in the callback
     173             :    */
     174           0 :   void set_jacobian_zero_out(bool state) { _zero_out_jacobian = state; }
     175             : 
     176             :   /**
     177             :    * Set to true to use the libMesh's default monitor, set to false to use your own
     178             :    */
     179           0 :   void use_default_monitor(bool state) { _default_monitor = state; }
     180             : 
     181             :   /**
     182             :    * Set to true to let PETSc reuse the base vector
     183             :    */
     184           0 :   void set_snesmf_reuse_base(bool state) { _snesmf_reuse_base = state; }
     185             : 
     186             :   /**
     187             :    * @return Whether we are reusing the nonlinear function evaluation as the base for doing
     188             :    * matrix-free approximation of the Jacobian action
     189             :    */
     190        2398 :   bool snes_mf_reuse_base() const { return _snesmf_reuse_base; }
     191             : 
     192             :   /**
     193             :    * Set whether evaluating the residual twice at the same solution gives exactly the same result.
     194             :    * This is used to decide whether to run the debug-mode check of matrix-free base vector reuse,
     195             :    * which requires an exact match. The check is already skipped for MPI-parallel and threaded runs;
     196             :    * applications whose assembly is non-deterministic for other reasons (e.g. due to device
     197             :    * parallelism) should set this to false. This only disables the check; the base vector is still
     198             :    * reused.
     199             :    */
     200           0 :   void set_reproducible_residual(bool state) { _reproducible_residual = state; }
     201             : 
     202             :   /**
     203             :    * @return Whether evaluating the residual twice at the same solution gives exactly the same
     204             :    * result
     205             :    */
     206        2398 :   bool reproducible_residual() const { return _reproducible_residual; }
     207             : 
     208             :   /**
     209             :    * Set whether we are computing the base vector for matrix-free finite-differencing
     210             :    */
     211           0 :   void set_computing_base_vector(bool computing_base_vector) { _computing_base_vector = computing_base_vector; }
     212             : 
     213             :   /**
     214             :    * @return whether we are computing the base vector for matrix-free finite-differencing
     215             :    */
     216           0 :   bool computing_base_vector() const { return _computing_base_vector; }
     217             : 
     218             :   /**
     219             :    * Abstract base class to be used to implement a custom line-search algorithm. When the system
     220             :    * eliminates constrained degrees of freedom, the line search's vectors are reduced; \p prolong()
     221             :    * forms full vectors from them
     222             :    */
     223             :   class ComputeLineSearchObject
     224             :   {
     225             :   public:
     226             :     virtual ~ComputeLineSearchObject () = default;
     227             : 
     228             :     virtual void linesearch (SNESLineSearch linesearch) = 0;
     229             :   };
     230             : 
     231             :   /**
     232             :    * A callable object that can be used to specify a custom line-search
     233             :    */
     234             :   std::unique_ptr<ComputeLineSearchObject> linesearch_object;
     235             : 
     236             :   /**
     237             :     * Setup the default monitor if required
     238             :     */
     239             :   void setup_default_monitor();
     240             : 
     241             :   /**
     242             :    * Getter for preconditioner reuse
     243             :    */
     244             :   virtual bool reuse_preconditioner() const override;
     245             : 
     246             :   /**
     247             :    *  Getter for the maximum iterations flag for preconditioner reuse
     248             :    */
     249             :   virtual unsigned int reuse_preconditioner_max_linear_its() const override;
     250             : 
     251             :   /**
     252             :    *  Immediately force a new preconditioner, even if reuse is set
     253             :    */
     254             :   virtual void force_new_preconditioner() override;
     255             : 
     256             :   /**
     257             :    * Builds \p _retained_is from the system's \p ConstraintEliminationDofMap, or clears it when
     258             :    * the system does not eliminate constraints
     259             :    */
     260             :   void setup_constraint_elimination();
     261             : 
     262             :   /**
     263             :    * Whether the solve eliminates constrained degrees of freedom
     264             :    */
     265       45732 :   bool eliminating_constraints() const { return static_cast<IS>(_retained_is) != nullptr; }
     266             : 
     267             :   /**
     268             :    * Makes the system's \p current_local_solution the full iterate that \p x represents: \p x
     269             :    * itself, with constraints enforced exactly if requested, or \f$ C x + h \f$ when eliminating
     270             :    * constraints. When eliminating constraints the system's \p solution is set as well
     271             :    */
     272             :   void localize_solution(Vec x);
     273             : 
     274             :   /**
     275             :    * Prolongs the reduced vector \p y into the full vector \p x, which must be parallel. With \p
     276             :    * homogeneous false this forms \f$ x = C y + h \f$; with \p homogeneous true, as for a step or
     277             :    * a search direction, \f$ x = C y \f$
     278             :    */
     279             :   void prolong(Vec y, NumericVector<T> & x, bool homogeneous) const;
     280             : 
     281             :   /**
     282             :    * Restricts the full vector \p x into the reduced vector \p y by taking its retained entries
     283             :    */
     284             :   void restrict_vector(const NumericVector<T> & x, Vec y) const;
     285             : 
     286             : 
     287             : protected:
     288             : 
     289             :   /**
     290             :    * Nonlinear solver context
     291             :    */
     292             :   WrappedPetsc<SNES> _snes;
     293             : 
     294             :   /**
     295             :    * Store the reason for SNES convergence/divergence for use even after the _snes
     296             :    * has been cleared.
     297             :    *
     298             :    * \note \p print_converged_reason() will always \e try to get the
     299             :    * current reason with SNESGetConvergedReason(), but if the SNES
     300             :    * object has already been cleared, it will fall back on this stored
     301             :    * value.  This value is therefore necessarily \e not cleared by the
     302             :    * \p clear() function.
     303             :    */
     304             :   SNESConvergedReason _reason;
     305             : 
     306             :   /**
     307             :    * Stores the total number of linear iterations from the last solve.
     308             :    */
     309             :   PetscInt _n_linear_iterations;
     310             : 
     311             :   /**
     312             :    * Stores the current nonlinear iteration number
     313             :    */
     314             :   unsigned _current_nonlinear_iteration_number;
     315             : 
     316             :   /**
     317             :    * true to zero out residual before going into application level call-back, otherwise false
     318             :    */
     319             :   bool _zero_out_residual;
     320             : 
     321             :   /**
     322             :    * true to zero out jacobian before going into application level call-back, otherwise false
     323             :    */
     324             :   bool _zero_out_jacobian;
     325             : 
     326             :   /**
     327             :    * true if we want the default monitor to be set, false for no monitor (i.e. user code can use their own)
     328             :    */
     329             :   bool _default_monitor;
     330             : 
     331             :   /**
     332             :    * True, If we want the base vector to be used for differencing even if the function provided to SNESSetFunction()
     333             :    * is not the same as that provided to MatMFFDSetFunction().
     334             :    * https://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/SNES/MatSNESMFSetReuseBase.html
     335             :    */
     336             :   bool _snesmf_reuse_base;
     337             : 
     338             :   /**
     339             :    * Whether residual evaluation is reproducible. See set_reproducible_residual()
     340             :    */
     341             :   bool _reproducible_residual;
     342             : 
     343             :   void build_mat_null_space(NonlinearImplicitSystem::ComputeVectorSubspace * computeSubspaceObject,
     344             :                             void (*)(std::vector<NumericVector<Number> *> &, sys_type &),
     345             :                             MatNullSpace *);
     346             : 
     347             :   /**
     348             :    * Whether we are computing the base vector for matrix-free finite differencing
     349             :    */
     350             :   bool _computing_base_vector;
     351             : 
     352             :   /**
     353             :     * Whether we've triggered the preconditioner reuse
     354             :     */
     355             :   bool _setup_reuse;
     356             : 
     357             :   /**
     358             :    * The local retained degrees of freedom of the system's \p ConstraintEliminationDofMap, in the
     359             :    * full numbering, when the solve eliminates constrained degrees of freedom. Entry \p i is the
     360             :    * full index of the \p i-th local entry of a reduced vector. Null otherwise
     361             :    */
     362             :   WrappedPetsc<IS> _retained_is;
     363             : 
     364             : #if defined(LIBMESH_ENABLE_AMR) && defined(LIBMESH_HAVE_METAPHYSICL)
     365             :   /**
     366             :    * Wrapper object for interacting with the "new" libMesh PETSc DM. The new libMesh PETSc DM
     367             :    * implementation is capable of geometric multigrid while the old implementation is not. The new
     368             :    * implementation can be activated from the command line with --use_petsc_dm
     369             :    */
     370             :   PetscDMWrapper _dm_wrapper;
     371             : #endif
     372             : 
     373             : private:
     374       11160 :   friend ResidualContext libmesh_petsc_snes_residual_helper (SNES snes, Vec x, void * ctx);
     375             :   friend void libmesh_petsc_snes_finish_residual (ResidualContext & rc,
     376             :                                                   Vec x,
     377             :                                                   Vec r,
     378             :                                                   NumericVector<Number> & R);
     379             :   friend PetscErrorCode libmesh_petsc_snes_residual (SNES snes, Vec x, Vec r, void * ctx);
     380             :   friend PetscErrorCode libmesh_petsc_snes_fd_residual (SNES snes, Vec x, Vec r, void * ctx);
     381             :   friend PetscErrorCode libmesh_petsc_snes_mffd_residual (SNES snes, Vec x, Vec r, void * ctx);
     382             :   friend PetscErrorCode libmesh_petsc_snes_jacobian (SNES snes, Vec x, Mat jac, Mat pc, void * ctx);
     383             :   friend PetscErrorCode libmesh_petsc_snes_postcheck (SNESLineSearch,
     384             :                                                       Vec x,
     385             :                                                       Vec y,
     386             :                                                       Vec w,
     387             :                                                       PetscBool * changed_y,
     388             :                                                       PetscBool * changed_w,
     389             :                                                       void * context);
     390             :   friend PetscErrorCode libmesh_petsc_snes_precheck (SNESLineSearch,
     391             :                                                      Vec X,
     392             :                                                      Vec Y,
     393             :                                                      PetscBool * changed,
     394             :                                                      void * context);
     395             : };
     396             : 
     397             : } // namespace libMesh
     398             : 
     399             : 
     400             : #endif // #ifdef LIBMESH_HAVE_PETSC
     401             : #endif // LIBMESH_PETSC_NONLINEAR_SOLVER_H

Generated by: LCOV version 1.14