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