LCOV - code coverage report
Current view: top level - include/systems - equation_systems.h (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4343 (6ea38c) with base 8c3130 Lines: 49 55 89.1 %
Date: 2026-10-13 21:47:33 Functions: 19 45 42.2 %
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_EQUATION_SYSTEMS_H
      21             : #define LIBMESH_EQUATION_SYSTEMS_H
      22             : 
      23             : // Local Includes
      24             : #include "libmesh/libmesh_common.h"
      25             : #include "libmesh/parameters.h"
      26             : #include "libmesh/system.h"
      27             : #include "libmesh/parallel_object.h"
      28             : 
      29             : // HP aCC needs these for some reason
      30             : #ifdef __HP_aCC
      31             : # include "libmesh/frequency_system.h"
      32             : # include "libmesh/transient_system.h"
      33             : # include "libmesh/newmark_system.h"
      34             : # include "libmesh/steady_system.h"
      35             : #endif
      36             : 
      37             : // C++ includes
      38             : #include <cstddef>
      39             : #include <functional>
      40             : #include <map>
      41             : #include <set>
      42             : #include <string>
      43             : #include <string_view>
      44             : #include <vector>
      45             : #include <memory>
      46             : 
      47             : namespace libMesh
      48             : {
      49             : 
      50             : // Forward Declarations
      51             : class Elem;
      52             : class MeshBase;
      53             : enum XdrMODE : int;
      54             : 
      55             : /**
      56             :  * This is the \p EquationSystems class.  It is in charge
      57             :  * of handling all the various equation systems defined
      58             :  * for a \p MeshBase.  It may have multiple systems, which may
      59             :  * be active or inactive, so that at different solution
      60             :  * stages only a sub-set may be solved for.  Also, through
      61             :  * the templated access, different types of systems
      62             :  * may be handled.  Also other features, like flags,
      63             :  * parameters, I/O etc are provided.
      64             :  *
      65             :  * \author Benjamin S. Kirk
      66             :  * \date 2002-2007
      67             :  * \brief Manages multiples systems of equations.
      68             :  */
      69       31484 : class EquationSystems : public ReferenceCountedObject<EquationSystems>,
      70             :                         public ParallelObject
      71             : 
      72             : {
      73             : public:
      74             : 
      75             :   /**
      76             :    * Define enumeration to set properties in EquationSystems::read()
      77             :    */
      78             :   enum ReadFlags { READ_HEADER           = 1,
      79             :                    READ_DATA             = 2,
      80             :                    READ_ADDITIONAL_DATA  = 4,
      81             :                    READ_LEGACY_FORMAT    = 8,
      82             :                    TRY_READ_IFEMS        = 16,
      83             :                    READ_BASIC_ONLY       = 32 };
      84             : 
      85             :   /**
      86             :    * Define enumeration to set properties in EquationSystems::write()
      87             :    */
      88             :   enum WriteFlags { WRITE_DATA             = 1,
      89             :                     WRITE_ADDITIONAL_DATA  = 2,
      90             :                     WRITE_PARALLEL_FILES   = 4,
      91             :                     WRITE_SERIAL_FILES     = 8 };
      92             : 
      93             :   /**
      94             :    * Constructor.
      95             :    */
      96             :   EquationSystems (MeshBase & mesh);
      97             : 
      98             :   /**
      99             :    * Destructor.  Should be virtual, since the user may want to derive
     100             :    * subclasses of EquationSystems.
     101             :    */
     102             :   virtual ~EquationSystems ();
     103             : 
     104             :   /**
     105             :    * Restores the data structure to a pristine state.
     106             :    */
     107             :   virtual void clear ();
     108             : 
     109             :   /**
     110             :    * Initialize all the systems
     111             :    */
     112             :   virtual void init ();
     113             : 
     114             :   /**
     115             :    * Handle any mesh changes and reinitialize all the systems on the
     116             :    * updated mesh
     117             :    */
     118             :   virtual void reinit ();
     119             : 
     120             :   /**
     121             :    * Handle the association of a completely *new* mesh with the
     122             :    * EquationSystem and all the Systems assigned to it.
     123             :    */
     124             :   virtual void reinit_mesh ();
     125             : 
     126             :   /**
     127             :    * Enable or disable default ghosting functors on the Mesh and on
     128             :    * all Systems.  Standard ghosting is enabled by default.  If
     129             :    * disabled, default ghosting will also be disabled on any later
     130             :    * added systems.
     131             :    *
     132             :    * Unless other equivalent ghosting functors have been added,
     133             :    * removing the default coupling functor is only safe for explicit
     134             :    * solves, and removing the default algebraic ghosting functor is
     135             :    * only safe for codes where no evaluations on neighbor cells (e.g.
     136             :    * no jump error estimators) are done.
     137             :    */
     138             :   virtual void enable_default_ghosting (bool enable);
     139             : 
     140             :   /**
     141             :    * Updates local values for all the systems
     142             :    */
     143             :   void update ();
     144             : 
     145             :   /**
     146             :    * \returns The number of equation systems.
     147             :    */
     148             :   unsigned int n_systems() const;
     149             : 
     150             :   /**
     151             :    * \returns \p true if the system named \p name exists within
     152             :    * this EquationSystems object.
     153             :    */
     154             :   bool has_system (std::string_view name) const;
     155             : 
     156             :   /**
     157             :    * \returns A constant reference to the system named \p name.
     158             :    * The template argument defines the return type.  For example,
     159             :    * const SteadySystem & sys = eq.get_system<SteadySystem> ("sys");
     160             :    * is an example of how the method might be used
     161             :    */
     162             :   template <typename T_sys>
     163             :   const T_sys & get_system (std::string_view name) const;
     164             : 
     165             :   /**
     166             :    * \returns A writable reference to the system named \p name.
     167             :    * The template argument defines the return type.  For example,
     168             :    * const SteadySystem & sys = eq.get_system<SteadySystem> ("sys");
     169             :    * is an example of how the method might be used
     170             :    */
     171             :   template <typename T_sys>
     172             :   T_sys & get_system (std::string_view name);
     173             : 
     174             :   /**
     175             :    * \returns A constant reference to system number \p num.
     176             :    * The template argument defines the return type.  For example,
     177             :    * const SteadySystem & sys = eq.get_system<SteadySystem> (0);
     178             :    * is an example of how the method might be used
     179             :    */
     180             :   template <typename T_sys>
     181             :   const T_sys & get_system (const unsigned int num) const;
     182             : 
     183             :   /**
     184             :    * \returns A writable reference to the system number \p num.
     185             :    * The template argument defines the return type.  For example,
     186             :    * const SteadySystem & sys = eq.get_system<SteadySystem> (0);
     187             :    * is an example of how the method might be used
     188             :    */
     189             :   template <typename T_sys>
     190             :   T_sys & get_system (const unsigned int num);
     191             : 
     192             :   /**
     193             :    * \returns A constant reference to the system named \p name.
     194             :    */
     195             :   const System & get_system (std::string_view name) const;
     196             : 
     197             :   /**
     198             :    * \returns A writable reference to the system named \p name.
     199             :    */
     200             :   System & get_system (std::string_view name);
     201             : 
     202             :   /**
     203             :    * \returns A constant reference to system number \p num.
     204             :    */
     205             :   const System & get_system (const unsigned int num) const;
     206             : 
     207             :   /**
     208             :    * \returns A writable reference to the system number \p num.
     209             :    */
     210             :   System & get_system (const unsigned int num);
     211             : 
     212             :   /**
     213             :    * Add the system of type \p system_type named \p name to the
     214             :    * systems array.
     215             :    */
     216             :   virtual System & add_system (std::string_view system_type,
     217             :                                std::string_view name);
     218             : 
     219             :   /**
     220             :    * Add the system named \p name to the systems array.
     221             :    */
     222             :   template <typename T_sys>
     223             :   T_sys & add_system (std::string_view name);
     224             : 
     225             :   /**
     226             :    * \returns The total number of variables in all
     227             :    * systems.
     228             :    */
     229             :   unsigned int n_vars () const;
     230             : 
     231             :   /**
     232             :    * \returns The total number of degrees of freedom
     233             :    * in all systems.
     234             :    */
     235             :   std::size_t n_dofs () const;
     236             : 
     237             :   /**
     238             :    * \returns The number of active degrees of freedom
     239             :    * for the EquationSystems object.
     240             :    */
     241             :   std::size_t n_active_dofs() const;
     242             : 
     243             :   /**
     244             :    * Call \p solve on all the individual equation systems.
     245             :    *
     246             :    * By default this function solves each equation system once,
     247             :    * in the order they were added.  For more sophisticated decoupled
     248             :    * problems the user may with to override this behavior in a derived
     249             :    * class.
     250             :    */
     251             :   virtual void solve ();
     252             : 
     253             :   /**
     254             :    * Call \p adjoint_solve on all the individual equation systems.
     255             :    *
     256             :    * By default this function solves each system's adjoint once,
     257             :    * in the reverse order from that in which they were added.  For
     258             :    * more sophisticated decoupled problems the user may with to
     259             :    * override this behavior in a derived class.
     260             :    */
     261             :   virtual void adjoint_solve (const QoISet & qoi_indices = QoISet());
     262             : 
     263             :   /**
     264             :    * Call \p sensitivity_solve on all the individual equation systems.
     265             :    *
     266             :    * By default this function solves each sensitivity system once,
     267             :    * in the order in which in which they were added.  For
     268             :    * more sophisticated decoupled problems the user may with to
     269             :    * override this behavior in a derived class.
     270             :    */
     271             :   virtual void sensitivity_solve (const ParameterVector & parameters);
     272             : 
     273             :   /**
     274             :    * Fill the input vector \p var_names with the names
     275             :    * of the variables for each system. If \p type is passed,
     276             :    * only variables of the specified type will be populated.
     277             :    * If systems_names!=nullptr, only include names from the
     278             :    * specified systems.
     279             :    */
     280             :   void build_variable_names (std::vector<std::string> & var_names,
     281             :                              const FEType * type=nullptr,
     282             :                              const std::set<std::string> * system_names=nullptr) const;
     283             : 
     284             :   /**
     285             :    * \returns Whether \p type can be represented as elemental data.
     286             :    *
     287             :    * Elemental data variables are CONSTANT element-interior fields,
     288             :    * regardless of their p_refinement flag, unless
     289             :    * \p allow_high_order_discontinuous is true, in which case
     290             :    * higher-order discontinuous (MONOMIAL, MONOMIAL_VEC, XYZ) fields
     291             :    * are also accepted.
     292             :    */
     293             :   static bool is_elemental_data_fe_type (const FEType & type,
     294             :                                          bool allow_high_order_discontinuous = false);
     295             : 
     296             :   /**
     297             :    * Filter \p var_names to names of variables that can be represented as
     298             :    * elemental data. If \p var_names is empty, all eligible variable names are
     299             :    * returned. Vector-valued variables are decomposed into component names.
     300             :    * If \p system_names!=nullptr, only include names from the specified systems.
     301             :    * See is_elemental_data_fe_type() for \p allow_high_order_discontinuous.
     302             :    */
     303             :   void build_elemental_data_variable_names
     304             :     (std::vector<std::string> & var_names,
     305             :      const std::set<std::string> * system_names=nullptr,
     306             :      bool allow_high_order_discontinuous = false) const;
     307             : 
     308             :   /**
     309             :    * Fill the input vector \p soln with the solution values for the
     310             :    * system named \p name.
     311             :    *
     312             :    * \note The input vector \p soln will only be assembled on
     313             :    * processor 0, so this method is only applicable to outputting plot
     314             :    * files from processor 0.
     315             :    */
     316             :   void build_solution_vector (std::vector<Number> & soln,
     317             :                               std::string_view system_name,
     318             :                               std::string_view variable_name = "all_vars") const;
     319             : 
     320             :   /**
     321             :    * Fill the input vector \p soln with solution values.  The
     322             :    * entries will be in node-major format (corresponding to
     323             :    * the names from \p build_variable_names()).
     324             :    *
     325             :    * If systems_names!=nullptr, only include data from the
     326             :    * specified systems.
     327             :    *
     328             :    * If \p add_sides is true, append data for plotting on "side
     329             :    * elements" too.
     330             :    */
     331             :   void build_solution_vector (std::vector<Number> & soln,
     332             :                               const std::set<std::string> * system_names=nullptr,
     333             :                               bool add_sides=false) const;
     334             : 
     335             :   /**
     336             :    * A version of build_solution_vector which is appropriate for
     337             :    * "parallel" output formats like Nemesis.
     338             :    *
     339             :    * \returns A std::unique_ptr to a node-major NumericVector of total
     340             :    * length n_nodes*n_vars that various I/O classes can then use to
     341             :    * get the local values they need to write on each processor.
     342             :    */
     343             :   std::unique_ptr<NumericVector<Number>>
     344             :   build_parallel_solution_vector(const std::set<std::string> * system_names=nullptr,
     345             :                                  bool add_sides=false) const;
     346             : 
     347             :   /**
     348             :    * Retrieve \p vars_active_subdomains, which indicates the active
     349             :    * subdomains for each variable in \p names.
     350             :    */
     351             :   void get_vars_active_subdomains(const std::vector<std::string> & names,
     352             :                                   std::vector<std::set<subdomain_id_type>> & vars_active_subdomains) const;
     353             : 
     354             :   /**
     355             :    * Retrieve the solution data for elemental data variables. If 'names' is
     356             :    * populated, only the variables corresponding to those names will be
     357             :    * retrieved. This can be used to filter which variables are retrieved.
     358             :    *
     359             :    * This is the more appropriately-named replacement for the get_solution()
     360             :    * function defined above. See is_elemental_data_fe_type() for
     361             :    * \p allow_high_order_discontinuous; when true, higher-order
     362             :    * discontinuous variables are included and their values are a
     363             :    * quadrature average over each element rather than a single DOF.
     364             :    */
     365             :   void build_elemental_solution_vector (std::vector<Number> & soln,
     366             :                                         std::vector<std::string> & names,
     367             :                                         bool allow_high_order_discontinuous = false) const;
     368             : 
     369             :   /**
     370             :    * Finds system and variable numbers for any variables of 'type' or of
     371             :    * 'types' corresponding to the entries in the input 'names' vector.
     372             :    * If 'names' is empty, this returns all variables of the type.
     373             :    * The names of vector variables are decomposed into individual ones
     374             :    * suffixed with their cartesian component, but there will still be
     375             :    * a single pair of system numbers for such vector variables. Thus,
     376             :    * the size of the 'names' vector modified by this function may not
     377             :    * be equal to that of the returned vector of pairs. Nevertheless, both
     378             :    * should be sorted in accordance with ExodusII format, and so the
     379             :    * developer just needs to know to separate dof_indices when
     380             :    * accessing the system solution for vector variables.
     381             :    *
     382             :    * This function is designed to work for either a single type or a
     383             :    * vector of types, but not both. This is because it can't simply be
     384             :    * called a second time with another type as it filters (deletes) the
     385             :    * names of those on the first call that used a different type. Thus,
     386             :    * the 'types' argument is for the case where variables of multiple
     387             :    * types are allowed to pass through.
     388             :    *
     389             :    * TODO: find a more generic way to handle this whole procedure.
     390             :    */
     391             :   std::vector<std::pair<unsigned int, unsigned int>>
     392             :   find_variable_numbers (std::vector<std::string> & names,
     393             :                          const FEType * type=nullptr,
     394             :                          const std::vector<FEType> * types=nullptr) const;
     395             : 
     396             :   /**
     397             :    * Finds system and variable numbers for variables that can be represented
     398             :    * as elemental data. See find_variable_numbers() for name filtering,
     399             :    * component decomposition, and sorting details, and
     400             :    * is_elemental_data_fe_type() for \p allow_high_order_discontinuous.
     401             :    */
     402             :   std::vector<std::pair<unsigned int, unsigned int>>
     403             :   find_elemental_data_variable_numbers (std::vector<std::string> & names,
     404             :                                         bool allow_high_order_discontinuous = false) const;
     405             : 
     406             :   /**
     407             :    * Builds a parallel vector of elemental data solution values corresponding to the entries
     408             :    * in the input 'names' vector. This vector is approximately uniformly
     409             :    * distributed across all of the available processors.
     410             :    *
     411             :    * The related function build_elemental_solution_vector() is
     412             :    * implemented by calling this function and then calling
     413             :    * localize_to_one() on the resulting vector.
     414             :    *
     415             :    * Returns a nullptr if no elemental data variables exist in the 'names'
     416             :    * vector (if it is empty, then it will return all variables in the system
     417             :    * of this type if any) or a std::unique_ptr to
     418             :    * a var-major numeric vector of total length n_elem * n_vars, where
     419             :    * n_vars includes all components of vectors, ordered according to:
     420             :    * [u0, u1, ... uN, v0, v1, ... vN, w0, w1, ... wN] for elemental data
     421             :    * variables (u, v, w) on a mesh with N elements.
     422             :    *
     423             :    * See is_elemental_data_fe_type() for \p allow_high_order_discontinuous;
     424             :    * when true, the value stored for a higher-order discontinuous variable
     425             :    * is a quadrature average of its solution over each element, rather
     426             :    * than a single DOF.
     427             :    */
     428             :   std::unique_ptr<NumericVector<Number>>
     429             :   build_parallel_elemental_solution_vector (std::vector<std::string> & names,
     430             :                                             bool allow_high_order_discontinuous = false) const;
     431             : 
     432             :   /**
     433             :    * Fill the input vector \p soln with solution values.  The
     434             :    * entries will be in geometry-major format: element, then local
     435             :    * node/vertex, then variable.
     436             : 
     437             :    * If systems_names!=nullptr, only include data from the
     438             :    * specified systems.
     439             : 
     440             :    * If vertices_only == true, then for higher-order elements only
     441             :    * the solution at the vertices is computed. This can be useful
     442             :    * when plotting discontinuous solutions on higher-order elements
     443             :    * and only a lower-order representation is required.
     444             :    *
     445             :    * If add_sides == true, append data for plotting on "side
     446             :    * elements" too.
     447             :    */
     448             :   void build_discontinuous_solution_vector
     449             :   (std::vector<Number> & soln,
     450             :    const std::set<std::string> * system_names = nullptr,
     451             :    const std::vector<std::string> * var_names = nullptr,
     452             :    bool vertices_only = false,
     453             :    bool add_sides = false) const;
     454             : 
     455             :   /*
     456             :    * Returns true iff the given side of the given element is *never*
     457             :    * added to output from that element, because it is considered to be
     458             :    * redundant with respect to the same data added from the
     459             :    * neighboring element sharing that side.  This helper function is
     460             :    * used with the add_sides option when building solution vectors
     461             :    * here and when outputting solution vectors in MeshOutput
     462             :    * (currently just Exodus) I/O.
     463             :    */
     464             :   static bool redundant_added_side(const Elem & elem, unsigned int side);
     465             : 
     466             : 
     467             :   /**
     468             :    * Read & initialize the systems from disk using the XDR data format.
     469             :    * This format allows for machine-independent binary output.
     470             :    *
     471             :    * Set which sections of the file to read by bitwise OR'ing the
     472             :    * EquationSystems::ReadFlags enumeration together. For example, to
     473             :    * read all sections of the file, set read_flags to:
     474             :    * (READ_HEADER | READ_DATA | READ_ADDITIONAL_DATA)
     475             :    *
     476             :    * \note The equation system can be defined without initializing
     477             :    * the data vectors to any solution values.  This can be done
     478             :    * by omitting READ_DATA in the read_flags parameter.
     479             :    *
     480             :    * If XdrMODE is omitted, it will be inferred as READ for filenames
     481             :    * containing .xda or as DECODE for filenames containing .xdr
     482             :    *
     483             :    * \param name Name of the file to be read.
     484             :    * \param read_flags Single flag created by bitwise-OR'ing several flags together.
     485             :    * \param mode Controls whether reading is done in binary or ascii mode.
     486             :    * \param partition_agnostic If true then the mesh and degrees of freedom
     487             :    * will be temporarily renumbered in a partition agnostic way so that
     488             :    * files written using "n" mpi processes can be re-read on "m" mpi
     489             :    * processes.  This renumbering is not compatible with meshes
     490             :    * that have two nodes in exactly the same position!
     491             :    */
     492             :   template <typename InValType = Number>
     493             :   void read (std::string_view name,
     494             :              const XdrMODE,
     495             :              const unsigned int read_flags=(READ_HEADER | READ_DATA),
     496             :              bool partition_agnostic = true);
     497             : 
     498             :   template <typename InValType = Number>
     499             :   void read (std::string_view name,
     500             :              const unsigned int read_flags=(READ_HEADER | READ_DATA),
     501             :              bool partition_agnostic = true);
     502             : 
     503             :   template <typename InValType = Number>
     504             :   void read (Xdr & io,
     505             :              std::function<std::unique_ptr<Xdr>()> & local_io_functor,
     506             :              const unsigned int read_flags=(READ_HEADER | READ_DATA),
     507             :              bool partition_agnostic = true);
     508             : 
     509             :   /**
     510             :    * Write the systems to disk using the XDR data format.
     511             :    * This format allows for machine-independent binary output.
     512             :    *
     513             :    * Set the writing properties using the EquationSystems::WriteFlags
     514             :    * enumeration. Set which sections to write out by bitwise OR'ing
     515             :    * the enumeration values. Write everything by setting write_flags to:
     516             :    * (WRITE_DATA | WRITE_ADDITIONAL_DATA)
     517             :    *
     518             :    * \note The solution data can be omitted by calling
     519             :    * this routine with WRITE_DATA omitted in the write_flags argument.
     520             :    *
     521             :    * If XdrMODE is omitted, it will be inferred as WRITE for filenames
     522             :    * containing .xda or as ENCODE for filenames containing .xdr
     523             :    *
     524             :    * \param name Name of the file to be read.
     525             :    * \param write_flags Single flag created by bitwise-OR'ing several flags together.
     526             :    * \param mode Controls whether reading is done in binary or ascii mode.
     527             :    * \param partition_agnostic If true then the mesh and degrees of freedom
     528             :    * will be temporarily renumbered in a partition agnostic way so that
     529             :    * files written using "n" mpi processes can be re-read on "m" mpi
     530             :    * processes.  This renumbering is not compatible with meshes
     531             :    * that have two nodes in exactly the same position!
     532             :    */
     533             :   void write (std::string_view name,
     534             :               const XdrMODE,
     535             :               const unsigned int write_flags=(WRITE_DATA),
     536             :               bool partition_agnostic = true) const;
     537             : 
     538             :   void write (std::string_view name,
     539             :               const unsigned int write_flags=(WRITE_DATA),
     540             :               bool partition_agnostic = true) const;
     541             : 
     542             :   void write (std::ostream name,
     543             :               const unsigned int write_flags=(WRITE_DATA),
     544             :               bool partition_agnostic = true) const;
     545             : 
     546             :   void write (Xdr & io,
     547             :               const unsigned int write_flags=(WRITE_DATA),
     548             :               bool partition_agnostic = true,
     549             :               Xdr * const local_io = nullptr) const;
     550             : 
     551             :   /**
     552             :    * \returns \p true when this equation system contains
     553             :    * identical data, up to the given threshold.  Delegates
     554             :    * most of the comparisons to perform to the responsible
     555             :    * systems
     556             :    */
     557             :   virtual bool compare (const EquationSystems & other_es,
     558             :                         const Real threshold,
     559             :                         const bool verbose) const;
     560             : 
     561             :   /**
     562             :    * \returns A string containing information about the
     563             :    * systems, flags, and parameters.
     564             :    */
     565             :   virtual std::string get_info() const;
     566             : 
     567             :   /**
     568             :    * Prints information about the equation systems, by default to
     569             :    * libMesh::out.
     570             :    */
     571             :   void print_info (std::ostream & os=libMesh::out) const;
     572             : 
     573             :   /**
     574             :    * Same as above, but allows you to also use stream syntax.
     575             :    */
     576             :   friend std::ostream & operator << (std::ostream & os,
     577             :                                      const EquationSystems & es);
     578             : 
     579             :   /**
     580             :    * \returns A constant reference to the mesh
     581             :    */
     582             :   const MeshBase & get_mesh() const;
     583             : 
     584             :   /**
     585             :    * \returns A reference to the mesh
     586             :    */
     587             :   MeshBase & get_mesh();
     588             : 
     589             :   /**
     590             :    * Serializes a distributed mesh and its associated
     591             :    * degree of freedom numbering for all systems
     592             :    **/
     593             :   void allgather ();
     594             : 
     595             :   /**
     596             :    * Calls to reinit() will also do two-step coarsen-then-refine
     597             :    **/
     598             :   void enable_refine_in_reinit() { this->_refine_in_reinit = true; }
     599             : 
     600             :   /**
     601             :    * Calls to reinit() will not try to coarsen or refine the mesh
     602             :    **/
     603             :   void disable_refine_in_reinit() { this->_refine_in_reinit = false; }
     604             : 
     605             :   /**
     606             :    * \returns Whether or not calls to reinit() will try to coarsen/refine the mesh
     607             :    **/
     608             :   bool refine_in_reinit_flag() { return this->_refine_in_reinit; }
     609             : 
     610             :   /**
     611             :    * Handle any mesh changes and project any solutions onto the
     612             :    * updated mesh.
     613             :    *
     614             :    * \returns Whether or not the mesh may have changed.
     615             :    */
     616             :   bool reinit_solutions ();
     617             : 
     618             :   /**
     619             :    * Reinitialize all systems on the current mesh.
     620             :    */
     621             :   virtual void reinit_systems ();
     622             : 
     623             :   /**
     624             :    * Data structure holding arbitrary parameters.
     625             :    */
     626             :   Parameters parameters;
     627             : 
     628             : 
     629             : protected:
     630             : 
     631             : 
     632             :   /**
     633             :    * The mesh data structure
     634             :    */
     635             :   MeshBase & _mesh;
     636             : 
     637             :   /**
     638             :    * Data structure holding the systems.
     639             :    */
     640             :   std::map<std::string, std::unique_ptr<System>, std::less<>> _systems;
     641             : 
     642             :   /**
     643             :    * Flag for whether to call coarsen/refine in reinit().
     644             :    * Default value: true
     645             :    */
     646             :   bool _refine_in_reinit;
     647             : 
     648             :   /**
     649             :    * Flag for whether to enable default ghosting on newly added Systems.
     650             :    * Default value: true
     651             :    */
     652             :   bool _enable_default_ghosting;
     653             : 
     654             : private:
     655             :   /**
     656             :    * Implementation detail for find_variable_numbers() variants.
     657             :    */
     658             :   std::vector<std::pair<unsigned int, unsigned int>>
     659             :   find_variable_numbers_by_predicate
     660             :     (std::vector<std::string> & names,
     661             :      const std::function<bool(const FEType &)> & type_filter) const;
     662             : 
     663             :   /**
     664             :    * This function is used in the implementation of add_system,
     665             :    * it loops over the nodes and elements of the Mesh, adding the
     666             :    * system to each one.  The main reason to separate this part
     667             :    * is to avoid coupling this header file to mesh.h, and elem.h.
     668             :    */
     669             :   void _add_system_to_nodes_and_elems();
     670             : 
     671             :   /**
     672             :    * This just calls DofMap::remove_default_ghosting() but using a
     673             :    * shim lets us forward-declare DofMap.
     674             :    */
     675             :   void _remove_default_ghosting(unsigned int sys_num);
     676             : };
     677             : 
     678             : 
     679             : 
     680             : // ------------------------------------------------------------
     681             : // EquationSystems inline methods
     682             : inline
     683        6256 : const MeshBase & EquationSystems::get_mesh () const
     684             : {
     685      122867 :   return _mesh;
     686             : }
     687             : 
     688             : 
     689             : 
     690             : inline
     691         254 : MeshBase & EquationSystems::get_mesh ()
     692             : {
     693      336289 :   return _mesh;
     694             : }
     695             : 
     696             : 
     697             : inline
     698           0 : unsigned int EquationSystems::n_systems () const
     699             : {
     700           0 :   return cast_int<unsigned int>(_systems.size());
     701             : }
     702             : 
     703             : 
     704             : 
     705             : 
     706             : template <typename T_sys>
     707             : inline
     708       15833 : T_sys & EquationSystems::add_system (std::string_view name)
     709             : {
     710       15833 :   if (!_systems.count(name))
     711             :     {
     712       14963 :       const unsigned int sys_num = this->n_systems();
     713             : 
     714        1422 :       auto result = _systems.emplace
     715       28978 :         (name, std::make_unique<T_sys>(*this, std::string(name),
     716             :                                        sys_num));
     717             : 
     718       15437 :       if (!_enable_default_ghosting)
     719           0 :         this->_remove_default_ghosting(sys_num);
     720             : 
     721             :       // Tell all the \p DofObject entities to add a system.
     722       15437 :       this->_add_system_to_nodes_and_elems();
     723             : 
     724             :       // Return reference to newly added item
     725         474 :       auto it = result.first;
     726         474 :       auto & sys_ptr = it->second;
     727         474 :       return cast_ref<T_sys &>(*sys_ptr);
     728             :     }
     729             :   else
     730             :     {
     731             :       // We now allow redundant add_system calls, to make it
     732             :       // easier to load data from files for user-derived system
     733             :       // subclasses
     734         396 :       return this->get_system<T_sys>(name);
     735             :     }
     736             : }
     737             : 
     738             : 
     739             : 
     740             : inline
     741         898 : bool EquationSystems::has_system (std::string_view name) const
     742             : {
     743         898 :   if (_systems.find(name) == _systems.end())
     744           0 :     return false;
     745         898 :   return true;
     746             : }
     747             : 
     748             : 
     749             : 
     750             : 
     751             : template <typename T_sys>
     752             : inline
     753       30308 : const T_sys & EquationSystems::get_system (const unsigned int num) const
     754             : {
     755         822 :   libmesh_assert_less (num, this->n_systems());
     756             : 
     757       32140 :   for (auto & pr : _systems)
     758             :     {
     759         862 :       const auto & sys_ptr = pr.second;
     760       32140 :       if (sys_ptr->number() == num)
     761       30308 :         return cast_ref<const T_sys &>(*sys_ptr);
     762             :     }
     763             :   // Error if we made it here
     764           0 :   libmesh_error_msg("ERROR: no system number " << num << " found!");
     765             : }
     766             : 
     767             : 
     768             : 
     769             : 
     770             : template <typename T_sys>
     771             : inline
     772      444135 : T_sys & EquationSystems::get_system (const unsigned int num)
     773             : {
     774       21402 :   libmesh_assert_less (num, this->n_systems());
     775             : 
     776      465360 :   for (auto & pr : _systems)
     777             :     {
     778       22044 :       auto & sys_ptr = pr.second;
     779      465360 :       if (sys_ptr->number() == num)
     780      444135 :         return cast_ref<T_sys &>(*sys_ptr);
     781             :     }
     782             : 
     783             :   // Error if we made it here
     784           0 :   libmesh_error_msg("ERROR: no system number " << num << " found!");
     785             : }
     786             : 
     787             : 
     788             : 
     789             : 
     790             : 
     791             : 
     792             : template <typename T_sys>
     793             : inline
     794       89263 : const T_sys & EquationSystems::get_system (std::string_view name) const
     795             : {
     796        2548 :   auto pos = _systems.find(name);
     797             : 
     798             :   // Check for errors
     799       89263 :   libmesh_error_msg_if(pos == _systems.end(), "ERROR: no system named \"" << name << "\" found!");
     800             : 
     801             :   // Attempt dynamic cast
     802        2548 :   const auto & sys_ptr = pos->second;
     803       91811 :   return cast_ref<const T_sys &>(*sys_ptr);
     804             : }
     805             : 
     806             : 
     807             : 
     808             : 
     809             : 
     810             : 
     811             : template <typename T_sys>
     812             : inline
     813       14967 : T_sys & EquationSystems::get_system (std::string_view name)
     814             : {
     815         418 :   auto pos = _systems.find(name);
     816             : 
     817             :   // Check for errors
     818       14967 :   libmesh_error_msg_if(pos == _systems.end(), "ERROR: no system named " << name << " found!");
     819             : 
     820             :   // Attempt dynamic cast
     821         418 :   auto & sys_ptr = pos->second;
     822       15385 :   return cast_ref<T_sys &>(*sys_ptr);
     823             : }
     824             : 
     825             : 
     826             : 
     827             : 
     828             : 
     829             : 
     830             : 
     831             : inline
     832        1798 : const System & EquationSystems::get_system (std::string_view name) const
     833             : {
     834       61861 :   return this->get_system<System>(name);
     835             : }
     836             : 
     837             : 
     838             : 
     839             : inline
     840         418 : System & EquationSystems::get_system (std::string_view name)
     841             : {
     842       16004 :   return this->get_system<System>(name);
     843             : }
     844             : 
     845             : 
     846             : 
     847             : inline
     848         822 : const System & EquationSystems::get_system (const unsigned int num) const
     849             : {
     850       30308 :   return this->get_system<System>(num);
     851             : }
     852             : 
     853             : 
     854             : 
     855             : inline
     856       21402 : System & EquationSystems::get_system (const unsigned int num)
     857             : {
     858      444135 :   return this->get_system<System>(num);
     859             : }
     860             : 
     861             : 
     862             : } // namespace libMesh
     863             : 
     864             : 
     865             : #endif // LIBMESH_EQUATION_SYSTEMS_H

Generated by: LCOV version 1.14