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
|