LCOV - code coverage report
Current view: top level - include/systems - system.h (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4229 (6a9aeb) with base 727f46 Lines: 76 107 71.0 %
Date: 2025-08-19 19:27:09 Functions: 38 57 66.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_SYSTEM_H
      21             : #define LIBMESH_SYSTEM_H
      22             : 
      23             : // Local Includes
      24             : #include "libmesh/elem_range.h"
      25             : #include "libmesh/enum_subset_solve_mode.h" // SUBSET_ZERO
      26             : #include "libmesh/enum_parallel_type.h" // PARALLEL
      27             : #include "libmesh/fem_function_base.h"
      28             : #include "libmesh/libmesh_common.h"
      29             : #include "libmesh/parallel_object.h"
      30             : #include "libmesh/parameters.h"
      31             : #include "libmesh/qoi_set.h"
      32             : #include "libmesh/reference_counted_object.h"
      33             : #include "libmesh/tensor_value.h" // For point_hessian
      34             : #include "libmesh/variable.h"
      35             : #include "libmesh/enum_matrix_build_type.h" // AUTOMATIC
      36             : 
      37             : // C++ includes
      38             : #include <cstddef>
      39             : #include <set>
      40             : #include <string>
      41             : #include <string_view>
      42             : #include <vector>
      43             : #include <memory>
      44             : 
      45             : // This define may be useful in --disable-optional builds when it is
      46             : // possible that libmesh will not have any solvers available.
      47             : #if defined(LIBMESH_HAVE_PETSC) || \
      48             :   defined(LIBMESH_HAVE_EIGEN)   || \
      49             :   defined(LIBMESH_HAVE_LASPACK) || \
      50             :   defined(LIBMESH_TRILINOS_HAVE_AZTECOO)
      51             : #define LIBMESH_HAVE_SOLVER 1
      52             : #endif
      53             : 
      54             : namespace libMesh
      55             : {
      56             : 
      57             : // Forward Declarations
      58             : class System;
      59             : class EquationSystems;
      60             : class MeshBase;
      61             : class Xdr;
      62             : class DofMap;
      63             : template <typename Output> class FunctionBase;
      64             : class ParameterVector;
      65             : class Point;
      66             : class SensitivityData;
      67             : class Matrix;
      68             : template <typename T> class NumericVector;
      69             : template <typename T> class SparseMatrix;
      70             : template <typename T> class VectorValue;
      71             : typedef VectorValue<Number> NumberVectorValue;
      72             : typedef NumberVectorValue Gradient;
      73             : class SystemSubset;
      74             : class FEType;
      75             : class SystemNorm;
      76             : enum FEMNormType : int;
      77             : 
      78             : /**
      79             :  * \brief Manages consistently variables, degrees of freedom, and coefficient
      80             :  * vectors.
      81             :  *
      82             :  * This is the base class for classes which contain information related to any
      83             :  * physical process that might be simulated. Such information may range from
      84             :  * the actual solution values to algorithmic flags that may be used to control
      85             :  * the numerical methods employed. In general, use an EquationSystems
      86             :  * object to handle one or more of the children of this class.
      87             :  *
      88             :  * Especially, this class manages the variables of the differential equation,
      89             :  * the coefficient vectors and the \p DofMap, and ensures that these are
      90             :  * consistent. It provides storage for the solution.  Furthermore, (de-)
      91             :  * serialization functionality is provided.
      92             :  *
      93             :  * \author Benjamin S. Kirk
      94             :  * \date 2003-2004
      95             :  */
      96             : class System : public ReferenceCountedObject<System>,
      97             :                public ParallelObject
      98             : {
      99             : public:
     100             : 
     101             :   /**
     102             :    * Constructor.  Optionally initializes required
     103             :    * data structures.
     104             :    */
     105             :   System (EquationSystems & es,
     106             :           const std::string & name,
     107             :           const unsigned int number);
     108             : 
     109             :   /**
     110             :    * Special functions.
     111             :    * - The copy constructor and assignment operator were previously
     112             :    *   declared as private libmesh_not_implemented() functions, this
     113             :    *   is the C++11 way of achieving the same effect.
     114             :    * - The System holds references to Mesh and EquationSystems
     115             :    *   objects, therefore it can't be default move-assigned.
     116             :    * - This class _can_ be default move constructed.
     117             :    * - The destructor dies with an error in dbg/devel modes if libMesh::closed()
     118             :    */
     119             :   System (const System &) = delete;
     120             :   System & operator= (const System &) = delete;
     121             :   System (System &&) = default;
     122             :   System & operator= (System &&) = delete;
     123             :   virtual ~System ();
     124             : 
     125             :   /**
     126             :    * Abstract base class to be used for system initialization.
     127             :    * A user class derived from this class may be used to
     128             :    * initialize the system values by attaching an object
     129             :    * with the method \p attach_init_object.
     130             :    */
     131             :   class Initialization
     132             :   {
     133             :   public:
     134             :     /**
     135             :      * Destructor.  Virtual because we will have virtual functions.
     136             :      */
     137             :     virtual ~Initialization () = default;
     138             : 
     139             :     /**
     140             :      * Initialization function.  This function will be called
     141             :      * to initialize the system values upon creation and must
     142             :      * be provided by the user in a derived class.
     143             :      */
     144             :     virtual void initialize () = 0;
     145             :   };
     146             : 
     147             : 
     148             : 
     149             :   /**
     150             :    * Abstract base class to be used for system assembly.
     151             :    * A user class derived from this class may be used to
     152             :    * assemble the system by attaching an object
     153             :    * with the method \p attach_assemble_object.
     154             :    */
     155             :   class Assembly
     156             :   {
     157             :   public:
     158             :     /**
     159             :      * Destructor.  Virtual because we will have virtual functions.
     160             :      */
     161             :     virtual ~Assembly () = default;
     162             : 
     163             :     /**
     164             :      * Assembly function.  This function will be called
     165             :      * to assemble the system prior to a solve and must
     166             :      * be provided by the user in a derived class.
     167             :      */
     168             :     virtual void assemble () = 0;
     169             :   };
     170             : 
     171             : 
     172             : 
     173             :   /**
     174             :    * Abstract base class to be used for system constraints.
     175             :    * A user class derived from this class may be used to
     176             :    * constrain the system by attaching an object
     177             :    * with the method \p attach_constraint_object.
     178             :    */
     179             :   class Constraint
     180             :   {
     181             :   public:
     182             :     /**
     183             :      * Destructor.  Virtual because we will have virtual functions.
     184             :      */
     185           0 :     virtual ~Constraint () = default;
     186             : 
     187             :     /**
     188             :      * Constraint function.  This function will be called
     189             :      * to constrain the system prior to a solve and must
     190             :      * be provided by the user in a derived class.
     191             :      */
     192             :     virtual void constrain () = 0;
     193             :   };
     194             : 
     195             : 
     196             : 
     197             :   /**
     198             :    * Abstract base class to be used for quantities of interest.
     199             :    * A user class derived from this class may be used to
     200             :    * compute quantities of interest by attaching an object
     201             :    * with the method \p attach_QOI_object.
     202             :    */
     203             :   class QOI
     204             :   {
     205             :   public:
     206             :     /**
     207             :      * Destructor.  Virtual because we will have virtual functions.
     208             :      */
     209             :     virtual ~QOI () = default;
     210             : 
     211             :     /**
     212             :      * Quantity of interest function.  This function will be called
     213             :      * to compute quantities of interest and must be provided by the
     214             :      * user in a derived class.
     215             :      */
     216             :     virtual void qoi (const QoISet & qoi_indices) = 0;
     217             :   };
     218             : 
     219             : 
     220             : 
     221             :   /**
     222             :    * Abstract base class to be used for derivatives of quantities
     223             :    * of interest. A user class derived from this class may be used
     224             :    * to compute quantities of interest by attaching an object
     225             :    * with the method \p attach_QOI_derivative_object.
     226             :    */
     227             :   class QOIDerivative
     228             :   {
     229             :   public:
     230             :     /**
     231             :      * Destructor.  Virtual because we will have virtual functions.
     232             :      */
     233             :     virtual ~QOIDerivative () = default;
     234             : 
     235             :     /**
     236             :      * Quantity of interest derivative function. This function will
     237             :      * be called to compute derivatives of quantities of interest and
     238             :      * must be provided by the user in a derived class.
     239             :      */
     240             :     virtual void qoi_derivative (const QoISet & qoi_indices,
     241             :                                  bool include_liftfunc,
     242             :                                  bool apply_constraints) = 0;
     243             :   };
     244             : 
     245             :   /**
     246             :    * The type of system.
     247             :    */
     248             :   typedef System sys_type;
     249             : 
     250             :   /**
     251             :    * \returns A reference to *this.
     252             :    */
     253             :   sys_type & system () { return *this; }
     254             : 
     255             :   /**
     256             :    * Clear all the data structures associated with
     257             :    * the system.
     258             :    */
     259             :   virtual void clear ();
     260             : 
     261             :   /**
     262             :    * Initializes degrees of freedom on the current mesh.
     263             :    * Sets the
     264             :    */
     265             :   void init ();
     266             : 
     267             :   /**
     268             :    * Reinitializes degrees of freedom and other required data on the
     269             :    * current mesh.
     270             :    *
     271             :    * \note The matrix is not initialized at this time since it may not
     272             :    * be required for all applications. Should be overridden in derived
     273             :    * classes.
     274             :    */
     275             :   virtual void reinit ();
     276             : 
     277             :   /**
     278             :    * Reinitializes the constraints for this system.
     279             :    *
     280             :    * Also prepares the send_list, whether or not constraints have
     281             :    * changed.
     282             :    */
     283             :   virtual void reinit_constraints ();
     284             : 
     285             :   /**
     286             :    * Reinitializes the system with a new mesh.
     287             :    */
     288             :   virtual void reinit_mesh();
     289             : 
     290             :   /**
     291             :    * \returns \p true iff this system has been initialized.
     292             :    */
     293             :   bool is_initialized() const;
     294             : 
     295             :   /**
     296             :    * Update the local values to reflect the solution
     297             :    * on neighboring processors.
     298             :    */
     299             :   virtual void update ();
     300             : 
     301             :   /**
     302             :    * Prepares \p matrix and \p _dof_map for matrix assembly.
     303             :    * Does not actually assemble anything.  For matrix assembly,
     304             :    * use the \p assemble() in derived classes.
     305             :    * Should be overridden in derived classes.
     306             :    */
     307             :   virtual void assemble ();
     308             : 
     309             :   /**
     310             :    * Calls user qoi function.
     311             :    * Can be overridden in derived classes.
     312             :    */
     313             :   virtual void assemble_qoi (const QoISet & qoi_indices = QoISet());
     314             : 
     315             :   /**
     316             :    * Calls user qoi derivative function.
     317             :    * Can be overridden in derived classes.
     318             :    */
     319             :   virtual void assemble_qoi_derivative (const QoISet & qoi_indices = QoISet(),
     320             :                                         bool include_liftfunc = true,
     321             :                                         bool apply_constraints = true);
     322             : 
     323             :   /**
     324             :    * Calls residual parameter derivative function.
     325             :    *
     326             :    * Library subclasses use finite differences by default.
     327             :    *
     328             :    * This should assemble the sensitivity rhs vectors to hold
     329             :    * -(partial R / partial p_i), making them ready to solve
     330             :    * the forward sensitivity equation.
     331             :    *
     332             :    * This method is only implemented in some derived classes.
     333             :    */
     334             :   virtual void assemble_residual_derivatives (const ParameterVector & parameters);
     335             : 
     336             :   /**
     337             :    * After calling this method, any solve will be restricted to the
     338             :    * given subdomain.  To disable this mode, call this method with \p
     339             :    * subset being a \p nullptr.
     340             :    */
     341             :   virtual void restrict_solve_to (const SystemSubset * subset,
     342             :                                   const SubsetSolveMode subset_solve_mode=SUBSET_ZERO);
     343             : 
     344             :   /**
     345             :    * Solves the system.  Should be overridden in derived systems.
     346             :    */
     347           0 :   virtual void solve () {}
     348             : 
     349             :   /**
     350             :    * Solves the sensitivity system, for the provided parameters.
     351             :    * Must be overridden in derived systems.
     352             :    *
     353             :    * \returns A pair with the total number of linear iterations
     354             :    * performed and the (sum of the) final residual norms
     355             :    *
     356             :    * This method is only implemented in some derived classes.
     357             :    */
     358             :   virtual std::pair<unsigned int, Real>
     359             :   sensitivity_solve (const ParameterVector & parameters);
     360             : 
     361             :   /**
     362             :    * Assembles & solves the linear system(s) (dR/du)*u_w = sum(w_p*-dR/dp), for
     363             :    * those parameters p contained within \p parameters weighted by the
     364             :    * values w_p found within \p weights.
     365             :    *
     366             :    * \returns A pair with the total number of linear iterations
     367             :    * performed and the (sum of the) final residual norms
     368             :    *
     369             :    * This method is only implemented in some derived classes.
     370             :    */
     371             :   virtual std::pair<unsigned int, Real>
     372             :   weighted_sensitivity_solve (const ParameterVector & parameters,
     373             :                               const ParameterVector & weights);
     374             : 
     375             :   /**
     376             :    * Solves the adjoint system, for the specified qoi indices, or for
     377             :    * every qoi if \p qoi_indices is nullptr.  Must be overridden in
     378             :    * derived systems.
     379             :    *
     380             :    * \returns A pair with the total number of linear iterations
     381             :    * performed and the (sum of the) final residual norms
     382             :    *
     383             :    * This method is only implemented in some derived classes.
     384             :    */
     385             :   virtual std::pair<unsigned int, Real>
     386             :   adjoint_solve (const QoISet & qoi_indices = QoISet());
     387             : 
     388             :   /**
     389             :    * Assembles & solves the linear system(s)
     390             :    * (dR/du)^T*z_w = sum(w_p*(d^2q/dudp - d^2R/dudp*z)), for those
     391             :    * parameters p contained within \p parameters, weighted by the
     392             :    * values w_p found within \p weights.
     393             :    *
     394             :    * Assumes that adjoint_solve has already calculated z for each qoi
     395             :    * in \p qoi_indices.
     396             :    *
     397             :    * \returns A pair with the total number of linear iterations
     398             :    * performed and the (sum of the) final residual norms
     399             :    *
     400             :    * This method is only implemented in some derived classes.
     401             :    */
     402             :   virtual std::pair<unsigned int, Real>
     403             :   weighted_sensitivity_adjoint_solve (const ParameterVector & parameters,
     404             :                                       const ParameterVector & weights,
     405             :                                       const QoISet & qoi_indices = QoISet());
     406             :   /**
     407             :    * Accessor for the adjoint_already_solved boolean
     408             :    */
     409         784 :   bool is_adjoint_already_solved() const
     410       25384 :   { return adjoint_already_solved;}
     411             : 
     412             :   /**
     413             :    * Setter for the adjoint_already_solved boolean
     414             :    */
     415             :   void set_adjoint_already_solved(bool setting)
     416             :   { adjoint_already_solved = setting;}
     417             : 
     418             : 
     419             :   /**
     420             :    * Solves for the derivative of each of the system's quantities of
     421             :    * interest q in \p qoi[qoi_indices] with respect to each parameter
     422             :    * in \p parameters, placing the result for qoi \p i and parameter
     423             :    * \p j into \p sensitivities[i][j].
     424             :    *
     425             :    * \note \p parameters is a const vector, not a vector-of-const;
     426             :    * parameter values in this vector need to be mutable for finite
     427             :    * differencing to work.
     428             :    *
     429             :    * Automatically chooses the forward method for problems with more
     430             :    * quantities of interest than parameters, or the adjoint method
     431             :    * otherwise.
     432             :    *
     433             :    * This method is only usable in derived classes which override
     434             :    * an implementation.
     435             :    */
     436             :   virtual void qoi_parameter_sensitivity (const QoISet & qoi_indices,
     437             :                                           const ParameterVector & parameters,
     438             :                                           SensitivityData & sensitivities);
     439             : 
     440             :   /**
     441             :    * Solves for parameter sensitivities using the adjoint method.
     442             :    *
     443             :    * This method is only implemented in some derived classes.
     444             :    */
     445             :   virtual void adjoint_qoi_parameter_sensitivity (const QoISet & qoi_indices,
     446             :                                                   const ParameterVector & parameters,
     447             :                                                   SensitivityData & sensitivities);
     448             : 
     449             :   /**
     450             :    * Solves for parameter sensitivities using the forward method.
     451             :    *
     452             :    * This method is only implemented in some derived classes.
     453             :    */
     454             :   virtual void forward_qoi_parameter_sensitivity (const QoISet & qoi_indices,
     455             :                                                   const ParameterVector & parameters,
     456             :                                                   SensitivityData & sensitivities);
     457             : 
     458             :   /**
     459             :    * For each of the system's quantities of interest q in
     460             :    * \p qoi[qoi_indices], and for a vector of parameters p, the
     461             :    * parameter sensitivity Hessian H_ij is defined as
     462             :    * H_ij = (d^2 q)/(d p_i d p_j)
     463             :    * This Hessian is the output of this method, where for each q_i,
     464             :    * H_jk is stored in \p hessian.second_derivative(i,j,k).
     465             :    *
     466             :    * This method is only implemented in some derived classes.
     467             :    */
     468             :   virtual void qoi_parameter_hessian(const QoISet & qoi_indices,
     469             :                                      const ParameterVector & parameters,
     470             :                                      SensitivityData & hessian);
     471             : 
     472             :   /**
     473             :    * For each of the system's quantities of interest q in
     474             :    * \p qoi[qoi_indices], and for a vector of parameters p, the
     475             :    * parameter sensitivity Hessian H_ij is defined as
     476             :    * H_ij = (d^2 q)/(d p_i d p_j)
     477             :    * The Hessian-vector product, for a vector v_k in parameter space, is
     478             :    * S_j = H_jk v_k
     479             :    * This product is the output of this method, where for each q_i,
     480             :    * S_j is stored in \p sensitivities[i][j].
     481             :    *
     482             :    * This method is only implemented in some derived classes.
     483             :    */
     484             :   virtual void qoi_parameter_hessian_vector_product(const QoISet & qoi_indices,
     485             :                                                     const ParameterVector & parameters,
     486             :                                                     const ParameterVector & vector,
     487             :                                                     SensitivityData & product);
     488             : 
     489             :   /**
     490             :    * \returns \p true when the other system contains
     491             :    * identical data, up to the given threshold.  Outputs
     492             :    * some diagnostic info when \p verbose is set.
     493             :    */
     494             :   virtual bool compare (const System & other_system,
     495             :                         const Real threshold,
     496             :                         const bool verbose) const;
     497             : 
     498             :   /**
     499             :    * \returns The system name.
     500             :    */
     501             :   const std::string & name () const;
     502             : 
     503             :   /**
     504             :    * \returns The type of system, helpful in identifying
     505             :    * which system type to use when reading equation system
     506             :    * data from file.  Should be overridden in derived classes.
     507             :    */
     508         502 :   virtual std::string system_type () const { return "Basic"; }
     509             : 
     510             :   /**
     511             :    * Projects arbitrary functions onto the current solution.
     512             :    * The function value \p f and its gradient \p g are
     513             :    * user-provided cloneable functors.
     514             :    * A gradient \p g is only required/used for projecting onto finite
     515             :    * element spaces with continuous derivatives.
     516             :    */
     517             :   void project_solution (FunctionBase<Number> * f,
     518             :                          FunctionBase<Gradient> * g = nullptr) const;
     519             : 
     520             :   /**
     521             :    * Projects arbitrary functions onto the current solution.
     522             :    * The function value \p f and its gradient \p g are
     523             :    * user-provided cloneable functors.
     524             :    * A gradient \p g is only required/used for projecting onto finite
     525             :    * element spaces with continuous derivatives.
     526             :    */
     527             :   void project_solution (FEMFunctionBase<Number> * f,
     528             :                          FEMFunctionBase<Gradient> * g = nullptr) const;
     529             : 
     530             :   /**
     531             :    * Projects arbitrary functions onto the current solution.
     532             :    * The function value \p fptr and its gradient \p gptr are
     533             :    * represented by function pointers.
     534             :    * A gradient \p gptr is only required/used for projecting onto
     535             :    * finite element spaces with continuous derivatives.
     536             :    */
     537             :   typedef Number (*ValueFunctionPointer)(const Point & p,
     538             :                                          const Parameters & Parameters,
     539             :                                          const std::string & sys_name,
     540             :                                          const std::string & unknown_name);
     541             :   typedef Gradient (*GradientFunctionPointer)(const Point & p,
     542             :                                               const Parameters & parameters,
     543             :                                               const std::string & sys_name,
     544             :                                               const std::string & unknown_name);
     545             :   void project_solution (ValueFunctionPointer fptr,
     546             :                          GradientFunctionPointer gptr,
     547             :                          const Parameters & parameters) const;
     548             : 
     549             :   /**
     550             :    * Projects arbitrary functions onto a vector of degree of freedom
     551             :    * values for the current system.
     552             :    * The function value \p f and its gradient \p g are
     553             :    * user-provided cloneable functors.
     554             :    * A gradient \p g is only required/used for projecting onto finite
     555             :    * element spaces with continuous derivatives.
     556             :    *
     557             :    * Constrain the new vector using the requested adjoint rather than
     558             :    * primal constraints if is_adjoint is non-negative.
     559             :    */
     560             :   void project_vector (NumericVector<Number> & new_vector,
     561             :                        FunctionBase<Number> * f,
     562             :                        FunctionBase<Gradient> * g = nullptr,
     563             :                        int is_adjoint = -1) const;
     564             : 
     565             :   /**
     566             :    * Projects arbitrary functions onto a vector of degree of freedom
     567             :    * values for the current system.
     568             :    * The function value \p f and its gradient \p g are
     569             :    * user-provided cloneable functors.
     570             :    * A gradient \p g is only required/used for projecting onto finite
     571             :    * element spaces with continuous derivatives.
     572             :    *
     573             :    * Constrain the new vector using the requested adjoint rather than
     574             :    * primal constraints if is_adjoint is non-negative.
     575             :    */
     576             :   void project_vector (NumericVector<Number> & new_vector,
     577             :                        FEMFunctionBase<Number> * f,
     578             :                        FEMFunctionBase<Gradient> * g = nullptr,
     579             :                        int is_adjoint = -1) const;
     580             : 
     581             :   /**
     582             :    * Projects arbitrary functions onto a vector of degree of freedom
     583             :    * values for the current system.
     584             :    * The function value \p fptr and its gradient \p gptr are
     585             :    * represented by function pointers.
     586             :    * A gradient \p gptr is only required/used for projecting onto
     587             :    * finite element spaces with continuous derivatives.
     588             :    *
     589             :    * Constrain the new vector using the requested adjoint rather than
     590             :    * primal constraints if is_adjoint is non-negative.
     591             :    */
     592             :   void project_vector (ValueFunctionPointer fptr,
     593             :                        GradientFunctionPointer gptr,
     594             :                        const Parameters & parameters,
     595             :                        NumericVector<Number> & new_vector,
     596             :                        int is_adjoint = -1) const;
     597             : 
     598             :   /**
     599             :    * Projects arbitrary boundary functions onto a vector of degree of
     600             :    * freedom values for the current system.
     601             :    * Only degrees of freedom which affect the function's trace on a
     602             :    * boundary in the set \p b are affected.
     603             :    * Only degrees of freedom associated with the variables listed in
     604             :    * the vector \p variables are projected.
     605             :    * The function value \p f and its gradient \p g are
     606             :    * user-provided cloneable functors.
     607             :    * A gradient \p g is only required/used for projecting onto finite
     608             :    * element spaces with continuous derivatives.
     609             :    */
     610             :   void boundary_project_solution (const std::set<boundary_id_type> & b,
     611             :                                   const std::vector<unsigned int> & variables,
     612             :                                   FunctionBase<Number> * f,
     613             :                                   FunctionBase<Gradient> * g = nullptr);
     614             : 
     615             :   /**
     616             :    * Projects arbitrary boundary functions onto a vector of degree of
     617             :    * freedom values for the current system.
     618             :    * Only degrees of freedom which affect the function's trace on a
     619             :    * boundary in the set \p b are affected.
     620             :    * Only degrees of freedom associated with the variables listed in
     621             :    * the vector \p variables are projected.
     622             :    * The function value \p fptr and its gradient \p gptr are
     623             :    * represented by function pointers.
     624             :    * A gradient \p gptr is only required/used for projecting onto
     625             :    * finite element spaces with continuous derivatives.
     626             :    */
     627             :   void boundary_project_solution (const std::set<boundary_id_type> & b,
     628             :                                   const std::vector<unsigned int> & variables,
     629             :                                   ValueFunctionPointer fptr,
     630             :                                   GradientFunctionPointer gptr,
     631             :                                   const Parameters & parameters);
     632             : 
     633             :   /**
     634             :    * Projects arbitrary boundary functions onto a vector of degree of
     635             :    * freedom values for the current system.
     636             :    * Only degrees of freedom which affect the function's trace on a
     637             :    * boundary in the set \p b are affected.
     638             :    * Only degrees of freedom associated with the variables listed in
     639             :    * the vector \p variables are projected.
     640             :    * The function value \p f and its gradient \p g are
     641             :    * user-provided cloneable functors.
     642             :    * A gradient \p g is only required/used for projecting onto finite
     643             :    * element spaces with continuous derivatives.
     644             :    *
     645             :    * Constrain the new vector using the requested adjoint rather than
     646             :    * primal constraints if is_adjoint is non-negative.
     647             :    */
     648             :   void boundary_project_vector (const std::set<boundary_id_type> & b,
     649             :                                 const std::vector<unsigned int> & variables,
     650             :                                 NumericVector<Number> & new_vector,
     651             :                                 FunctionBase<Number> * f,
     652             :                                 FunctionBase<Gradient> * g = nullptr,
     653             :                                 int is_adjoint = -1) const;
     654             : 
     655             :   /**
     656             :    * Projects arbitrary boundary functions onto a vector of degree of
     657             :    * freedom values for the current system.
     658             :    * Only degrees of freedom which affect the function's trace on a
     659             :    * boundary in the set \p b are affected.
     660             :    * Only degrees of freedom associated with the variables listed in
     661             :    * the vector \p variables are projected.
     662             :    * The function value \p fptr and its gradient \p gptr are
     663             :    * represented by function pointers.
     664             :    * A gradient \p gptr is only required/used for projecting onto
     665             :    * finite element spaces with continuous derivatives.
     666             :    *
     667             :    * Constrain the new vector using the requested adjoint rather than
     668             :    * primal constraints if is_adjoint is non-negative.
     669             :    */
     670             :   void boundary_project_vector (const std::set<boundary_id_type> & b,
     671             :                                 const std::vector<unsigned int> & variables,
     672             :                                 ValueFunctionPointer fptr,
     673             :                                 GradientFunctionPointer gptr,
     674             :                                 const Parameters & parameters,
     675             :                                 NumericVector<Number> & new_vector,
     676             :                                 int is_adjoint = -1) const;
     677             : 
     678             :   /**
     679             :    * \returns The system number.
     680             :    */
     681             :   unsigned int number () const;
     682             : 
     683             :   /**
     684             :    * Fill the input vector \p global_soln so that it contains
     685             :    * the global solution on all processors.
     686             :    * Requires communication with all other processors.
     687             :    */
     688             :   void update_global_solution (std::vector<Number> & global_soln) const;
     689             : 
     690             :   /**
     691             :    * Fill the input vector \p global_soln so that it contains
     692             :    * the global solution on processor \p dest_proc.
     693             :    * Requires communication with all other processors.
     694             :    */
     695             :   void update_global_solution (std::vector<Number> & global_soln,
     696             :                                const processor_id_type dest_proc) const;
     697             : 
     698             :   /**
     699             :    * \returns A constant reference to this systems's \p _mesh.
     700             :    */
     701             :   const MeshBase & get_mesh() const;
     702             : 
     703             :   /**
     704             :    * \returns A reference to this systems's \p _mesh.
     705             :    */
     706             :   MeshBase & get_mesh();
     707             : 
     708             :   /**
     709             :    * \returns A constant reference to this system's \p _dof_map.
     710             :    */
     711             :   const DofMap & get_dof_map() const;
     712             : 
     713             :   /**
     714             :    * \returns A writable reference to this system's \p _dof_map.
     715             :    */
     716             :   DofMap & get_dof_map();
     717             : 
     718             :   /**
     719             :    * \returns A constant reference to this system's parent EquationSystems object.
     720             :    */
     721      558896 :   const EquationSystems & get_equation_systems() const { return _equation_systems; }
     722             : 
     723             :   /**
     724             :    * \returns A reference to this system's parent EquationSystems object.
     725             :    */
     726      219069 :   EquationSystems & get_equation_systems() { return _equation_systems; }
     727             : 
     728             :   /**
     729             :    * \returns \p true if the system is active, \p false otherwise.
     730             :    * An active system will be solved.
     731             :    */
     732             :   bool active () const;
     733             : 
     734             :   /**
     735             :    * Activates the system.  Only active systems are solved.
     736             :    */
     737             :   void activate ();
     738             : 
     739             :   /**
     740             :    * Deactivates the system.  Only active systems are solved.
     741             :    */
     742             :   void deactivate ();
     743             : 
     744             :   /**
     745             :    * Sets the system to be "basic only": i.e. advanced system
     746             :    * components such as ImplicitSystem matrices may not be
     747             :    * initialized.  This is useful for efficiency in certain utility
     748             :    * programs that never use System::solve().  This method must be
     749             :    * called after the System or derived class is created but before it
     750             :    * is initialized; e.g. from within EquationSystems::read()
     751             :    */
     752             :   void set_basic_system_only ();
     753             : 
     754             :   /**
     755             :    * Vector iterator typedefs.
     756             :    */
     757             :   typedef std::map<std::string, std::unique_ptr<NumericVector<Number>>, std::less<>>::iterator       vectors_iterator;
     758             :   typedef std::map<std::string, std::unique_ptr<NumericVector<Number>>, std::less<>>::const_iterator const_vectors_iterator;
     759             : 
     760             :   /**
     761             :    * Beginning of vectors container
     762             :    */
     763             :   vectors_iterator vectors_begin ();
     764             : 
     765             :   /**
     766             :    * Beginning of vectors container
     767             :    */
     768             :   const_vectors_iterator vectors_begin () const;
     769             : 
     770             :   /**
     771             :    * End of vectors container
     772             :    */
     773             :   vectors_iterator vectors_end ();
     774             : 
     775             :   /**
     776             :    * End of vectors container
     777             :    */
     778             :   const_vectors_iterator vectors_end () const;
     779             : 
     780             :   /**
     781             :    * Matrix iterator typedefs.
     782             :    */
     783             :   typedef std::map<std::string, std::unique_ptr<SparseMatrix<Number>>, std::less<>>::iterator        matrices_iterator;
     784             :   typedef std::map<std::string, std::unique_ptr<SparseMatrix<Number>>, std::less<>>::const_iterator  const_matrices_iterator;
     785             : 
     786             :   /**
     787             :    * Beginning of matrices container
     788             :    */
     789             :   matrices_iterator matrices_begin ();
     790             : 
     791             :   /**
     792             :    * Beginning of matrices container
     793             :    */
     794             :   const_matrices_iterator matrices_begin () const;
     795             : 
     796             :   /**
     797             :    * End of matrices container
     798             :    */
     799             :   matrices_iterator matrices_end ();
     800             : 
     801             :   /**
     802             :    * End of matrices container
     803             :    */
     804             :   const_matrices_iterator matrices_end () const;
     805             : 
     806             :   /**
     807             :    * Adds the additional vector \p vec_name to this system.  All the
     808             :    * additional vectors are similarly distributed, like the \p
     809             :    * solution, and initialized to zero.
     810             :    *
     811             :    * By default vectors added by add_vector are projected to changed grids by
     812             :    * reinit().  To zero them instead (more efficient), pass "false" as the
     813             :    * second argument
     814             :    *
     815             :    * If the vector already exists, the existing vector is returned.
     816             :    * after any upgrade to the \p projections or \p type has been made.
     817             :    * We *only* handle upgrades (projections false->true, or type
     818             :    * PARALLEL->GHOSTED) in this fashion, not downgrades, on the theory
     819             :    * that if two codes have differing needs we want to support the
     820             :    * union of those needs, not the intersection.  Downgrades can only
     821             :    * be accomplished manually, via \p set_vector_preservation() or by
     822             :    * setting a vector \p type() and re-initializing.
     823             :    */
     824             :   NumericVector<Number> & add_vector (std::string_view vec_name,
     825             :                                       const bool projections=true,
     826             :                                       const ParallelType type = PARALLEL);
     827             : 
     828             :   /**
     829             :    * Removes the additional vector \p vec_name from this system
     830             :    */
     831             :   void remove_vector(std::string_view vec_name);
     832             : 
     833             :   /**
     834             :    * Tells the System whether or not to project the solution vector onto new
     835             :    * grids when the system is reinitialized.  The solution will be projected
     836             :    * unless project_solution_on_reinit() = false is called.
     837             :    */
     838        2392 :   bool & project_solution_on_reinit (void)
     839        2392 :   { return _solution_projection; }
     840             : 
     841             :   /**
     842             :    * \returns \p true if this \p System has a vector associated with the
     843             :    * given name, \p false otherwise.
     844             :    */
     845             :   bool have_vector (std::string_view vec_name) const;
     846             : 
     847             :   /**
     848             :    * \returns A const pointer to the vector if this \p System has a
     849             :    * vector associated with the given name, \p nullptr otherwise.
     850             :    */
     851             :   const NumericVector<Number> * request_vector (std::string_view vec_name) const;
     852             : 
     853             :   /**
     854             :    * \returns A pointer to the vector if this \p System has a
     855             :    * vector associated with the given name, \p nullptr otherwise.
     856             :    */
     857             :   NumericVector<Number> * request_vector (std::string_view vec_name);
     858             : 
     859             :   /**
     860             :    * \returns A const pointer to this system's additional vector
     861             :    * number \p vec_num (where the vectors are counted starting with
     862             :    * 0), or \p nullptr if the system has no such vector.
     863             :    */
     864             :   const NumericVector<Number> * request_vector (const unsigned int vec_num) const;
     865             : 
     866             :   /**
     867             :    * \returns A writable pointer to this system's additional
     868             :    * vector number \p vec_num (where the vectors are counted starting
     869             :    * with 0), or \p nullptr if the system has no such vector.
     870             :    */
     871             :   NumericVector<Number> * request_vector (const unsigned int vec_num);
     872             : 
     873             :   /**
     874             :    * \returns A const reference to this system's additional vector
     875             :    * named \p vec_name.  Access is only granted when the vector is already
     876             :    * properly initialized.
     877             :    */
     878             :   const NumericVector<Number> & get_vector (std::string_view vec_name) const;
     879             : 
     880             :   /**
     881             :    * \returns A writable reference to this system's additional vector
     882             :    * named \p vec_name.  Access is only granted when the vector is already
     883             :    * properly initialized.
     884             :    */
     885             :   NumericVector<Number> & get_vector (std::string_view vec_name);
     886             : 
     887             :   /**
     888             :    * \returns A const reference to this system's additional vector
     889             :    * number \p vec_num (where the vectors are counted starting with
     890             :    * 0).
     891             :    */
     892             :   const NumericVector<Number> & get_vector (const unsigned int vec_num) const;
     893             : 
     894             :   /**
     895             :    * \returns A writable reference to this system's additional
     896             :    * vector number \p vec_num (where the vectors are counted starting
     897             :    * with 0).
     898             :    */
     899             :   NumericVector<Number> & get_vector (const unsigned int vec_num);
     900             : 
     901             :   /**
     902             :    * \returns The name of this system's additional vector number \p
     903             :    * vec_num (where the vectors are counted starting with 0).
     904             :    */
     905             :   const std::string & vector_name (const unsigned int vec_num) const;
     906             : 
     907             :   /**
     908             :    * \returns The name of a system vector, given a reference to that vector
     909             :    */
     910             :   const std::string & vector_name (const NumericVector<Number> & vec_reference) const;
     911             : 
     912             :   /**
     913             :    * Allows one to set the QoI index controlling whether the vector
     914             :    * identified by vec_name represents a solution from the adjoint
     915             :    * (qoi_num >= 0) or primal (qoi_num == -1) space.  This becomes
     916             :    * significant if those spaces have differing heterogeneous
     917             :    * Dirichlet constraints.
     918             :    *
     919             :    * qoi_num == -2 can be used to indicate a vector which should not
     920             :    * be affected by constraints during projection operations.
     921             :    */
     922             :   void set_vector_as_adjoint (const std::string & vec_name, int qoi_num);
     923             : 
     924             :   /**
     925             :    * \returns The integer describing whether the vector identified by
     926             :    * vec_name represents a solution from an adjoint (non-negative) or
     927             :    * the primal (-1) space.
     928             :    */
     929             :   int vector_is_adjoint (std::string_view vec_name) const;
     930             : 
     931             :   /**
     932             :    * Allows one to set the boolean controlling whether the vector
     933             :    * identified by vec_name should be "preserved": projected to new
     934             :    * meshes, saved, etc.
     935             :    */
     936             :   void set_vector_preservation (const std::string & vec_name, bool preserve);
     937             : 
     938             :   /**
     939             :    * \returns The boolean describing whether the vector identified by
     940             :    * vec_name should be "preserved": projected to new meshes, saved,
     941             :    * etc.
     942             :    */
     943             :   bool vector_preservation (std::string_view vec_name) const;
     944             : 
     945             :   /**
     946             :    * \returns A reference to one of the system's adjoint solution
     947             :    * vectors, by default the one corresponding to the first qoi.
     948             :    * Creates the vector if it doesn't already exist.
     949             :    */
     950             :   NumericVector<Number> & add_adjoint_solution(unsigned int i=0);
     951             : 
     952             :   /**
     953             :    * \returns A reference to one of the system's adjoint solution
     954             :    * vectors, by default the one corresponding to the first qoi.
     955             :    */
     956             :   NumericVector<Number> & get_adjoint_solution(unsigned int i=0);
     957             : 
     958             :   /**
     959             :    * \returns A reference to one of the system's adjoint solution
     960             :    * vectors, by default the one corresponding to the first qoi.
     961             :    */
     962             :   const NumericVector<Number> & get_adjoint_solution(unsigned int i=0) const;
     963             : 
     964             :   /**
     965             :    * \returns A reference to one of the system's solution sensitivity
     966             :    * vectors, by default the one corresponding to the first parameter.
     967             :    * Creates the vector if it doesn't already exist.
     968             :    */
     969             :   NumericVector<Number> & add_sensitivity_solution(unsigned int i=0);
     970             : 
     971             :   /**
     972             :    * \returns A reference to one of the system's solution sensitivity
     973             :    * vectors, by default the one corresponding to the first parameter.
     974             :    */
     975             :   NumericVector<Number> & get_sensitivity_solution(unsigned int i=0);
     976             : 
     977             :   /**
     978             :    * \returns A reference to one of the system's solution sensitivity
     979             :    * vectors, by default the one corresponding to the first parameter.
     980             :    */
     981             :   const NumericVector<Number> & get_sensitivity_solution(unsigned int i=0) const;
     982             : 
     983             :   /**
     984             :    * \returns A reference to one of the system's weighted sensitivity
     985             :    * adjoint solution vectors, by default the one corresponding to the
     986             :    * first qoi.
     987             :    * Creates the vector if it doesn't already exist.
     988             :    */
     989             :   NumericVector<Number> & add_weighted_sensitivity_adjoint_solution(unsigned int i=0);
     990             : 
     991             :   /**
     992             :    * \returns A reference to one of the system's weighted sensitivity
     993             :    * adjoint solution vectors, by default the one corresponding to the
     994             :    * first qoi.
     995             :    */
     996             :   NumericVector<Number> & get_weighted_sensitivity_adjoint_solution(unsigned int i=0);
     997             : 
     998             :   /**
     999             :    * \returns A reference to one of the system's weighted sensitivity
    1000             :    * adjoint solution vectors, by default the one corresponding to the
    1001             :    * first qoi.
    1002             :    */
    1003             :   const NumericVector<Number> & get_weighted_sensitivity_adjoint_solution(unsigned int i=0) const;
    1004             : 
    1005             :   /**
    1006             :    * \returns A reference to the solution of the last weighted
    1007             :    * sensitivity solve
    1008             :    * Creates the vector if it doesn't already exist.
    1009             :    */
    1010             :   NumericVector<Number> & add_weighted_sensitivity_solution();
    1011             : 
    1012             :   /**
    1013             :    * \returns A reference to the solution of the last weighted
    1014             :    * sensitivity solve
    1015             :    */
    1016             :   NumericVector<Number> & get_weighted_sensitivity_solution();
    1017             : 
    1018             :   /**
    1019             :    * \returns A reference to the solution of the last weighted
    1020             :    * sensitivity solve
    1021             :    */
    1022             :   const NumericVector<Number> & get_weighted_sensitivity_solution() const;
    1023             : 
    1024             :   /**
    1025             :    * \returns A reference to one of the system's adjoint rhs
    1026             :    * vectors, by default the one corresponding to the first qoi.
    1027             :    * Creates the vector if it doesn't already exist.
    1028             :    */
    1029             :   NumericVector<Number> & add_adjoint_rhs(unsigned int i=0);
    1030             : 
    1031             :   /**
    1032             :    * \returns A reference to one of the system's adjoint rhs
    1033             :    * vectors, by default the one corresponding to the first qoi.
    1034             :    * This what the user's QoI derivative code should assemble
    1035             :    * when setting up an adjoint problem
    1036             :    */
    1037             :   NumericVector<Number> & get_adjoint_rhs(unsigned int i=0);
    1038             : 
    1039             :   /**
    1040             :    * \returns A reference to one of the system's adjoint rhs
    1041             :    * vectors, by default the one corresponding to the first qoi.
    1042             :    */
    1043             :   const NumericVector<Number> & get_adjoint_rhs(unsigned int i=0) const;
    1044             : 
    1045             :   /**
    1046             :    * \returns A reference to one of the system's sensitivity rhs
    1047             :    * vectors, by default the one corresponding to the first parameter.
    1048             :    * Creates the vector if it doesn't already exist.
    1049             :    */
    1050             :   NumericVector<Number> & add_sensitivity_rhs(unsigned int i=0);
    1051             : 
    1052             :   /**
    1053             :    * \returns A reference to one of the system's sensitivity rhs
    1054             :    * vectors, by default the one corresponding to the first parameter.
    1055             :    * By default these vectors are built by the library, using finite
    1056             :    * differences, when \p assemble_residual_derivatives() is called.
    1057             :    *
    1058             :    * When assembled, this vector should hold
    1059             :    * -(partial R / partial p_i)
    1060             :    */
    1061             :   NumericVector<Number> & get_sensitivity_rhs(unsigned int i=0);
    1062             : 
    1063             :   /**
    1064             :    * \returns A reference to one of the system's sensitivity rhs
    1065             :    * vectors, by default the one corresponding to the first parameter.
    1066             :    */
    1067             :   const NumericVector<Number> & get_sensitivity_rhs(unsigned int i=0) const;
    1068             : 
    1069             :   /**
    1070             :    * \returns The number of vectors (in addition to the solution)
    1071             :    * handled by this system
    1072             :    * This is the size of the \p _vectors map
    1073             :    */
    1074             :   unsigned int n_vectors () const;
    1075             : 
    1076             :   /**
    1077             :    * \returns The number of matrices
    1078             :    * handled by this system.
    1079             :    * This is the size of the \p _matrices map
    1080             :    */
    1081             :   unsigned int n_matrices () const;
    1082             : 
    1083             :   /**
    1084             :    * \returns The number of variables in the system
    1085             :    */
    1086             :   unsigned int n_vars() const;
    1087             : 
    1088             :   /**
    1089             :    * \returns The number of \p VariableGroup variable groups in the system
    1090             :    */
    1091             :   unsigned int n_variable_groups() const;
    1092             : 
    1093             :   /**
    1094             :    * \returns The total number of scalar components in the system's
    1095             :    * variables.  This will equal \p n_vars() in the case of all
    1096             :    * scalar-valued variables.
    1097             :    */
    1098             :   unsigned int n_components() const;
    1099             : 
    1100             :   /**
    1101             :    * \returns The number of degrees of freedom in the system
    1102             :    */
    1103             :   dof_id_type n_dofs() const;
    1104             : 
    1105             :   /**
    1106             :    * \returns The number of active degrees of freedom
    1107             :    * for this System.
    1108             :    */
    1109             :   dof_id_type n_active_dofs() const;
    1110             : 
    1111             :   /**
    1112             :    * \returns The total number of constrained degrees of freedom
    1113             :    * in the system.
    1114             :    */
    1115             :   dof_id_type n_constrained_dofs() const;
    1116             : 
    1117             :   /**
    1118             :    * \returns The number of constrained degrees of freedom
    1119             :    * on this processor.
    1120             :    */
    1121             :   dof_id_type n_local_constrained_dofs() const;
    1122             : 
    1123             :   /**
    1124             :    * \returns The number of degrees of freedom local
    1125             :    * to this processor
    1126             :    */
    1127             :   dof_id_type n_local_dofs() const;
    1128             : 
    1129             :   /**
    1130             :    * Adds the variable \p var to the list of variables
    1131             :    * for this system. If \p active_subdomains is either \p nullptr
    1132             :    * (the default) or points to an empty set, then it will be assumed that
    1133             :    * \p var has no subdomain restrictions
    1134             :    *
    1135             :    * \returns The index number for the new variable.
    1136             :    */
    1137             :   unsigned int add_variable (std::string_view var,
    1138             :                              const FEType & type,
    1139             :                              const std::set<subdomain_id_type> * const active_subdomains = nullptr);
    1140             : 
    1141             :   /**
    1142             :    * Adds the variable \p var to the list of variables
    1143             :    * for this system.  Same as before, but assumes \p LAGRANGE
    1144             :    * as default value for \p FEType.family. If \p active_subdomains is either
    1145             :    * \p nullptr (the default) or points to an empty set, then it will be assumed
    1146             :    * that \p var has no subdomain restrictions
    1147             :    */
    1148             :   unsigned int add_variable (std::string_view var,
    1149             :                              const Order order = FIRST,
    1150             :                              const FEFamily = LAGRANGE,
    1151             :                              const std::set<subdomain_id_type> * const active_subdomains = nullptr);
    1152             : 
    1153             :   /**
    1154             :    * Adds the variable \p var to the list of variables
    1155             :    * for this system. If \p active_subdomains is either \p nullptr
    1156             :    * (the default) or points to an empty set, then it will be assumed that
    1157             :    * \p var has no subdomain restrictions
    1158             :    *
    1159             :    * \returns The index number for the new variable.
    1160             :    */
    1161             :   unsigned int add_variables (const std::vector<std::string> & vars,
    1162             :                               const FEType & type,
    1163             :                               const std::set<subdomain_id_type> * const active_subdomains = nullptr);
    1164             : 
    1165             :   /**
    1166             :    * Adds the variable \p var to the list of variables
    1167             :    * for this system.  Same as before, but assumes \p LAGRANGE
    1168             :    * as default value for \p FEType.family. If \p active_subdomains is either
    1169             :    * \p nullptr (the default) or points to an empty set, then it will be assumed that
    1170             :    * \p var has no subdomain restrictions
    1171             :    */
    1172             :   unsigned int add_variables (const std::vector<std::string> & vars,
    1173             :                               const Order order = FIRST,
    1174             :                               const FEFamily = LAGRANGE,
    1175             :                               const std::set<subdomain_id_type> * const active_subdomains = nullptr);
    1176             : 
    1177             :   /**
    1178             :    * Return a constant reference to \p Variable \p var.
    1179             :    */
    1180             :   const Variable & variable (unsigned int var) const;
    1181             : 
    1182             :   /**
    1183             :    * Return a constant reference to \p VariableGroup \p vg.
    1184             :    */
    1185             :   const VariableGroup & variable_group (unsigned int vg) const;
    1186             : 
    1187             :   /**
    1188             :    * \returns \p true if a variable named \p var exists in this System
    1189             :    */
    1190             :   bool has_variable(std::string_view var) const;
    1191             : 
    1192             :   /**
    1193             :    * \returns The name of variable \p i.
    1194             :    */
    1195             :   const std::string & variable_name(const unsigned int i) const;
    1196             : 
    1197             :   /**
    1198             :    * \returns The variable number associated with
    1199             :    * the user-specified variable named \p var.
    1200             :    */
    1201             :   unsigned int variable_number (std::string_view var) const;
    1202             : 
    1203             :   /**
    1204             :    * Fills \p all_variable_numbers with all the variable numbers for the
    1205             :    * variables that have been added to this system.
    1206             :    */
    1207             :   void get_all_variable_numbers(std::vector<unsigned int> & all_variable_numbers) const;
    1208             : 
    1209             :   /**
    1210             :    * \returns An index, starting from 0 for the first component of the
    1211             :    * first variable, and incrementing for each component of each
    1212             :    * (potentially vector-valued) variable in the system in order.
    1213             :    * For systems with only scalar-valued variables, this will be the
    1214             :    * same as \p variable_number(var)
    1215             :    *
    1216             :    * Irony: currently our only non-scalar-valued variable type is
    1217             :    * SCALAR.
    1218             :    */
    1219             :   unsigned int variable_scalar_number (std::string_view var,
    1220             :                                        unsigned int component) const;
    1221             : 
    1222             :   /**
    1223             :    * \returns An index, starting from 0 for the first component of the
    1224             :    * first variable, and incrementing for each component of each
    1225             :    * (potentially vector-valued) variable in the system in order.
    1226             :    * For systems with only scalar-valued variables, this will be the
    1227             :    * same as \p var_num
    1228             :    *
    1229             :    * Irony: currently our only non-scalar-valued variable type is
    1230             :    * SCALAR.
    1231             :    */
    1232             :   unsigned int variable_scalar_number (unsigned int var_num,
    1233             :                                        unsigned int component) const;
    1234             : 
    1235             : 
    1236             :   /**
    1237             :    * \returns The finite element type variable number \p i.
    1238             :    */
    1239             :   const FEType & variable_type (const unsigned int i) const;
    1240             : 
    1241             :   /**
    1242             :    * \returns The finite element type for variable \p var.
    1243             :    */
    1244             :   const FEType & variable_type (std::string_view var) const;
    1245             : 
    1246             :   /**
    1247             :    * \returns \p true when \p VariableGroup structures should be
    1248             :    * automatically identified, \p false otherwise.
    1249             :    */
    1250             :   bool identify_variable_groups () const;
    1251             : 
    1252             :   /**
    1253             :    * Toggle automatic \p VariableGroup identification.
    1254             :    */
    1255             :   void identify_variable_groups (const bool);
    1256             : 
    1257             :   /**
    1258             :    * \returns A norm of variable \p var in the vector \p v, in the specified
    1259             :    * norm (e.g. L2, L_INF, H1)
    1260             :    */
    1261             :   Real calculate_norm(const NumericVector<Number> & v,
    1262             :                       unsigned int var,
    1263             :                       FEMNormType norm_type,
    1264             :                       std::set<unsigned int> * skip_dimensions=nullptr) const;
    1265             : 
    1266             :   /**
    1267             :    * \returns A norm of the vector \p v, using \p component_norm and \p
    1268             :    * component_scale to choose and weight the norms of each variable.
    1269             :    */
    1270             :   Real calculate_norm(const NumericVector<Number> & v,
    1271             :                       const SystemNorm & norm,
    1272             :                       std::set<unsigned int> * skip_dimensions=nullptr) const;
    1273             : 
    1274             :   /**
    1275             :    * Reads the basic data header for this System.
    1276             :    */
    1277             :   void read_header (Xdr & io,
    1278             :                     std::string_view version,
    1279             :                     const bool read_header=true,
    1280             :                     const bool read_additional_data=true,
    1281             :                     const bool read_legacy_format=false);
    1282             : 
    1283             :   /**
    1284             :    * Reads additional data, namely vectors, for this System.
    1285             :    *
    1286             :    * \deprecated The ability to read XDR data files in the old (aka
    1287             :    * "legacy") XDR format has been deprecated for many years, this
    1288             :    * capability may soon disappear altogether.
    1289             :    */
    1290             : #ifdef LIBMESH_ENABLE_DEPRECATED
    1291             :   void read_legacy_data (Xdr & io,
    1292             :                          const bool read_additional_data=true);
    1293             : #endif
    1294             : 
    1295             :   /**
    1296             :    * Reads additional data, namely vectors, for this System.
    1297             :    * This method may safely be called on a distributed-memory mesh.
    1298             :    */
    1299             :   template <typename ValType>
    1300             :   void read_serialized_data (Xdr & io,
    1301             :                              const bool read_additional_data=true);
    1302             :   /**
    1303             :    * Non-templated version for backward compatibility.
    1304             :    *
    1305             :    * Reads additional data, namely vectors, for this System.
    1306             :    * This method may safely be called on a distributed-memory mesh.
    1307             :    */
    1308           0 :   void read_serialized_data (Xdr & io,
    1309             :                              const bool read_additional_data=true)
    1310           0 :   { read_serialized_data<Number>(io, read_additional_data); }
    1311             : 
    1312             :   /**
    1313             :    * Read a number of identically distributed vectors.  This method
    1314             :    * allows for optimization for the multiple vector case by only communicating
    1315             :    * the metadata once.
    1316             :    */
    1317             :   template <typename InValType>
    1318             :   std::size_t read_serialized_vectors (Xdr & io,
    1319             :                                        const std::vector<NumericVector<Number> *> & vectors) const;
    1320             : 
    1321             :   /**
    1322             :    * Non-templated version for backward compatibility.
    1323             :    *
    1324             :    * Read a number of identically distributed vectors.  This method
    1325             :    * allows for optimization for the multiple vector case by only communicating
    1326             :    * the metadata once.
    1327             :    */
    1328           8 :   std::size_t read_serialized_vectors (Xdr & io,
    1329             :                                        const std::vector<NumericVector<Number> *> & vectors) const
    1330         284 :   { return read_serialized_vectors<Number>(io, vectors); }
    1331             : 
    1332             :   /**
    1333             :    * Reads additional data, namely vectors, for this System.
    1334             :    * This method may safely be called on a distributed-memory mesh.
    1335             :    * This method will read an individual file for each processor in the simulation
    1336             :    * where the local solution components for that processor are stored.
    1337             :    */
    1338             :   template <typename InValType>
    1339             :   void read_parallel_data (Xdr & io,
    1340             :                            const bool read_additional_data);
    1341             : 
    1342             :   /**
    1343             :    * Non-templated version for backward compatibility.
    1344             :    *
    1345             :    * Reads additional data, namely vectors, for this System.
    1346             :    * This method may safely be called on a distributed-memory mesh.
    1347             :    * This method will read an individual file for each processor in the simulation
    1348             :    * where the local solution components for that processor are stored.
    1349             :    */
    1350             :   void read_parallel_data (Xdr & io,
    1351             :                            const bool read_additional_data)
    1352             :   { read_parallel_data<Number>(io, read_additional_data); }
    1353             : 
    1354             :   /**
    1355             :    * Writes the basic data header for this System.
    1356             :    */
    1357             :   void write_header (Xdr & io,
    1358             :                      std::string_view version,
    1359             :                      const bool write_additional_data) const;
    1360             : 
    1361             :   /**
    1362             :    * Writes additional data, namely vectors, for this System.
    1363             :    * This method may safely be called on a distributed-memory mesh.
    1364             :    */
    1365             :   void write_serialized_data (Xdr & io,
    1366             :                               const bool write_additional_data = true) const;
    1367             : 
    1368             :   /**
    1369             :    * Serialize & write a number of identically distributed vectors.  This method
    1370             :    * allows for optimization for the multiple vector case by only communicating
    1371             :    * the metadata once.
    1372             :    */
    1373             :   std::size_t write_serialized_vectors (Xdr & io,
    1374             :                                         const std::vector<const NumericVector<Number> *> & vectors) const;
    1375             : 
    1376             :   /**
    1377             :    * Writes additional data, namely vectors, for this System.
    1378             :    * This method may safely be called on a distributed-memory mesh.
    1379             :    * This method will create an individual file for each processor in the simulation
    1380             :    * where the local solution components for that processor will be stored.
    1381             :    */
    1382             :   void write_parallel_data (Xdr & io,
    1383             :                             const bool write_additional_data) const;
    1384             : 
    1385             :   /**
    1386             :    * \returns A string containing information about the
    1387             :    * system.
    1388             :    */
    1389             :   std::string get_info () const;
    1390             : 
    1391             :   /**
    1392             :    * Register a user function to use in initializing the system.
    1393             :    */
    1394             :   void attach_init_function (void fptr(EquationSystems & es,
    1395             :                                        const std::string & name));
    1396             : 
    1397             :   /**
    1398             :    * Register a user class to use to initialize the system.
    1399             :    *
    1400             :    * \note This is exclusive with the \p attach_init_function.
    1401             :    */
    1402             :   void attach_init_object (Initialization & init);
    1403             : 
    1404             :   /**
    1405             :    * Register a user function to use in assembling the system
    1406             :    * matrix and RHS.
    1407             :    */
    1408             :   void attach_assemble_function (void fptr(EquationSystems & es,
    1409             :                                            const std::string & name));
    1410             : 
    1411             :   /**
    1412             :    * Register a user object to use in assembling the system
    1413             :    * matrix and RHS.
    1414             :    */
    1415             :   void attach_assemble_object (Assembly & assemble);
    1416             : 
    1417             :   /**
    1418             :    * Register a user function for imposing constraints.
    1419             :    */
    1420             :   void attach_constraint_function (void fptr(EquationSystems & es,
    1421             :                                              const std::string & name));
    1422             : 
    1423             :   /**
    1424             :    * Register a user object for imposing constraints.
    1425             :    */
    1426             :   void attach_constraint_object (Constraint & constrain);
    1427             : 
    1428             :   /**
    1429             :    * \returns true if there is a user-defined constraint object
    1430             :    * attached to this object, false otherwise.  Calling System::
    1431             :    * get_constraint_object() when there is no user-defined constraint
    1432             :    * object attached leads to either undefined behavior (dereferencing
    1433             :    * a nullptr) or an assert (in dbg mode) so you should call this
    1434             :    * function first unless you are sure there is a user-defined
    1435             :    * constraint object attached.
    1436             :    */
    1437             :   bool has_constraint_object () const;
    1438             : 
    1439             :   /**
    1440             :    * Return the user object for imposing constraints.
    1441             :    */
    1442             :   Constraint& get_constraint_object ();
    1443             : 
    1444             :   /**
    1445             :    * Register a user function for evaluating the quantities of interest,
    1446             :    * whose values should be placed in \p System::qoi
    1447             :    */
    1448             :   void attach_QOI_function (void fptr(EquationSystems & es,
    1449             :                                       const std::string & name,
    1450             :                                       const QoISet & qoi_indices));
    1451             : 
    1452             :   /**
    1453             :    * Register a user object for evaluating the quantities of interest,
    1454             :    * whose values should be placed in \p System::qoi
    1455             :    */
    1456             :   void attach_QOI_object (QOI & qoi);
    1457             : 
    1458             :   /**
    1459             :    * Register a user function for evaluating derivatives of a quantity
    1460             :    * of interest with respect to test functions, whose values should
    1461             :    * be placed in \p System::rhs
    1462             :    */
    1463             :   void attach_QOI_derivative (void fptr(EquationSystems & es,
    1464             :                                         const std::string & name,
    1465             :                                         const QoISet & qoi_indices,
    1466             :                                         bool include_liftfunc,
    1467             :                                         bool apply_constraints));
    1468             : 
    1469             :   /**
    1470             :    * Register a user object for evaluating derivatives of a quantity
    1471             :    * of interest with respect to test functions, whose values should
    1472             :    * be placed in \p System::rhs
    1473             :    */
    1474             :   void attach_QOI_derivative_object (QOIDerivative & qoi_derivative);
    1475             : 
    1476             :   /**
    1477             :    * Calls user's attached initialization function, or is overridden by
    1478             :    * the user in derived classes.
    1479             :    */
    1480             :   virtual void user_initialization ();
    1481             : 
    1482             :   /**
    1483             :    * Calls user's attached assembly function, or is overridden by
    1484             :    * the user in derived classes.
    1485             :    */
    1486             :   virtual void user_assembly ();
    1487             : 
    1488             :   /**
    1489             :    * Calls user's attached constraint function, or is overridden by
    1490             :    * the user in derived classes.
    1491             :    */
    1492             :   virtual void user_constrain ();
    1493             : 
    1494             :   /**
    1495             :    * Calls user's attached quantity of interest function, or is
    1496             :    * overridden by the user in derived classes.
    1497             :    */
    1498             :   virtual void user_QOI (const QoISet & qoi_indices);
    1499             : 
    1500             :   /**
    1501             :    * Calls user's attached quantity of interest derivative function,
    1502             :    * or is overridden by the user in derived classes.
    1503             :    */
    1504             :   virtual void user_QOI_derivative (const QoISet & qoi_indices = QoISet(),
    1505             :                                     bool include_liftfunc = true,
    1506             :                                     bool apply_constraints = true);
    1507             : 
    1508             :   /**
    1509             :    * Re-update the local values when the mesh has changed.
    1510             :    * This method takes the data updated by \p update() and
    1511             :    * makes it up-to-date on the current mesh.
    1512             :    */
    1513             :   virtual void re_update ();
    1514             : 
    1515             :   /**
    1516             :    * Restrict vectors after the mesh has coarsened
    1517             :    */
    1518             :   virtual void restrict_vectors ();
    1519             : 
    1520             :   /**
    1521             :    * Prolong vectors after the mesh has refined
    1522             :    */
    1523             :   virtual void prolong_vectors ();
    1524             : 
    1525             :   /// Parameters for the system. If a parameter is not provided, it should be retrieved from the EquationSystems
    1526             :   Parameters parameters;
    1527             : 
    1528             :   /**
    1529             :    * Flag which tells the system to whether or not to
    1530             :    * call the user assembly function during each call to solve().
    1531             :    * By default, every call to solve() begins with a call to the
    1532             :    * user assemble, so this flag is true.  (For explicit systems,
    1533             :    * "solving" the system occurs during the assembly step, so this
    1534             :    * flag is always true for explicit systems.)
    1535             :    *
    1536             :    * You will only want to set this to false if you need direct
    1537             :    * control over when the system is assembled, and are willing to
    1538             :    * track the state of its assembly yourself.  An example of such a
    1539             :    * case is an implicit system with multiple right hand sides.  In
    1540             :    * this instance, a single assembly would likely be followed with
    1541             :    * multiple calls to solve.
    1542             :    *
    1543             :    * The frequency system and Newmark system have their own versions
    1544             :    * of this flag, called _finished_assemble, which might be able to
    1545             :    * be replaced with this more general concept.
    1546             :    */
    1547             :   bool assemble_before_solve;
    1548             : 
    1549             :   /**
    1550             :    * Avoids use of any cached data that might affect any solve result.  Should
    1551             :    * be overridden in derived systems.
    1552             :    */
    1553             :   virtual void disable_cache ();
    1554             : 
    1555             :   /**
    1556             :    * A boolean to be set to true by systems using elem_fixed_solution,
    1557             :    * for optional use by e.g. stabilized methods.
    1558             :    * False by default.
    1559             :    *
    1560             :    * \note For FEMSystem users, if this variable is set to true, it
    1561             :    * must be before init_data() is called.
    1562             :    */
    1563             :   bool use_fixed_solution;
    1564             : 
    1565             :   /**
    1566             :    * A member int that can be employed to indicate increased or
    1567             :    * reduced quadrature order.
    1568             :    *
    1569             :    * \note For FEMSystem users, by default, when calling the
    1570             :    * user-defined residual functions, the FEMSystem will first set up
    1571             :    * an appropriate FEType::default_quadrature_rule() object for
    1572             :    * performing the integration.  This rule will integrate elements of
    1573             :    * order up to 2*p+1 exactly (where p is the sum of the base FEType
    1574             :    * and local p refinement levels), but if additional (or reduced)
    1575             :    * quadrature accuracy is desired then this extra_quadrature_order
    1576             :    * (default 0) will be added.
    1577             :    */
    1578             :   int extra_quadrature_order;
    1579             : 
    1580             : 
    1581             :   //--------------------------------------------------
    1582             :   // The solution and solution access members
    1583             : 
    1584             :   /**
    1585             :    * \returns The current solution for the specified global
    1586             :    * DOF.
    1587             :    */
    1588             :   Number current_solution (const dof_id_type global_dof_number) const;
    1589             : 
    1590             :   /**
    1591             :    * Data structure to hold solution values.
    1592             :    */
    1593             :   std::unique_ptr<NumericVector<Number>> solution;
    1594             : 
    1595             :   /**
    1596             :    * All the values I need to compute my contribution
    1597             :    * to the simulation at hand.  Think of this as the
    1598             :    * current solution with any ghost values needed from
    1599             :    * other processors.  This vector is necessarily larger
    1600             :    * than the \p solution vector in the case of a parallel
    1601             :    * simulation.  The \p update() member is used to synchronize
    1602             :    * the contents of the \p solution and \p current_local_solution
    1603             :    * vectors.
    1604             :    */
    1605             :   std::unique_ptr<NumericVector<Number>> current_local_solution;
    1606             : 
    1607             :   /**
    1608             :    * For time-dependent problems, this is the time t at the beginning of
    1609             :    * the current timestep.
    1610             :    *
    1611             :    * \note For DifferentiableSystem users: do \e not access this time
    1612             :    * during an assembly!  Use the DiffContext::time value instead to
    1613             :    * get correct results.
    1614             :    */
    1615             :   Real time;
    1616             : 
    1617             :   /**
    1618             :    * Number of currently active quantities of interest.
    1619             :    */
    1620             :   unsigned int n_qois() const;
    1621             : 
    1622             : #ifndef LIBMESH_ENABLE_DEPRECATED // We use accessors for these now
    1623             : private:
    1624             : #endif
    1625             :   /**
    1626             :    * Values of the quantities of interest.  This vector needs
    1627             :    * to be both resized and filled by the user before any quantity of
    1628             :    * interest assembly is done and before any sensitivities are
    1629             :    * calculated.
    1630             :    */
    1631             :   std::vector<Number> qoi;
    1632             : 
    1633             :   /**
    1634             :    * Vector to hold error estimates for qois, either from a steady
    1635             :    * state calculation, or from a single unsteady solver timestep. Used
    1636             :    * by the library after resizing to match the size of the qoi vector.
    1637             :    * User code can use this for accumulating error estimates for example.
    1638             :    */
    1639             :   std::vector<Number> qoi_error_estimates;
    1640             : #ifndef LIBMESH_ENABLE_DEPRECATED
    1641             : public:
    1642             : #endif
    1643             : 
    1644             :   /**
    1645             :    * Accessors for qoi and qoi_error_estimates vectors
    1646             :    */
    1647             :   void init_qois(unsigned int n_qois);
    1648             : 
    1649             :   void set_qoi(unsigned int qoi_index, Number qoi_value);
    1650             :   Number get_qoi_value(unsigned int qoi_index) const;
    1651             : 
    1652             :   void set_qoi(std::vector<Number> new_qoi);
    1653             : 
    1654             :   /**
    1655             :    * Returns a *copy* of qoi, not a reference
    1656             :    */
    1657             :   std::vector<Number> get_qoi_values() const;
    1658             : 
    1659             :   void set_qoi_error_estimate(unsigned int qoi_index, Number qoi_error_estimate);
    1660             :   Number get_qoi_error_estimate_value(unsigned int qoi_index) const;
    1661             : 
    1662             :   /**
    1663             :    * \returns The value of the solution variable \p var at the physical
    1664             :    * point \p p in the mesh, without knowing a priori which element
    1665             :    * contains \p p, using the degree of freedom coefficients in \p sol
    1666             :    * (or in \p current_local_solution if \p sol is left null).
    1667             :    *
    1668             :    * \note This function uses \p MeshBase::sub_point_locator(); users
    1669             :    * may or may not want to call \p MeshBase::clear_point_locator()
    1670             :    * afterward.  Also, point_locator() is expensive (N log N for
    1671             :    * initial construction, log N for evaluations).  Avoid using this
    1672             :    * function in any context where you are already looping over
    1673             :    * elements.
    1674             :    *
    1675             :    * Because the element containing \p p may lie on any processor,
    1676             :    * this function is parallel-only.
    1677             :    *
    1678             :    * By default this method expects the point to reside inside the domain
    1679             :    * and will abort if no element can be found which contains \p p.  The
    1680             :    * optional parameter \p insist_on_success can be set to false to allow
    1681             :    * the method to return 0 when the point is not located.
    1682             :    */
    1683             :   Number point_value(unsigned int var, const Point & p,
    1684             :                      const bool insist_on_success = true,
    1685             :                      const NumericVector<Number> * sol = nullptr) const;
    1686             : 
    1687             :   /**
    1688             :    * \returns The value of the solution variable \p var at the physical
    1689             :    * point \p p contained in local Elem \p e, using the degree of
    1690             :    * freedom coefficients in \p sol (or in \p current_local_solution
    1691             :    * if \p sol is left null).
    1692             :    *
    1693             :    * This version of point_value can be run in serial, but assumes \p e is in
    1694             :    * the local mesh partition or is algebraically ghosted.
    1695             :    */
    1696             :   Number point_value(unsigned int var, const Point & p, const Elem & e,
    1697             :                      const NumericVector<Number> * sol = nullptr) const;
    1698             : 
    1699             :   /**
    1700             :    * Calls the version of point_value() which takes a reference.
    1701             :    * This function exists only to prevent people from calling the
    1702             :    * version of point_value() that has a boolean third argument, which
    1703             :    * would result in unnecessary PointLocator calls.
    1704             :    */
    1705             :   Number point_value(unsigned int var, const Point & p, const Elem * e) const;
    1706             : 
    1707             :   /**
    1708             :    * Calls the parallel version of point_value().
    1709             :    * This function exists only to prevent people from accidentally
    1710             :    * calling the version of point_value() that has a boolean third
    1711             :    * argument, which would result in incorrect output.
    1712             :    */
    1713             :   Number point_value(unsigned int var, const Point & p, const NumericVector<Number> * sol) const;
    1714             : 
    1715             :   /**
    1716             :    * \returns The gradient of the solution variable \p var at the physical
    1717             :    * point \p p in the mesh, similarly to point_value.
    1718             :    */
    1719             :   Gradient point_gradient(unsigned int var, const Point & p,
    1720             :                           const bool insist_on_success = true,
    1721             :                           const NumericVector<Number> * sol = nullptr) const;
    1722             : 
    1723             :   /**
    1724             :    * \returns The gradient of the solution variable \p var at the physical
    1725             :    * point \p p in local Elem \p e in the mesh, similarly to point_value.
    1726             :    */
    1727             :   Gradient point_gradient(unsigned int var, const Point & p, const Elem & e,
    1728             :                           const NumericVector<Number> * sol = nullptr) const;
    1729             : 
    1730             :   /**
    1731             :    * Calls the version of point_gradient() which takes a reference.
    1732             :    * This function exists only to prevent people from calling the
    1733             :    * version of point_gradient() that has a boolean third argument, which
    1734             :    * would result in unnecessary PointLocator calls.
    1735             :    */
    1736             :   Gradient point_gradient(unsigned int var, const Point & p, const Elem * e) const;
    1737             : 
    1738             :   /**
    1739             :    * Calls the parallel version of point_gradient().
    1740             :    * This function exists only to prevent people from accidentally
    1741             :    * calling the version of point_gradient() that has a boolean third
    1742             :    * argument, which would result in incorrect output.
    1743             :    */
    1744             :   Gradient point_gradient(unsigned int var, const Point & p, const NumericVector<Number> * sol) const;
    1745             : 
    1746             :   /**
    1747             :    * \returns The second derivative tensor of the solution variable \p var
    1748             :    * at the physical point \p p in the mesh, similarly to point_value.
    1749             :    */
    1750             :   Tensor point_hessian(unsigned int var, const Point & p,
    1751             :                        const bool insist_on_success = true,
    1752             :                        const NumericVector<Number> * sol = nullptr) const;
    1753             : 
    1754             :   /**
    1755             :    * \returns The second derivative tensor of the solution variable \p var
    1756             :    * at the physical point \p p in local Elem \p e in the mesh, similarly to
    1757             :    * point_value.
    1758             :    */
    1759             :   Tensor point_hessian(unsigned int var, const Point & p, const Elem & e,
    1760             :                        const NumericVector<Number> * sol = nullptr) const;
    1761             : 
    1762             :   /**
    1763             :    * Calls the version of point_hessian() which takes a reference.
    1764             :    * This function exists only to prevent people from calling the
    1765             :    * version of point_hessian() that has a boolean third argument, which
    1766             :    * would result in unnecessary PointLocator calls.
    1767             :    */
    1768             :   Tensor point_hessian(unsigned int var, const Point & p, const Elem * e) const;
    1769             : 
    1770             :   /**
    1771             :    * Calls the parallel version of point_hessian().
    1772             :    * This function exists only to prevent people from accidentally
    1773             :    * calling the version of point_hessian() that has a boolean third
    1774             :    * argument, which would result in incorrect output.
    1775             :    */
    1776             :   Tensor point_hessian(unsigned int var, const Point & p, const NumericVector<Number> * sol) const;
    1777             : 
    1778             : 
    1779             :   /**
    1780             :    * Fills the std::set with the degrees of freedom on the local
    1781             :    * processor corresponding the the variable number passed in.
    1782             :    */
    1783             :   void local_dof_indices (const unsigned int var,
    1784             :                           std::set<dof_id_type> & var_indices) const;
    1785             : 
    1786             :   /**
    1787             :    * Zeroes all dofs in \p v that correspond to variable number \p
    1788             :    * var_num.
    1789             :    */
    1790             :   void zero_variable (NumericVector<Number> & v, unsigned int var_num) const;
    1791             : 
    1792             :   /**
    1793             :    * Setter and getter functions for project_with_constraints boolean
    1794             :    */
    1795         476 :   bool get_project_with_constraints()
    1796             :   {
    1797       16190 :     return project_with_constraints;
    1798             :   }
    1799             : 
    1800         952 :   void set_project_with_constraints(bool _project_with_constraints)
    1801             :   {
    1802       32856 :     project_with_constraints = _project_with_constraints;
    1803         952 :   }
    1804             : 
    1805             :   /**
    1806             :    * \returns A writable reference to a boolean that determines if this system
    1807             :    * can be written to file or not.  If set to \p true, then
    1808             :    * \p EquationSystems::write will ignore this system.
    1809             :    */
    1810       11774 :   bool & hide_output() { return _hide_output; }
    1811             : 
    1812             : #ifdef LIBMESH_HAVE_METAPHYSICL
    1813             :   /**
    1814             :    * This method creates a projection matrix which corresponds to the
    1815             :    * operation of project_vector between old and new solution spaces.
    1816             :    *
    1817             :    * Heterogeneous Dirichlet boundary conditions are *not* taken into
    1818             :    * account here; if this matrix is used for prolongation (mesh
    1819             :    * refinement) on a side with a heterogeneous BC, the newly created
    1820             :    * degrees of freedom on that side will still match the coarse grid
    1821             :    * approximation of the BC, not the fine grid approximation.
    1822             :    */
    1823             :   void projection_matrix (SparseMatrix<Number> & proj_mat) const;
    1824             : #endif // LIBMESH_HAVE_METAPHYSICL
    1825             : 
    1826             :   /**
    1827             :    * Adds the additional matrix \p mat_name to this system.  Only
    1828             :    * allowed prior to \p assemble().  All additional matrices
    1829             :    * have the same sparsity pattern as the matrix used during
    1830             :    * solution.  When not \p System but the user wants to
    1831             :    * initialize the main/system matrix, then all the additional matrices,
    1832             :    * if existent, have to be initialized by the user, too.
    1833             :    *
    1834             :    * This non-template method will add a derived matrix type corresponding to
    1835             :    * the solver package. If the user wishes to specify the matrix type to add,
    1836             :    * use the templated \p add_matrix method instead
    1837             :    *
    1838             :    * @param mat_name A name for the matrix
    1839             :    * @param type The serial/parallel/ghosted type of the matrix
    1840             :    * @param mat_build_type The matrix type to build
    1841             :    *
    1842             :    */
    1843             :   SparseMatrix<Number> & add_matrix (std::string_view mat_name,
    1844             :                                      ParallelType type = PARALLEL,
    1845             :                                      MatrixBuildType mat_build_type = MatrixBuildType::AUTOMATIC);
    1846             : 
    1847             :   /**
    1848             :   * Adds the additional matrix \p mat_name to this system.  Only
    1849             :   * allowed prior to \p assemble().  All additional matrices
    1850             :   * have the same sparsity pattern as the matrix used during
    1851             :   * solution.  When not \p System but the user wants to
    1852             :   * initialize the main/system matrix, then all the additional matrices,
    1853             :   * if existent, have to be initialized by the user, too.
    1854             :   *
    1855             :   * This method will create add a derived matrix of type
    1856             :   * \p MatrixType<Number>. One can use the non-templated \p add_matrix method to
    1857             :   * add a matrix corresponding to the default solver package
    1858             :   *
    1859             :   * @param mat_name A name for the matrix
    1860             :   * @param type The serial/parallel/ghosted type of the matrix
    1861             :   */
    1862             :   template <template <typename> class>
    1863             :   SparseMatrix<Number> & add_matrix (std::string_view mat_name, ParallelType = PARALLEL);
    1864             : 
    1865             :   /**
    1866             :    * Adds the additional matrix \p mat_name to this system.  Only
    1867             :    * allowed prior to \p assemble().  All additional matrices
    1868             :    * have the same sparsity pattern as the matrix used during
    1869             :    * solution.  When not \p System but the user wants to
    1870             :    * initialize the main/system matrix, then all the additional matrices,
    1871             :    * if existent, have to be initialized by the user, too.
    1872             :    *
    1873             :    * @param mat_name A name for the matrix
    1874             :    * @param matrix The matrix we are handing over the \p System for ownership
    1875             :    * @param type The serial/parallel/ghosted type of the matrix
    1876             :    *
    1877             :    */
    1878             :   SparseMatrix<Number> & add_matrix (std::string_view mat_name,
    1879             :                                      std::unique_ptr<SparseMatrix<Number>> matrix,
    1880             :                                      ParallelType type = PARALLEL);
    1881             : 
    1882             :   /**
    1883             :    * Removes the additional matrix \p mat_name from this system
    1884             :    */
    1885             :   void remove_matrix(std::string_view mat_name);
    1886             : 
    1887             :   /**
    1888             :    * \returns \p true if this \p System has a matrix associated with the
    1889             :    * given name, \p false otherwise.
    1890             :    */
    1891           0 :   inline bool have_matrix (std::string_view mat_name) const { return _matrices.count(mat_name); }
    1892             : 
    1893             :   /**
    1894             :    * \returns A const pointer to this system's additional matrix
    1895             :    * named \p mat_name, or \p nullptr if no matrix by that name
    1896             :    * exists.
    1897             :    */
    1898             :   const SparseMatrix<Number> * request_matrix (std::string_view mat_name) const;
    1899             : 
    1900             :   /**
    1901             :    * \returns A writable pointer to this system's additional matrix
    1902             :    * named \p mat_name, or \p nullptr if no matrix by that name
    1903             :    * exists.
    1904             :    */
    1905             :   SparseMatrix<Number> * request_matrix (std::string_view mat_name);
    1906             : 
    1907             :   /**
    1908             :    * \returns A const reference to this system's matrix
    1909             :    * named \p mat_name.
    1910             :    */
    1911             :   const SparseMatrix<Number> & get_matrix (std::string_view mat_name) const;
    1912             : 
    1913             :   /**
    1914             :    * \returns A writable reference to this system's matrix
    1915             :    * named \p mat_name.
    1916             :    */
    1917             :   SparseMatrix<Number> & get_matrix (std::string_view mat_name);
    1918             : 
    1919             :   /**
    1920             :    * Sets whether to use hash table matrix assembly if the matrix sub-classes support it
    1921             :    */
    1922             :   void prefer_hash_table_matrix_assembly(bool preference);
    1923             : 
    1924             :   /**
    1925             :    * Instructs this system to prefix solve options with its name for solvers that leverage prefixes
    1926             :    */
    1927           0 :   void prefix_with_name(bool value) { _prefix_with_name = value; }
    1928             : 
    1929             :   /**
    1930             :    * @returns Whether we are name prefixing
    1931             :    */
    1932      224786 :   [[nodiscard]] bool prefix_with_name() const { return _prefix_with_name; }
    1933             : 
    1934             :   /**
    1935             :    * @returns A prefix that may be applied to solver options. Note that this
    1936             :    * prefix is only used if \p prefix_with_name()
    1937             :    */
    1938           0 :   std::string prefix() const { return this->name() + "_"; }
    1939             : 
    1940             :   /**
    1941             :    * Request that static condensation be performed for this system
    1942             :    */
    1943             :    virtual void create_static_condensation();
    1944             : 
    1945             :    /**
    1946             :     * @returns Whether this system will be statically condensed
    1947             :     */
    1948             :    bool has_static_condensation() const;
    1949             : 
    1950             : protected:
    1951             : 
    1952             :   /**
    1953             :    * Initializes the data for the system.
    1954             :    *
    1955             :    * \note This is called before any user-supplied initialization
    1956             :    * function so that all required storage will be available.
    1957             :    */
    1958             :   virtual void init_data ();
    1959             : 
    1960             :   /**
    1961             :    * Insertion point for adding matrices in derived classes
    1962             :    * before init_matrices() is called.
    1963             :    */
    1964      219448 :   virtual void add_matrices() {}
    1965             : 
    1966             :   /**
    1967             :    * Initializes the matrices associated with this system.
    1968             :    */
    1969             :   virtual void init_matrices ();
    1970             : 
    1971             :   /**
    1972             :    * \returns Whether or not matrices can still be added without
    1973             :    * expensive per-matrix initialization.
    1974             :    */
    1975         272 :   bool can_add_matrices() const { return !_matrices_initialized; }
    1976             : 
    1977             :   /**
    1978             :    * Projects the vector defined on the old mesh onto the
    1979             :    * new mesh.
    1980             :    *
    1981             :    * Constrain the new vector using the requested adjoint rather than
    1982             :    * primal constraints if is_adjoint is non-negative.
    1983             :    */
    1984             :   void project_vector (NumericVector<Number> &,
    1985             :                        int is_adjoint = -1) const;
    1986             : 
    1987             :   /**
    1988             :    * Projects the vector defined on the old mesh onto the
    1989             :    * new mesh. The original vector is unchanged and the new vector
    1990             :    * is passed through the second argument.
    1991             :    *
    1992             :    * Constrain the new vector using the requested adjoint rather than
    1993             :    * primal constraints if is_adjoint is non-negative.
    1994             :    */
    1995             :   void project_vector (const NumericVector<Number> &,
    1996             :                        NumericVector<Number> &,
    1997             :                        int is_adjoint = -1) const;
    1998             : 
    1999             :   /*
    2000             :    * If we have e.g. a element space constrained by spline values, we
    2001             :    * can directly project only on the constrained basis; to get
    2002             :    * consistent constraining values we have to solve for them.
    2003             :    *
    2004             :    * Constrain the new vector using the requested adjoint rather than
    2005             :    * primal constraints if is_adjoint is non-negative.
    2006             :    */
    2007             :   void solve_for_unconstrained_dofs (NumericVector<Number> &,
    2008             :                                      int is_adjoint = -1) const;
    2009             : 
    2010             :   /**
    2011             :    * Whether this object should condense out constrained degrees of freedom
    2012             :    */
    2013         140 :   virtual bool condense_constrained_dofs() const { return false; }
    2014             : 
    2015             : private:
    2016             :   /**
    2017             :    * Helper function to keep DofMap forward declarable in system.h
    2018             :    */
    2019             :   void late_matrix_init(SparseMatrix<Number> & mat,
    2020             :                         ParallelType type);
    2021             : 
    2022             :   /**
    2023             :    * Finds the discrete norm for the entries in the vector
    2024             :    * corresponding to Dofs associated with var.
    2025             :    */
    2026             :   Real discrete_var_norm (const NumericVector<Number> & v,
    2027             :                           unsigned int var,
    2028             :                           FEMNormType norm_type) const;
    2029             : 
    2030             :   /**
    2031             :    * Reads an input vector from the stream \p io and assigns
    2032             :    * the values to a set of \p DofObjects.  This method uses
    2033             :    * blocked input and is safe to call on a distributed memory-mesh.
    2034             :    * Unless otherwise specified, all variables are read.
    2035             :    *
    2036             :    * If an entry in \p vecs is a null pointer, the corresponding data
    2037             :    * is read (incrementing the file read location) but discarded.
    2038             :    */
    2039             :   template <typename iterator_type, typename InValType>
    2040             :   std::size_t read_serialized_blocked_dof_objects (const dof_id_type n_objects,
    2041             :                                                    const iterator_type begin,
    2042             :                                                    const iterator_type end,
    2043             :                                                    const InValType dummy,
    2044             :                                                    Xdr & io,
    2045             :                                                    const std::vector<NumericVector<Number> *> & vecs,
    2046             :                                                    const unsigned int var_to_read=libMesh::invalid_uint) const;
    2047             : 
    2048             :   /**
    2049             :    * Reads the SCALAR dofs from the stream \p io and assigns the values
    2050             :    * to the appropriate entries of \p vec.
    2051             :    *
    2052             :    * \returns The number of dofs read.
    2053             :    *
    2054             :    * Reads data and discards it if \p vec is a null pointer.
    2055             :    */
    2056             :   unsigned int read_SCALAR_dofs (const unsigned int var,
    2057             :                                  Xdr & io,
    2058             :                                  NumericVector<Number> * vec) const;
    2059             : 
    2060             :   /**
    2061             :    * Reads a vector for this System.
    2062             :    * This method may safely be called on a distributed-memory mesh.
    2063             :    *
    2064             :    * \returns The length of the vector read.
    2065             :    *
    2066             :    * Reads data and discards it if \p vec is a null pointer.
    2067             :    */
    2068             :   template <typename InValType>
    2069             :   numeric_index_type read_serialized_vector (Xdr & io,
    2070             :                                              NumericVector<Number> * vec);
    2071             : 
    2072             :   /**
    2073             :    * Non-templated version for backward compatibility.
    2074             :    *
    2075             :    * Reads a vector for this System.
    2076             :    * This method may safely be called on a distributed-memory mesh.
    2077             :    *
    2078             :    * \returns The length of the vector read.
    2079             :    */
    2080             :   numeric_index_type read_serialized_vector (Xdr & io,
    2081             :                                              NumericVector<Number> & vec)
    2082             :   { return read_serialized_vector<Number>(io, &vec); }
    2083             : 
    2084             :   /**
    2085             :    * Writes an output vector to the stream \p io for a set of \p DofObjects.
    2086             :    * This method uses blocked output and is safe to call on a distributed memory-mesh.
    2087             :    *
    2088             :    * \returns The number of values written
    2089             :    */
    2090             :   template <typename iterator_type>
    2091             :   std::size_t write_serialized_blocked_dof_objects (const std::vector<const NumericVector<Number> *> & vecs,
    2092             :                                                     const dof_id_type n_objects,
    2093             :                                                     const iterator_type begin,
    2094             :                                                     const iterator_type end,
    2095             :                                                     Xdr & io,
    2096             :                                                     const unsigned int var_to_write=libMesh::invalid_uint) const;
    2097             : 
    2098             :   /**
    2099             :    * Writes the SCALAR dofs associated with var to the stream \p io.
    2100             :    *
    2101             :    * \returns The number of values written.
    2102             :    */
    2103             :   unsigned int write_SCALAR_dofs (const NumericVector<Number> & vec,
    2104             :                                   const unsigned int var,
    2105             :                                   Xdr & io) const;
    2106             : 
    2107             :   /**
    2108             :    * Writes a vector for this System.
    2109             :    * This method may safely be called on a distributed-memory mesh.
    2110             :    *
    2111             :    * \returns The number of values written.
    2112             :    */
    2113             :   dof_id_type write_serialized_vector (Xdr & io,
    2114             :                                        const NumericVector<Number> & vec) const;
    2115             : 
    2116             :   /**
    2117             :    * Function that initializes the system.
    2118             :    */
    2119             :   void (* _init_system_function) (EquationSystems & es,
    2120             :                                   const std::string & name);
    2121             : 
    2122             :   /**
    2123             :    * Object that initializes the system.
    2124             :    */
    2125             :   Initialization * _init_system_object;
    2126             : 
    2127             :   /**
    2128             :    * Function that assembles the system.
    2129             :    */
    2130             :   void (* _assemble_system_function) (EquationSystems & es,
    2131             :                                       const std::string & name);
    2132             : 
    2133             :   /**
    2134             :    * Object that assembles the system.
    2135             :    */
    2136             :   Assembly * _assemble_system_object;
    2137             : 
    2138             :   /**
    2139             :    * Function to impose constraints.
    2140             :    */
    2141             :   void (* _constrain_system_function) (EquationSystems & es,
    2142             :                                        const std::string & name);
    2143             : 
    2144             :   /**
    2145             :    * Object that constrains the system.
    2146             :    */
    2147             :   Constraint * _constrain_system_object;
    2148             : 
    2149             :   /**
    2150             :    * Function to evaluate quantity of interest
    2151             :    */
    2152             :   void (* _qoi_evaluate_function) (EquationSystems & es,
    2153             :                                    const std::string & name,
    2154             :                                    const QoISet & qoi_indices);
    2155             : 
    2156             :   /**
    2157             :    * Object to compute quantities of interest.
    2158             :    */
    2159             :   QOI * _qoi_evaluate_object;
    2160             : 
    2161             :   /**
    2162             :    * Function to evaluate quantity of interest derivative
    2163             :    */
    2164             :   void (* _qoi_evaluate_derivative_function) (EquationSystems & es,
    2165             :                                               const std::string & name,
    2166             :                                               const QoISet & qoi_indices,
    2167             :                                               bool include_liftfunc,
    2168             :                                               bool apply_constraints);
    2169             : 
    2170             :   /**
    2171             :    * Object to compute derivatives of quantities of interest.
    2172             :    */
    2173             :   QOIDerivative * _qoi_evaluate_derivative_object;
    2174             : 
    2175             :   /**
    2176             :    * Data structure describing the relationship between
    2177             :    * nodes, variables, etc... and degrees of freedom.
    2178             :    */
    2179             :   std::unique_ptr<DofMap> _dof_map;
    2180             : 
    2181             :   /**
    2182             :    * Constant reference to the \p EquationSystems object
    2183             :    * used for the simulation.
    2184             :    */
    2185             :   EquationSystems & _equation_systems;
    2186             : 
    2187             :   /**
    2188             :    * Constant reference to the \p mesh data structure used
    2189             :    * for the simulation.
    2190             :    */
    2191             :   MeshBase & _mesh;
    2192             : 
    2193             :   /**
    2194             :    * A name associated with this system.
    2195             :    */
    2196             :   const std::string _sys_name;
    2197             : 
    2198             :   /**
    2199             :    * The number associated with this system
    2200             :    */
    2201             :   const unsigned int _sys_number;
    2202             : 
    2203             :   /**
    2204             :    * The \p Variable in this \p System.
    2205             :    */
    2206             :   std::vector<Variable> _variables;
    2207             : 
    2208             :   /**
    2209             :    * The \p VariableGroup in this \p System.
    2210             :    */
    2211             :   std::vector<VariableGroup> _variable_groups;
    2212             : 
    2213             :   /**
    2214             :    * The variable numbers corresponding to user-specified
    2215             :    * names, useful for name-based lookups.
    2216             :    */
    2217             :   std::map<std::string, unsigned int, std::less<>> _variable_numbers;
    2218             : 
    2219             :   /**
    2220             :    * Flag stating if the system is active or not.
    2221             :    */
    2222             :   bool _active;
    2223             : 
    2224             :   /**
    2225             :    * Some systems need an arbitrary number of vectors.
    2226             :    * This map allows names to be associated with arbitrary
    2227             :    * vectors.  All the vectors in this map will be distributed
    2228             :    * in the same way as the solution vector.
    2229             :    */
    2230             :   std::map<std::string, std::unique_ptr<NumericVector<Number>>, std::less<>> _vectors;
    2231             : 
    2232             :   /**
    2233             :    * Holds true if a vector by that name should be projected
    2234             :    * onto a changed grid, false if it should be zeroed.
    2235             :    */
    2236             :   std::map<std::string, bool, std::less<>> _vector_projections;
    2237             : 
    2238             :   /**
    2239             :    * Holds non-negative if a vector by that name should be projected
    2240             :    * using adjoint constraints/BCs, -1 if primal
    2241             :    */
    2242             :   std::map<std::string, int, std::less<>> _vector_is_adjoint;
    2243             : 
    2244             :   /**
    2245             :    * Some systems need an arbitrary number of matrices.
    2246             :    */
    2247             :   std::map<std::string, std::unique_ptr<SparseMatrix<Number>>, std::less<>> _matrices;
    2248             : 
    2249             :   /**
    2250             :    * Holds the types of the matrices
    2251             :    */
    2252             :   std::map<std::string, ParallelType, std::less<>> _matrix_types;
    2253             : 
    2254             :   /**
    2255             :    * \p false when additional matrices being added require initialization, \p true otherwise.
    2256             :    */
    2257             :   bool _matrices_initialized;
    2258             : 
    2259             :   /**
    2260             :    * Holds true if the solution vector should be projected
    2261             :    * onto a changed grid, false if it should be zeroed.
    2262             :    * This is true by default.
    2263             :    */
    2264             :   bool _solution_projection;
    2265             : 
    2266             :   /**
    2267             :    * Holds true if the components of more advanced system types (e.g.
    2268             :    * system matrices) should not be initialized.
    2269             :    */
    2270             :   bool _basic_system_only;
    2271             : 
    2272             :   /**
    2273             :    * \p true when additional vectors and variables do not require
    2274             :    * immediate initialization, \p false otherwise.
    2275             :    */
    2276             :   bool _is_initialized;
    2277             : 
    2278             :   /**
    2279             :    * \p true when \p VariableGroup structures should be automatically
    2280             :    * identified, \p false otherwise.  Defaults to \p true.
    2281             :    */
    2282             :   bool _identify_variable_groups;
    2283             : 
    2284             :   /**
    2285             :    * This flag is used only when *reading* in a system from file.
    2286             :    * Based on the system header, it keeps track of how many
    2287             :    * additional vectors were actually written for this file.
    2288             :    */
    2289             :   unsigned int _additional_data_written;
    2290             : 
    2291             :   /**
    2292             :    * This vector is used only when *reading* in a system from file.
    2293             :    * Based on the system header, it keeps track of any index remapping
    2294             :    * between variable names in the data file and variable names in the
    2295             :    * already-constructed system.  I.e. if we have a system with
    2296             :    * variables "A1", "A2", "B1", and "B2", but we read in a data file with
    2297             :    * only "A1" and "B1" defined, then we don't want to try and read in
    2298             :    * A2 or B2, and we don't want to assign A1 and B1 values to
    2299             :    * different dof indices.
    2300             :    */
    2301             :   std::vector<unsigned int> _written_var_indices;
    2302             : 
    2303             :   /**
    2304             :    * Has the adjoint problem already been solved?  If the user sets
    2305             :    * \p adjoint_already_solved to \p true, we won't waste time solving
    2306             :    * it again.
    2307             :    */
    2308             :   bool adjoint_already_solved;
    2309             : 
    2310             :   /**
    2311             :    * Are we allowed to write this system to file?  If \p _hide_output is
    2312             :    * \p true, then \p EquationSystems::write will ignore this system.
    2313             :    */
    2314             :   bool _hide_output;
    2315             : 
    2316             :   /**
    2317             :    * Do we want to apply constraints while projecting vectors ?
    2318             :    */
    2319             :   bool project_with_constraints;
    2320             : 
    2321             :   /**
    2322             :    * Whether to use hash table matrix assembly if the matrix sub-classes support it
    2323             :    */
    2324             :   bool _prefer_hash_table_matrix_assembly;
    2325             : 
    2326             :   /**
    2327             :    * Whether any of our matrices require an initial sparsity pattern computation in order to determine preallocation
    2328             :    */
    2329             :   bool _require_sparsity_pattern;
    2330             : 
    2331             :   /**
    2332             :    * Whether we are name prefixing solver options
    2333             :    */
    2334             :   bool _prefix_with_name;
    2335             : };
    2336             : 
    2337             : 
    2338             : 
    2339             : // ------------------------------------------------------------
    2340             : // System inline methods
    2341             : inline
    2342      681881 : const std::string & System::name() const
    2343             : {
    2344    14330898 :   return _sys_name;
    2345             : }
    2346             : 
    2347             : 
    2348             : 
    2349             : inline
    2350      651117 : unsigned int System::number() const
    2351             : {
    2352     9557115 :   return _sys_number;
    2353             : }
    2354             : 
    2355             : 
    2356             : 
    2357             : inline
    2358      837304 : const MeshBase & System::get_mesh() const
    2359             : {
    2360    16746904 :   return _mesh;
    2361             : }
    2362             : 
    2363             : 
    2364             : 
    2365             : inline
    2366       27730 : MeshBase & System::get_mesh()
    2367             : {
    2368     1187356 :   return _mesh;
    2369             : }
    2370             : 
    2371             : 
    2372             : 
    2373             : inline
    2374    52983171 : const DofMap & System::get_dof_map() const
    2375             : {
    2376    52983171 :   return *_dof_map;
    2377             : }
    2378             : 
    2379             : 
    2380             : 
    2381             : inline
    2382      326166 : DofMap & System::get_dof_map()
    2383             : {
    2384      326166 :   return *_dof_map;
    2385             : }
    2386             : 
    2387             : 
    2388             : 
    2389             : inline
    2390             : bool System::active() const
    2391             : {
    2392             :   return _active;
    2393             : }
    2394             : 
    2395             : 
    2396             : 
    2397             : inline
    2398             : void System::activate ()
    2399             : {
    2400             :   _active = true;
    2401             : }
    2402             : 
    2403             : 
    2404             : 
    2405             : inline
    2406             : void System::deactivate ()
    2407             : {
    2408             :   _active = false;
    2409             : }
    2410             : 
    2411             : 
    2412             : 
    2413             : inline
    2414       22164 : bool System::is_initialized () const
    2415             : {
    2416       44029 :   return _is_initialized;
    2417             : }
    2418             : 
    2419             : 
    2420             : 
    2421             : inline
    2422           0 : void System::set_basic_system_only ()
    2423             : {
    2424           0 :   _basic_system_only = true;
    2425           0 : }
    2426             : 
    2427             : 
    2428             : 
    2429             : inline
    2430     7760152 : unsigned int System::n_vars() const
    2431             : {
    2432    16607764 :   return cast_int<unsigned int>(_variables.size());
    2433             : }
    2434             : 
    2435             : 
    2436             : 
    2437             : inline
    2438       29328 : unsigned int System::n_variable_groups() const
    2439             : {
    2440       58656 :   return cast_int<unsigned int>(_variable_groups.size());
    2441             : }
    2442             : 
    2443             : 
    2444             : 
    2445             : inline
    2446      241168 : unsigned int System::n_components() const
    2447             : {
    2448      241168 :   if (_variables.empty())
    2449         608 :     return 0;
    2450             : 
    2451         216 :   const Variable & last = _variables.back();
    2452       11005 :   return last.first_scalar_number() + last.n_components(this->get_mesh());
    2453             : }
    2454             : 
    2455             : 
    2456             : 
    2457             : inline
    2458     2610889 : const Variable & System::variable (const unsigned int i) const
    2459             : {
    2460     2610889 :   libmesh_assert_less (i, _variables.size());
    2461             : 
    2462    17421281 :   return _variables[i];
    2463             : }
    2464             : 
    2465             : 
    2466             : 
    2467             : inline
    2468       14804 : const VariableGroup & System::variable_group (const unsigned int vg) const
    2469             : {
    2470       14804 :   libmesh_assert_less (vg, _variable_groups.size());
    2471             : 
    2472      518347 :   return _variable_groups[vg];
    2473             : }
    2474             : 
    2475             : 
    2476             : 
    2477             : inline
    2478      688820 : const std::string & System::variable_name (const unsigned int i) const
    2479             : {
    2480      688820 :   libmesh_assert_less (i, _variables.size());
    2481             : 
    2482     2277693 :   return _variables[i].name();
    2483             : }
    2484             : 
    2485             : 
    2486             : 
    2487             : inline
    2488             : unsigned int
    2489           0 : System::variable_scalar_number (std::string_view var,
    2490             :                                 unsigned int component) const
    2491             : {
    2492           0 :   return variable_scalar_number(this->variable_number(var), component);
    2493             : }
    2494             : 
    2495             : 
    2496             : 
    2497             : inline
    2498             : unsigned int
    2499      410275 : System::variable_scalar_number (unsigned int var_num,
    2500             :                                 unsigned int component) const
    2501             : {
    2502     2074499 :   return _variables[var_num].first_scalar_number() + component;
    2503             : }
    2504             : 
    2505             : 
    2506             : 
    2507             : inline
    2508      432637 : const FEType & System::variable_type (const unsigned int i) const
    2509             : {
    2510      432637 :   libmesh_assert_less (i, _variables.size());
    2511             : 
    2512    40107647 :   return _variables[i].type();
    2513             : }
    2514             : 
    2515             : 
    2516             : 
    2517             : inline
    2518         958 : const FEType & System::variable_type (std::string_view var) const
    2519             : {
    2520       34063 :   return _variables[this->variable_number(var)].type();
    2521             : }
    2522             : 
    2523             : 
    2524             : 
    2525             : inline
    2526        1134 : bool System::identify_variable_groups () const
    2527             : {
    2528       39256 :   return _identify_variable_groups;
    2529             : }
    2530             : 
    2531             : 
    2532             : 
    2533             : inline
    2534             : void System::identify_variable_groups (const bool ivg)
    2535             : {
    2536             :   _identify_variable_groups = ivg;
    2537             : }
    2538             : 
    2539             : 
    2540             : 
    2541             : inline
    2542       22218 : dof_id_type System::n_active_dofs() const
    2543             : {
    2544       22948 :   return this->n_dofs() - this->n_constrained_dofs();
    2545             : }
    2546             : 
    2547             : 
    2548             : 
    2549             : inline
    2550             : bool System::have_vector (std::string_view vec_name) const
    2551             : {
    2552             :   return (_vectors.count(vec_name));
    2553             : }
    2554             : 
    2555             : 
    2556             : 
    2557             : inline
    2558        1640 : unsigned int System::n_vectors () const
    2559             : {
    2560        1640 :   return cast_int<unsigned int>(_vectors.size());
    2561             : }
    2562             : 
    2563             : inline
    2564        1440 : System::vectors_iterator System::vectors_begin ()
    2565             : {
    2566        1440 :   return _vectors.begin();
    2567             : }
    2568             : 
    2569             : inline
    2570        1892 : System::const_vectors_iterator System::vectors_begin () const
    2571             : {
    2572        1892 :   return _vectors.begin();
    2573             : }
    2574             : 
    2575             : inline
    2576        1440 : System::vectors_iterator System::vectors_end ()
    2577             : {
    2578        1440 :   return _vectors.end();
    2579             : }
    2580             : 
    2581             : inline
    2582        3784 : System::const_vectors_iterator System::vectors_end () const
    2583             : {
    2584        3784 :   return _vectors.end();
    2585             : }
    2586             : 
    2587             : inline
    2588             : System::matrices_iterator System::matrices_begin ()
    2589             : {
    2590             :   return _matrices.begin();
    2591             : }
    2592             : 
    2593             : inline
    2594             : System::const_matrices_iterator System::matrices_begin () const
    2595             : {
    2596             :   return _matrices.begin();
    2597             : }
    2598             : 
    2599             : inline
    2600             : System::matrices_iterator System::matrices_end ()
    2601             : {
    2602             :   return _matrices.end();
    2603             : }
    2604             : 
    2605             : inline
    2606             : System::const_matrices_iterator System::matrices_end () const
    2607             : {
    2608             :   return _matrices.end();
    2609             : }
    2610             : 
    2611             : inline
    2612           0 : void System::assemble_residual_derivatives (const ParameterVector &)
    2613             : {
    2614           0 :   libmesh_not_implemented();
    2615             : }
    2616             : 
    2617             : inline
    2618           0 : void System::disable_cache () { assemble_before_solve = true; }
    2619             : 
    2620             : inline
    2621     1536026 : unsigned int System::n_qois() const
    2622             : {
    2623             : #ifndef LIBMESH_ENABLE_DEPRECATED
    2624             :   libmesh_assert_equal_to(this->qoi.size(), this->qoi_error_estimates.size());
    2625             : #endif
    2626             : 
    2627     7862673 :   return cast_int<unsigned int>(this->qoi.size());
    2628             : }
    2629             : 
    2630             : inline
    2631             : std::pair<unsigned int, Real>
    2632           0 : System::sensitivity_solve (const ParameterVector &)
    2633             : {
    2634           0 :   libmesh_not_implemented();
    2635             : }
    2636             : 
    2637             : inline
    2638             : std::pair<unsigned int, Real>
    2639           0 : System::weighted_sensitivity_solve (const ParameterVector &,
    2640             :                                     const ParameterVector &)
    2641             : {
    2642           0 :   libmesh_not_implemented();
    2643             : }
    2644             : 
    2645             : inline
    2646             : std::pair<unsigned int, Real>
    2647           0 : System::adjoint_solve (const QoISet &)
    2648             : {
    2649           0 :   libmesh_not_implemented();
    2650             : }
    2651             : 
    2652             : inline
    2653             : std::pair<unsigned int, Real>
    2654           0 : System::weighted_sensitivity_adjoint_solve (const ParameterVector &,
    2655             :                                             const ParameterVector &,
    2656             :                                             const QoISet &)
    2657             : {
    2658           0 :   libmesh_not_implemented();
    2659             : }
    2660             : 
    2661             : inline
    2662             : void
    2663           0 : System::adjoint_qoi_parameter_sensitivity (const QoISet &,
    2664             :                                            const ParameterVector &,
    2665             :                                            SensitivityData &)
    2666             : {
    2667           0 :   libmesh_not_implemented();
    2668             : }
    2669             : 
    2670             : inline
    2671             : void
    2672           0 : System::forward_qoi_parameter_sensitivity (const QoISet &,
    2673             :                                            const ParameterVector &,
    2674             :                                            SensitivityData &)
    2675             : {
    2676           0 :   libmesh_not_implemented();
    2677             : }
    2678             : 
    2679             : inline
    2680             : void
    2681           0 : System::qoi_parameter_hessian(const QoISet &,
    2682             :                               const ParameterVector &,
    2683             :                               SensitivityData &)
    2684             : {
    2685           0 :   libmesh_not_implemented();
    2686             : }
    2687             : 
    2688             : inline
    2689             : void
    2690           0 : System::qoi_parameter_hessian_vector_product(const QoISet &,
    2691             :                                              const ParameterVector &,
    2692             :                                              const ParameterVector &,
    2693             :                                              SensitivityData &)
    2694             : {
    2695           0 :   libmesh_not_implemented();
    2696             : }
    2697             : 
    2698             : inline
    2699        1032 : unsigned int System::n_matrices () const
    2700             : {
    2701        1032 :   return cast_int<unsigned int>(_matrices.size());
    2702             : }
    2703             : 
    2704             : template <template <typename> class MatrixType>
    2705             : inline
    2706             : SparseMatrix<Number> &
    2707             : System::add_matrix (std::string_view mat_name,
    2708             :                     const ParallelType type)
    2709             : {
    2710             :   // Return the matrix if it is already there.
    2711             :   auto it = this->_matrices.find(mat_name);
    2712             :   if (it != this->_matrices.end())
    2713             :     return *it->second;
    2714             : 
    2715             :   // Otherwise build the matrix to return.
    2716             :   auto pr = _matrices.emplace(mat_name, std::make_unique<MatrixType<Number>>(this->comm()));
    2717             :   _matrix_types.emplace(mat_name, type);
    2718             : 
    2719             :   SparseMatrix<Number> & mat = *(pr.first->second);
    2720             : 
    2721             :   // Initialize it first if we've already initialized the others.
    2722             :   this->late_matrix_init(mat, type);
    2723             : 
    2724             :   return mat;
    2725             : }
    2726             : 
    2727             : inline void
    2728             : System::prefer_hash_table_matrix_assembly(const bool preference)
    2729             : {
    2730             :   libmesh_error_msg_if(
    2731             :       _matrices_initialized,
    2732             :       "System::prefer_hash_table_matrix_assembly() should be called before matrices are initialized");
    2733             :   _prefer_hash_table_matrix_assembly = preference;
    2734             : }
    2735             : 
    2736             : } // namespace libMesh
    2737             : 
    2738             : #endif // LIBMESH_SYSTEM_H

Generated by: LCOV version 1.14