LCOV - code coverage report
Current view: top level - include/systems - system.h (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4475 (55045b) with base a68cc6 Lines: 50 81 61.7 %
Date: 2026-06-03 14:29:06 Functions: 28 47 59.6 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14