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 24720 : 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.
289 : */
290 : static bool is_elemental_data_fe_type (const FEType & type);
291 :
292 : /**
293 : * Filter \p var_names to names of variables that can be represented as
294 : * elemental data. If \p var_names is empty, all eligible variable names are
295 : * returned. Vector-valued variables are decomposed into component names.
296 : * If \p system_names!=nullptr, only include names from the specified systems.
297 : */
298 : void build_elemental_data_variable_names
299 : (std::vector<std::string> & var_names,
300 : const std::set<std::string> * system_names=nullptr) const;
301 :
302 : /**
303 : * Fill the input vector \p soln with the solution values for the
304 : * system named \p name.
305 : *
306 : * \note The input vector \p soln will only be assembled on
307 : * processor 0, so this method is only applicable to outputting plot
308 : * files from processor 0.
309 : */
310 : void build_solution_vector (std::vector<Number> & soln,
311 : std::string_view system_name,
312 : std::string_view variable_name = "all_vars") const;
313 :
314 : /**
315 : * Fill the input vector \p soln with solution values. The
316 : * entries will be in node-major format (corresponding to
317 : * the names from \p build_variable_names()).
318 : *
319 : * If systems_names!=nullptr, only include data from the
320 : * specified systems.
321 : *
322 : * If \p add_sides is true, append data for plotting on "side
323 : * elements" too.
324 : */
325 : void build_solution_vector (std::vector<Number> & soln,
326 : const std::set<std::string> * system_names=nullptr,
327 : bool add_sides=false) const;
328 :
329 : /**
330 : * A version of build_solution_vector which is appropriate for
331 : * "parallel" output formats like Nemesis.
332 : *
333 : * \returns A std::unique_ptr to a node-major NumericVector of total
334 : * length n_nodes*n_vars that various I/O classes can then use to
335 : * get the local values they need to write on each processor.
336 : */
337 : std::unique_ptr<NumericVector<Number>>
338 : build_parallel_solution_vector(const std::set<std::string> * system_names=nullptr,
339 : bool add_sides=false) const;
340 :
341 : /**
342 : * Retrieve \p vars_active_subdomains, which indicates the active
343 : * subdomains for each variable in \p names.
344 : */
345 : void get_vars_active_subdomains(const std::vector<std::string> & names,
346 : std::vector<std::set<subdomain_id_type>> & vars_active_subdomains) const;
347 :
348 : /**
349 : * Retrieve the solution data for elemental data variables. If 'names' is
350 : * populated, only the variables corresponding to those names will be
351 : * retrieved. This can be used to filter which variables are retrieved.
352 : *
353 : * This is the more appropriately-named replacement for the get_solution()
354 : * function defined above.
355 : */
356 : void build_elemental_solution_vector (std::vector<Number> & soln,
357 : std::vector<std::string> & names) const;
358 :
359 : /**
360 : * Finds system and variable numbers for any variables of 'type' or of
361 : * 'types' corresponding to the entries in the input 'names' vector.
362 : * If 'names' is empty, this returns all variables of the type.
363 : * The names of vector variables are decomposed into individual ones
364 : * suffixed with their cartesian component, but there will still be
365 : * a single pair of system numbers for such vector variables. Thus,
366 : * the size of the 'names' vector modified by this function may not
367 : * be equal to that of the returned vector of pairs. Nevertheless, both
368 : * should be sorted in accordance with ExodusII format, and so the
369 : * developer just needs to know to separate dof_indices when
370 : * accessing the system solution for vector variables.
371 : *
372 : * This function is designed to work for either a single type or a
373 : * vector of types, but not both. This is because it can't simply be
374 : * called a second time with another type as it filters (deletes) the
375 : * names of those on the first call that used a different type. Thus,
376 : * the 'types' argument is for the case where variables of multiple
377 : * types are allowed to pass through.
378 : *
379 : * TODO: find a more generic way to handle this whole procedure.
380 : */
381 : std::vector<std::pair<unsigned int, unsigned int>>
382 : find_variable_numbers (std::vector<std::string> & names,
383 : const FEType * type=nullptr,
384 : const std::vector<FEType> * types=nullptr) const;
385 :
386 : /**
387 : * Finds system and variable numbers for variables that can be represented
388 : * as elemental data. See find_variable_numbers() for name filtering,
389 : * component decomposition, and sorting details.
390 : */
391 : std::vector<std::pair<unsigned int, unsigned int>>
392 : find_elemental_data_variable_numbers (std::vector<std::string> & names) const;
393 :
394 : /**
395 : * Builds a parallel vector of elemental data solution values corresponding to the entries
396 : * in the input 'names' vector. This vector is approximately uniformly
397 : * distributed across all of the available processors.
398 : *
399 : * The related function build_elemental_solution_vector() is
400 : * implemented by calling this function and then calling
401 : * localize_to_one() on the resulting vector.
402 : *
403 : * Returns a nullptr if no elemental data variables exist in the 'names'
404 : * vector (if it is empty, then it will return all variables in the system
405 : * of this type if any) or a std::unique_ptr to
406 : * a var-major numeric vector of total length n_elem * n_vars, where
407 : * n_vars includes all components of vectors, ordered according to:
408 : * [u0, u1, ... uN, v0, v1, ... vN, w0, w1, ... wN] for elemental data
409 : * variables (u, v, w) on a mesh with N elements.
410 : */
411 : std::unique_ptr<NumericVector<Number>>
412 : build_parallel_elemental_solution_vector (std::vector<std::string> & names) const;
413 :
414 : /**
415 : * Fill the input vector \p soln with solution values. The
416 : * entries will be in geometry-major format: element, then local
417 : * node/vertex, then variable.
418 :
419 : * If systems_names!=nullptr, only include data from the
420 : * specified systems.
421 :
422 : * If vertices_only == true, then for higher-order elements only
423 : * the solution at the vertices is computed. This can be useful
424 : * when plotting discontinuous solutions on higher-order elements
425 : * and only a lower-order representation is required.
426 : *
427 : * If add_sides == true, append data for plotting on "side
428 : * elements" too.
429 : */
430 : void build_discontinuous_solution_vector
431 : (std::vector<Number> & soln,
432 : const std::set<std::string> * system_names = nullptr,
433 : const std::vector<std::string> * var_names = nullptr,
434 : bool vertices_only = false,
435 : bool add_sides = false) const;
436 :
437 : /*
438 : * Returns true iff the given side of the given element is *never*
439 : * added to output from that element, because it is considered to be
440 : * redundant with respect to the same data added from the
441 : * neighboring element sharing that side. This helper function is
442 : * used with the add_sides option when building solution vectors
443 : * here and when outputting solution vectors in MeshOutput
444 : * (currently just Exodus) I/O.
445 : */
446 : static bool redundant_added_side(const Elem & elem, unsigned int side);
447 :
448 :
449 : /**
450 : * Read & initialize the systems from disk using the XDR data format.
451 : * This format allows for machine-independent binary output.
452 : *
453 : * Set which sections of the file to read by bitwise OR'ing the
454 : * EquationSystems::ReadFlags enumeration together. For example, to
455 : * read all sections of the file, set read_flags to:
456 : * (READ_HEADER | READ_DATA | READ_ADDITIONAL_DATA)
457 : *
458 : * \note The equation system can be defined without initializing
459 : * the data vectors to any solution values. This can be done
460 : * by omitting READ_DATA in the read_flags parameter.
461 : *
462 : * If XdrMODE is omitted, it will be inferred as READ for filenames
463 : * containing .xda or as DECODE for filenames containing .xdr
464 : *
465 : * \param name Name of the file to be read.
466 : * \param read_flags Single flag created by bitwise-OR'ing several flags together.
467 : * \param mode Controls whether reading is done in binary or ascii mode.
468 : * \param partition_agnostic If true then the mesh and degrees of freedom
469 : * will be temporarily renumbered in a partition agnostic way so that
470 : * files written using "n" mpi processes can be re-read on "m" mpi
471 : * processes. This renumbering is not compatible with meshes
472 : * that have two nodes in exactly the same position!
473 : */
474 : template <typename InValType = Number>
475 : void read (std::string_view name,
476 : const XdrMODE,
477 : const unsigned int read_flags=(READ_HEADER | READ_DATA),
478 : bool partition_agnostic = true);
479 :
480 : template <typename InValType = Number>
481 : void read (std::string_view name,
482 : const unsigned int read_flags=(READ_HEADER | READ_DATA),
483 : bool partition_agnostic = true);
484 :
485 : template <typename InValType = Number>
486 : void read (Xdr & io,
487 : std::function<std::unique_ptr<Xdr>()> & local_io_functor,
488 : const unsigned int read_flags=(READ_HEADER | READ_DATA),
489 : bool partition_agnostic = true);
490 :
491 : /**
492 : * Write the systems to disk using the XDR data format.
493 : * This format allows for machine-independent binary output.
494 : *
495 : * Set the writing properties using the EquationSystems::WriteFlags
496 : * enumeration. Set which sections to write out by bitwise OR'ing
497 : * the enumeration values. Write everything by setting write_flags to:
498 : * (WRITE_DATA | WRITE_ADDITIONAL_DATA)
499 : *
500 : * \note The solution data can be omitted by calling
501 : * this routine with WRITE_DATA omitted in the write_flags argument.
502 : *
503 : * If XdrMODE is omitted, it will be inferred as WRITE for filenames
504 : * containing .xda or as ENCODE for filenames containing .xdr
505 : *
506 : * \param name Name of the file to be read.
507 : * \param write_flags Single flag created by bitwise-OR'ing several flags together.
508 : * \param mode Controls whether reading is done in binary or ascii mode.
509 : * \param partition_agnostic If true then the mesh and degrees of freedom
510 : * will be temporarily renumbered in a partition agnostic way so that
511 : * files written using "n" mpi processes can be re-read on "m" mpi
512 : * processes. This renumbering is not compatible with meshes
513 : * that have two nodes in exactly the same position!
514 : */
515 : void write (std::string_view name,
516 : const XdrMODE,
517 : const unsigned int write_flags=(WRITE_DATA),
518 : bool partition_agnostic = true) const;
519 :
520 : void write (std::string_view name,
521 : const unsigned int write_flags=(WRITE_DATA),
522 : bool partition_agnostic = true) const;
523 :
524 : void write (std::ostream name,
525 : const unsigned int write_flags=(WRITE_DATA),
526 : bool partition_agnostic = true) const;
527 :
528 : void write (Xdr & io,
529 : const unsigned int write_flags=(WRITE_DATA),
530 : bool partition_agnostic = true,
531 : Xdr * const local_io = nullptr) const;
532 :
533 : /**
534 : * \returns \p true when this equation system contains
535 : * identical data, up to the given threshold. Delegates
536 : * most of the comparisons to perform to the responsible
537 : * systems
538 : */
539 : virtual bool compare (const EquationSystems & other_es,
540 : const Real threshold,
541 : const bool verbose) const;
542 :
543 : /**
544 : * \returns A string containing information about the
545 : * systems, flags, and parameters.
546 : */
547 : virtual std::string get_info() const;
548 :
549 : /**
550 : * Prints information about the equation systems, by default to
551 : * libMesh::out.
552 : */
553 : void print_info (std::ostream & os=libMesh::out) const;
554 :
555 : /**
556 : * Same as above, but allows you to also use stream syntax.
557 : */
558 : friend std::ostream & operator << (std::ostream & os,
559 : const EquationSystems & es);
560 :
561 : /**
562 : * \returns A constant reference to the mesh
563 : */
564 : const MeshBase & get_mesh() const;
565 :
566 : /**
567 : * \returns A reference to the mesh
568 : */
569 : MeshBase & get_mesh();
570 :
571 : /**
572 : * Serializes a distributed mesh and its associated
573 : * degree of freedom numbering for all systems
574 : **/
575 : void allgather ();
576 :
577 : /**
578 : * Calls to reinit() will also do two-step coarsen-then-refine
579 : **/
580 : void enable_refine_in_reinit() { this->_refine_in_reinit = true; }
581 :
582 : /**
583 : * Calls to reinit() will not try to coarsen or refine the mesh
584 : **/
585 : void disable_refine_in_reinit() { this->_refine_in_reinit = false; }
586 :
587 : /**
588 : * \returns Whether or not calls to reinit() will try to coarsen/refine the mesh
589 : **/
590 : bool refine_in_reinit_flag() { return this->_refine_in_reinit; }
591 :
592 : /**
593 : * Handle any mesh changes and project any solutions onto the
594 : * updated mesh.
595 : *
596 : * \returns Whether or not the mesh may have changed.
597 : */
598 : bool reinit_solutions ();
599 :
600 : /**
601 : * Reinitialize all systems on the current mesh.
602 : */
603 : virtual void reinit_systems ();
604 :
605 : /**
606 : * Data structure holding arbitrary parameters.
607 : */
608 : Parameters parameters;
609 :
610 :
611 : protected:
612 :
613 :
614 : /**
615 : * The mesh data structure
616 : */
617 : MeshBase & _mesh;
618 :
619 : /**
620 : * Data structure holding the systems.
621 : */
622 : std::map<std::string, std::unique_ptr<System>, std::less<>> _systems;
623 :
624 : /**
625 : * Flag for whether to call coarsen/refine in reinit().
626 : * Default value: true
627 : */
628 : bool _refine_in_reinit;
629 :
630 : /**
631 : * Flag for whether to enable default ghosting on newly added Systems.
632 : * Default value: true
633 : */
634 : bool _enable_default_ghosting;
635 :
636 : private:
637 : /**
638 : * Implementation detail for find_variable_numbers() variants.
639 : */
640 : std::vector<std::pair<unsigned int, unsigned int>>
641 : find_variable_numbers_by_predicate
642 : (std::vector<std::string> & names,
643 : const std::function<bool(const FEType &)> & type_filter) const;
644 :
645 : /**
646 : * This function is used in the implementation of add_system,
647 : * it loops over the nodes and elements of the Mesh, adding the
648 : * system to each one. The main reason to separate this part
649 : * is to avoid coupling this header file to mesh.h, and elem.h.
650 : */
651 : void _add_system_to_nodes_and_elems();
652 :
653 : /**
654 : * This just calls DofMap::remove_default_ghosting() but using a
655 : * shim lets us forward-declare DofMap.
656 : */
657 : void _remove_default_ghosting(unsigned int sys_num);
658 : };
659 :
660 :
661 :
662 : // ------------------------------------------------------------
663 : // EquationSystems inline methods
664 : inline
665 6248 : const MeshBase & EquationSystems::get_mesh () const
666 : {
667 122658 : return _mesh;
668 : }
669 :
670 :
671 :
672 : inline
673 246 : MeshBase & EquationSystems::get_mesh ()
674 : {
675 278869 : return _mesh;
676 : }
677 :
678 :
679 : inline
680 0 : unsigned int EquationSystems::n_systems () const
681 : {
682 0 : return cast_int<unsigned int>(_systems.size());
683 : }
684 :
685 :
686 :
687 :
688 : template <typename T_sys>
689 : inline
690 15707 : T_sys & EquationSystems::add_system (std::string_view name)
691 : {
692 15707 : if (!_systems.count(name))
693 : {
694 14833 : const unsigned int sys_num = this->n_systems();
695 :
696 1434 : auto result = _systems.emplace
697 28710 : (name, std::make_unique<T_sys>(*this, std::string(name),
698 : sys_num));
699 :
700 15311 : if (!_enable_default_ghosting)
701 0 : this->_remove_default_ghosting(sys_num);
702 :
703 : // Tell all the \p DofObject entities to add a system.
704 15311 : this->_add_system_to_nodes_and_elems();
705 :
706 : // Return reference to newly added item
707 478 : auto it = result.first;
708 478 : auto & sys_ptr = it->second;
709 478 : return cast_ref<T_sys &>(*sys_ptr);
710 : }
711 : else
712 : {
713 : // We now allow redundant add_system calls, to make it
714 : // easier to load data from files for user-derived system
715 : // subclasses
716 396 : return this->get_system<T_sys>(name);
717 : }
718 : }
719 :
720 :
721 :
722 : inline
723 894 : bool EquationSystems::has_system (std::string_view name) const
724 : {
725 894 : if (_systems.find(name) == _systems.end())
726 0 : return false;
727 894 : return true;
728 : }
729 :
730 :
731 :
732 :
733 : template <typename T_sys>
734 : inline
735 29811 : const T_sys & EquationSystems::get_system (const unsigned int num) const
736 : {
737 808 : libmesh_assert_less (num, this->n_systems());
738 :
739 31643 : for (auto & pr : _systems)
740 : {
741 848 : const auto & sys_ptr = pr.second;
742 31643 : if (sys_ptr->number() == num)
743 29811 : return cast_ref<const T_sys &>(*sys_ptr);
744 : }
745 : // Error if we made it here
746 0 : libmesh_error_msg("ERROR: no system number " << num << " found!");
747 : }
748 :
749 :
750 :
751 :
752 : template <typename T_sys>
753 : inline
754 381299 : T_sys & EquationSystems::get_system (const unsigned int num)
755 : {
756 17968 : libmesh_assert_less (num, this->n_systems());
757 :
758 402453 : for (auto & pr : _systems)
759 : {
760 18606 : auto & sys_ptr = pr.second;
761 402453 : if (sys_ptr->number() == num)
762 381299 : return cast_ref<T_sys &>(*sys_ptr);
763 : }
764 :
765 : // Error if we made it here
766 0 : libmesh_error_msg("ERROR: no system number " << num << " found!");
767 : }
768 :
769 :
770 :
771 :
772 :
773 :
774 : template <typename T_sys>
775 : inline
776 88837 : const T_sys & EquationSystems::get_system (std::string_view name) const
777 : {
778 2536 : auto pos = _systems.find(name);
779 :
780 : // Check for errors
781 88837 : libmesh_error_msg_if(pos == _systems.end(), "ERROR: no system named \"" << name << "\" found!");
782 :
783 : // Attempt dynamic cast
784 2536 : const auto & sys_ptr = pos->second;
785 91373 : return cast_ref<const T_sys &>(*sys_ptr);
786 : }
787 :
788 :
789 :
790 :
791 :
792 :
793 : template <typename T_sys>
794 : inline
795 14967 : T_sys & EquationSystems::get_system (std::string_view name)
796 : {
797 418 : auto pos = _systems.find(name);
798 :
799 : // Check for errors
800 14967 : libmesh_error_msg_if(pos == _systems.end(), "ERROR: no system named " << name << " found!");
801 :
802 : // Attempt dynamic cast
803 418 : auto & sys_ptr = pos->second;
804 15385 : return cast_ref<T_sys &>(*sys_ptr);
805 : }
806 :
807 :
808 :
809 :
810 :
811 :
812 :
813 : inline
814 1790 : const System & EquationSystems::get_system (std::string_view name) const
815 : {
816 61577 : return this->get_system<System>(name);
817 : }
818 :
819 :
820 :
821 : inline
822 418 : System & EquationSystems::get_system (std::string_view name)
823 : {
824 16004 : return this->get_system<System>(name);
825 : }
826 :
827 :
828 :
829 : inline
830 808 : const System & EquationSystems::get_system (const unsigned int num) const
831 : {
832 29811 : return this->get_system<System>(num);
833 : }
834 :
835 :
836 :
837 : inline
838 17968 : System & EquationSystems::get_system (const unsigned int num)
839 : {
840 381299 : return this->get_system<System>(num);
841 : }
842 :
843 :
844 : } // namespace libMesh
845 :
846 :
847 : #endif // LIBMESH_EQUATION_SYSTEMS_H
|