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