Line data Source code
1 : //* This file is part of the MOOSE framework
2 : //* https://mooseframework.inl.gov
3 : //*
4 : //* All rights reserved, see COPYRIGHT for full restrictions
5 : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 : //*
7 : //* Licensed under LGPL 2.1, please see LICENSE for details
8 : //* https://www.gnu.org/licenses/lgpl-2.1.html
9 :
10 : #pragma once
11 :
12 : #include "THMObject.h"
13 : #include "FlowModel.h"
14 : #include "THMProblem.h"
15 : #include "InputParameterWarehouse.h"
16 : #include "LoggingInterface.h"
17 : #include "NamingInterface.h"
18 : #include "ADFunctorInterface.h"
19 :
20 : class THMProblem;
21 : class THMMesh;
22 : class ThermalHydraulicsApp;
23 :
24 : /**
25 : * Base class for THM components
26 : */
27 : class Component : public THMObject,
28 : public LoggingInterface,
29 : public NamingInterface,
30 : public ADFunctorInterface
31 : {
32 : public:
33 : Component(const InputParameters & parameters);
34 :
35 : /// Component setup status type
36 : enum EComponentSetupStatus
37 : {
38 : CREATED, ///< only created
39 : MESH_PREPARED, ///< mesh set up
40 : INITIALIZED_PRIMARY, ///< mesh set up, called primary init
41 : INITIALIZED_SECONDARY, ///< mesh set up, called both inits
42 : CHECKED ///< mesh set up, called both inits, checked
43 : };
44 :
45 : /// Return a string for the setup status
46 : std::string stringify(EComponentSetupStatus status) const;
47 :
48 : /**
49 : * Get the component name
50 : * @return The name of the component. For composite component, return its parent name
51 : */
52 : const std::string & cname() const;
53 :
54 15548 : Component * parent() { return _parent; }
55 :
56 : /**
57 : * Const reference to mesh, which can be called at any point
58 : *
59 : * Note that overloading mesh() was not possible due to the need to call this
60 : * const version, even when the component is not const.
61 : */
62 3947 : const THMMesh & constMesh() const { return _mesh; }
63 :
64 : /**
65 : * Non-const reference to THM mesh, which can only be called before the end of mesh setup
66 : */
67 : THMMesh & mesh();
68 :
69 : /**
70 : * Gets the THM problem
71 : */
72 : THMProblem & getTHMProblem() const;
73 :
74 : /**
75 : * Test if a parameter exists in the object's input parameters
76 : * @param name The name of the parameter
77 : * @return true if the parameter exists, false otherwise
78 : */
79 : template <typename T>
80 : bool hasParam(const std::string & name) const;
81 :
82 : /**
83 : * Returns a list of names of components that this component depends upon
84 : */
85 : const std::vector<std::string> & getDependencies() const { return _dependencies; }
86 :
87 : /**
88 : * Wrapper function for \c init() that marks the function as being called
89 : */
90 : void executeInit();
91 :
92 : /**
93 : * Wrapper function for \c initSecondary() that marks the function as being called
94 : */
95 : void executeInitSecondary();
96 :
97 : /**
98 : * Wrapper function for \c check() that marks the function as being called
99 : */
100 : void executeCheck() const;
101 :
102 : /**
103 : * Wrapper function for \c setupMesh() that marks the function as being called
104 : */
105 : void executeSetupMesh();
106 :
107 : /**
108 : * Adds relationship managers for the component
109 : */
110 15611 : virtual void addRelationshipManagers(Moose::RelationshipManagerType /*input_rm_type*/) {}
111 :
112 6258 : virtual void addVariables() {}
113 :
114 24 : virtual void addMooseObjects() {}
115 :
116 : /**
117 : * Return a reference to a component via a parameter name
118 : * @tparam T the type of the component we are requesting
119 : * @param name The parameter name that has the component name
120 : */
121 : template <typename T>
122 : const T & getComponent(const std::string & name) const;
123 :
124 : /**
125 : * Return a reference to a component given its name
126 : * @tparam T the type of the component we are requesting
127 : * @param cname The name of the component
128 : */
129 : template <typename T>
130 : const T & getComponentByName(const std::string & cname) const;
131 :
132 : /**
133 : * Check the existence and type of a component via a parameter name
134 : * @tparam T the type of the component we are requesting
135 : * @param name The parameter name that has the component name
136 : * @return true if the component with given name and type exists, otherwise false
137 : */
138 : template <typename T>
139 : bool hasComponent(const std::string & name) const;
140 :
141 : /**
142 : * Check the existence and type of a component given its name
143 : * @tparam T the type of the component we are requesting
144 : * @param cname The name of the component
145 : * @return true if the component with given name and type exists, otherwise false
146 : */
147 : template <typename T>
148 : bool hasComponentByName(const std::string & cname) const;
149 :
150 : /**
151 : * Connect with control logic
152 : */
153 : void connectObject(const InputParameters & params,
154 : const std::string & mooseName,
155 : const std::string & name) const;
156 : /**
157 : * Connect with control logic
158 : */
159 : void connectObject(const InputParameters & params,
160 : const std::string & mooseName,
161 : const std::string & name,
162 : const std::string & par_name) const;
163 :
164 : /**
165 : * Makes a function controllable if it is constant
166 : *
167 : * @param[in] fn_name name of the function
168 : * @param[in] control_name name of control parameter
169 : * @param[in] param name of controlled parameter
170 : */
171 : void makeFunctionControllableIfConstant(const FunctionName & fn_name,
172 : const std::string & control_name,
173 : const std::string & param = "value") const;
174 :
175 : /**
176 : * Throws an error if the supplied setup status of this component has not been reached
177 : *
178 : * This is useful for getter functions that rely on data initialized after the
179 : * constructor; if an error is not thrown, then uninitialized data could be
180 : * returned from these functions.
181 : *
182 : * @param[in] status Setup status that this component must have reached
183 : */
184 : void checkSetupStatus(const EComponentSetupStatus & status) const;
185 :
186 : /**
187 : * Checks that a component exists
188 : *
189 : * @param[in] comp_name name of the component
190 : */
191 : void checkComponentExistsByName(const std::string & comp_name) const;
192 :
193 : /**
194 : * Checks that the component of a certain type exists, where the name is given by a parameter
195 : *
196 : * @tparam T enforced type of component
197 : * @param[in] param parameter name for component name
198 : */
199 : template <typename T>
200 : void checkComponentOfTypeExists(const std::string & param) const;
201 :
202 : /**
203 : * Checks that the component of a certain type exists
204 : *
205 : * @tparam T enforced type of component
206 : * @param[in] comp_name component name
207 : */
208 : template <typename T>
209 : void checkComponentOfTypeExistsByName(const std::string & comp_name) const;
210 :
211 : /**
212 : * Logs an error
213 : */
214 : template <typename... Args>
215 267 : void logError(Args &&... args) const
216 : {
217 267 : logComponentError(cname(), std::forward<Args>(args)...);
218 267 : }
219 :
220 : /**
221 : * Logs a warning
222 : */
223 : template <typename... Args>
224 46 : void logWarning(Args &&... args) const
225 : {
226 46 : logComponentWarning(cname(), std::forward<Args>(args)...);
227 46 : }
228 :
229 : /**
230 : * Adds a component name to the list of dependencies
231 : *
232 : * @param[in] dependency name of component to add to list of dependencies
233 : */
234 : void addDependency(const std::string & dependency);
235 :
236 : /**
237 : * Gets an enum parameter
238 : *
239 : * This function takes the name of a MooseEnum parameter that is tied to an
240 : * enum defined in THM. If the value is invalid, an error will be logged,
241 : * and a negative integer will be cast into the enum type.
242 : *
243 : * @tparam T enum type
244 : * @param[in] param name of the MooseEnum parameter
245 : * @param[in] log_error If true, log an error if the valid is invalid
246 : */
247 : template <typename T>
248 : T getEnumParam(const std::string & param, bool log_error = true) const;
249 :
250 : /**
251 : * Whether the problem is transient
252 : */
253 13872 : bool problemIsTransient() const { return getTHMProblem().isTransient(); }
254 :
255 : /**
256 : * Gets the node IDs corresponding to this component
257 : */
258 : const std::vector<dof_id_type> & getNodeIDs() const;
259 :
260 : /**
261 : * Gets the element IDs corresponding to this component
262 : */
263 : const std::vector<dof_id_type> & getElementIDs() const;
264 :
265 : /**
266 : * Gets the subdomain names for this component
267 : *
268 : * @return vector of subdomain names for this component
269 : */
270 : virtual const std::vector<SubdomainName> & getSubdomainNames() const;
271 :
272 : /**
273 : * Gets the coordinate system types for this component
274 : *
275 : * @return vector of coordinate system types for this component
276 : */
277 : virtual const std::vector<Moose::CoordinateSystemType> & getCoordSysTypes() const;
278 :
279 : /**
280 : * Runtime check to make sure that a parameter of specified type exists in the component's input
281 : * parameters
282 : *
283 : * This is intended to help developers write code. The idea is to provide a useful message when
284 : * developers make typos, etc. If this check fails, the code execution will be stopped.
285 : *
286 : * @tparam T The type of the parameter to be checked
287 : * @param function_name The name of the function calling this method
288 : * @param param_name The name of the parameter to be checked
289 : */
290 : template <typename T>
291 : void insistParameterExists(const std::string & function_name,
292 : const std::string & param_name) const;
293 :
294 : /**
295 : * Checks that a parameter value is less than a value
296 : *
297 : * @tparam T type of parameter
298 : * @param[in] param parameter name
299 : * @param[in] value_max value which parameter value must be less than
300 : */
301 : template <typename T>
302 : void checkParameterValueLessThan(const std::string & param, const T & value_max) const;
303 :
304 : /**
305 : * Checks that the size of a vector parameter is less than a value
306 : *
307 : * @tparam T type of element in the vector parameter
308 : * @param[in] param parameter name
309 : * @param[in] n_entries value which parameter size must be less than
310 : */
311 : template <typename T>
312 : void checkSizeLessThan(const std::string & param, const unsigned int & n_entries) const;
313 :
314 : /**
315 : * Checks that the size of a vector parameter is greater than a value
316 : *
317 : * @tparam T type of element in the vector parameter
318 : * @param[in] param parameter name
319 : * @param[in] n_entries value which parameter size must be greater than
320 : */
321 : template <typename T>
322 : void checkSizeGreaterThan(const std::string & param, const unsigned int & n_entries) const;
323 :
324 : /**
325 : * Checks that the size of two vector parameters are equal
326 : *
327 : * @tparam T1 type of element in the first vector parameter
328 : * @tparam T2 type of element in the second vector parameter
329 : * @param[in] param1 first parameter name
330 : * @param[in] param2 second parameter name
331 : */
332 : template <typename T1, typename T2>
333 : void checkEqualSize(const std::string & param1, const std::string & param2) const;
334 :
335 : /**
336 : * Checks that the size of a vector parameter equals a value
337 : *
338 : * This version does not supply a description to the value.
339 : *
340 : * @tparam T type of element in the vector parameter
341 : * @param[in] param parameter name
342 : * @param[in] n_entries value which parameter size must be equal to
343 : */
344 : template <typename T>
345 : void checkSizeEqualsValue(const std::string & param, const unsigned int & n_entries) const;
346 :
347 : /**
348 : * Checks that the size of a vector parameter equals a value
349 : *
350 : * This version supplies a description to the value.
351 : *
352 : * @tparam T type of element in the vector parameter
353 : * @param[in] param parameter name
354 : * @param[in] n_entries value which parameter size must be equal to
355 : * @param[in] description description of the value that size must be equal to
356 : */
357 : template <typename T>
358 : void checkSizeEqualsValue(const std::string & param,
359 : const unsigned int & n_entries,
360 : const std::string & description) const;
361 :
362 : /**
363 : * Checks that the size of a vector parameter equals the value of another parameter
364 : *
365 : * @tparam T1 type of element in the vector parameter
366 : * @tparam T2 type of the parameter whose value is compared to size
367 : * @param[in] param1 vector parameter name
368 : * @param[in] param2 name of parameter whose value is compared to size
369 : */
370 : template <typename T1, typename T2>
371 : void checkSizeEqualsParameterValue(const std::string & param1, const std::string & param2) const;
372 :
373 : /**
374 : * Checks that exactly one parameter out of a list is provided
375 : *
376 : * @param[in] params vector of parameter names
377 : * @param[in] need_one_specified Need one of the parameters specified?
378 : */
379 : void checkMutuallyExclusiveParameters(const std::vector<std::string> & params,
380 : bool need_one_specified = true) const;
381 :
382 : protected:
383 : /**
384 : * Initializes the component
385 : *
386 : * The reason this function exists (as opposed to just having everything in
387 : * the constructor) is because some initialization depends on all components
388 : * existing, since many components couple to other components. Therefore,
389 : * when deciding whether code should go into the constructor or this function,
390 : * one should use the following reasoning: if an operation does not require
391 : * the existence of other components, then put that operation in the
392 : * constructor; otherwise, put it in this function.
393 : */
394 1364 : virtual void init() {}
395 :
396 : /**
397 : * Perform secondary initialization, which relies on init() being called
398 : * for all components.
399 : */
400 8823 : virtual void initSecondary() {}
401 :
402 : /**
403 : * Check the component integrity
404 : */
405 343 : virtual void check() const {}
406 :
407 : /**
408 : * Performs mesh setup such as creating mesh or naming mesh sets
409 : */
410 2403 : virtual void setupMesh() {}
411 :
412 : /**
413 : * Method to add a relationship manager for the objects being added to the system. Relationship
414 : * managers have to be added relatively early. In many cases before the Action::act() method
415 : * is called.
416 : *
417 : * This method was copied from Action.
418 : *
419 : * @param moose_object_pars The MooseObject to inspect for RelationshipManagers to add
420 : */
421 : void addRelationshipManagersFromParameters(const InputParameters & moose_object_pars);
422 :
423 : Node * addNode(const Point & pt);
424 : Elem * addNodeElement(dof_id_type node);
425 :
426 : /**
427 : * Sets the next subdomain ID, name, and coordinate system
428 : *
429 : * @param[in] subdomain_id subdomain index
430 : * @param[in] subdomain_name name of the new subdomain
431 : * @param[in] coord_system type of coordinate system
432 : */
433 : virtual void
434 : setSubdomainInfo(SubdomainID subdomain_id,
435 : const std::string & subdomain_name,
436 10632 : const Moose::CoordinateSystemType & coord_system = Moose::COORD_XYZ);
437 :
438 : /// Pointer to a parent component (used in composed components)
439 : Component * _parent;
440 :
441 : /// THM problem this component is part of
442 : /// TODO: make _sim private (applications need to switch to getters to avoid breaking).
443 : /// Also, rename to "_thm_problem" at that point.
444 : THMProblem & _sim;
445 :
446 : /// The Factory associated with the MooseApp
447 : Factory & _factory;
448 :
449 : const Real & _zero;
450 :
451 : /// The THM mesh
452 : /// TODO: make _mesh private (applications need to switch to getters to avoid breaking)
453 : THMMesh & _mesh;
454 :
455 : /// Node IDs of this component
456 : std::vector<dof_id_type> _node_ids;
457 : /// Element IDs of this component
458 : std::vector<dof_id_type> _elem_ids;
459 :
460 : /// List of subdomain IDs this components owns
461 : std::vector<SubdomainID> _subdomain_ids;
462 : /// List of subdomain names this components owns
463 : std::vector<SubdomainName> _subdomain_names;
464 : /// List of coordinate system for each subdomain
465 : std::vector<Moose::CoordinateSystemType> _coord_sys;
466 :
467 : private:
468 : /**
469 : * Method for adding a single relationship manager
470 : *
471 : * This method was copied from Action.
472 : *
473 : * @param moose_object_pars The parameters of the MooseObject that requested the RM
474 : * @param rm_name The class type of the RM, e.g. ElementSideNeighborLayers
475 : * @param rm_type The RelationshipManagerType, e.g. geometric, algebraic, coupling
476 : * @param rm_input_parameter_func The RM callback function, typically a lambda defined in the
477 : * requesting MooseObject's validParams function
478 : * @param sys_type A RMSystemType that can be used to limit the systems and consequent dof_maps
479 : * that the RM can be attached to
480 : */
481 : void
482 : addRelationshipManager(const InputParameters & moose_object_pars,
483 : std::string rm_name,
484 : Moose::RelationshipManagerType rm_type,
485 : Moose::RelationshipManagerInputParameterCallback rm_input_parameter_func,
486 : Moose::RMSystemType sys_type = Moose::RMSystemType::NONE);
487 :
488 : /// Component setup status
489 : mutable EComponentSetupStatus _component_setup_status;
490 :
491 : /// List of names of components that this component depends upon
492 : std::vector<std::string> _dependencies;
493 :
494 : public:
495 : static InputParameters validParams();
496 : };
497 :
498 : template <typename T>
499 : bool
500 32999 : Component::hasParam(const std::string & name) const
501 : {
502 32999 : return parameters().have_parameter<T>(name);
503 : }
504 :
505 : template <typename T>
506 : const T &
507 950 : Component::getComponent(const std::string & pname) const
508 : {
509 : const std::string & comp_name = getParam<std::string>(pname);
510 950 : return getComponentByName<T>(comp_name);
511 : }
512 :
513 : template <typename T>
514 : const T &
515 : Component::getComponentByName(const std::string & comp_name) const
516 : {
517 30989 : return _sim.getComponentByName<T>(comp_name);
518 : }
519 :
520 : template <typename T>
521 : bool
522 482 : Component::hasComponent(const std::string & pname) const
523 : {
524 : const std::string & comp_name = getParam<std::string>(pname);
525 482 : return hasComponentByName<T>(comp_name);
526 : }
527 :
528 : template <typename T>
529 : bool
530 : Component::hasComponentByName(const std::string & comp_name) const
531 : {
532 47462 : if (_sim.hasComponentOfType<T>(comp_name))
533 : return true;
534 : else
535 : return false;
536 : }
537 :
538 : template <typename T>
539 : T
540 8680 : Component::getEnumParam(const std::string & param, bool log_error) const
541 : {
542 : const MooseEnum & moose_enum = getParam<MooseEnum>(param);
543 8680 : const T value = THM::stringToEnum<T>(moose_enum);
544 8680 : if (log_error && static_cast<int>(value) < 0) // cast necessary for scoped enums
545 : {
546 : // Get the keys from the MooseEnum. Unfortunately, this returns a list of
547 : // *all* keys, including the invalid key that was supplied. Thus, that key
548 : // needs to be manually excluded below.
549 0 : const std::vector<std::string> & keys = moose_enum.getNames();
550 :
551 : // Create the string of keys to go in the error message. The last element of
552 : // keys is skipped because the invalid key should always be last.
553 0 : std::string keys_string = "{";
554 0 : for (unsigned int i = 0; i < keys.size() - 1; ++i)
555 : {
556 0 : if (i != 0)
557 : keys_string += ",";
558 0 : keys_string += "'" + keys[i] + "'";
559 : }
560 : keys_string += "}";
561 :
562 0 : logError("The parameter '" + param + "' was given an invalid value ('" +
563 0 : std::string(moose_enum) + "'). Valid values (case-insensitive) are " + keys_string);
564 0 : }
565 :
566 8680 : return value;
567 : }
568 :
569 : template <typename T>
570 : void
571 32999 : Component::insistParameterExists(const std::string & function_name,
572 : const std::string & param_name) const
573 : {
574 32999 : if (!hasParam<T>(param_name))
575 0 : mooseError(name(),
576 : ": Calling ",
577 : function_name,
578 : " failed, parameter '",
579 : param_name,
580 : "' does not exist or does not have the type you requested. Double check your "
581 : "spelling and/or type of the parameter.");
582 32999 : }
583 :
584 : template <typename T>
585 : void
586 474 : Component::checkComponentOfTypeExists(const std::string & param) const
587 : {
588 948 : insistParameterExists<std::string>(__FUNCTION__, param);
589 :
590 : const std::string & comp_name = getParam<std::string>(param);
591 474 : checkComponentOfTypeExistsByName<T>(comp_name);
592 474 : }
593 :
594 : template <typename T>
595 : void
596 27204 : Component::checkComponentOfTypeExistsByName(const std::string & comp_name) const
597 : {
598 27204 : if (!_sim.hasComponentOfType<T>(comp_name))
599 : {
600 36 : if (_sim.hasComponent(comp_name))
601 36 : logError("The component '", comp_name, "' is not of type '", demangle(typeid(T).name()), "'");
602 : else
603 18 : logError("The component '", comp_name, "' does not exist");
604 : }
605 27204 : }
606 :
607 : template <typename T>
608 : void
609 : Component::checkParameterValueLessThan(const std::string & param, const T & value_max) const
610 : {
611 : insistParameterExists<T>(__FUNCTION__, param);
612 :
613 : const auto & value = getParam<T>(param);
614 : if (value >= value_max)
615 : logError("The value of parameter '", param, "' (", value, ") must be less than ", value_max);
616 : }
617 :
618 : template <typename T>
619 : void
620 : Component::checkSizeLessThan(const std::string & param, const unsigned int & n_entries) const
621 : {
622 : insistParameterExists<std::vector<T>>(__FUNCTION__, param);
623 :
624 : const auto & value = getParam<std::vector<T>>(param);
625 : if (value.size() >= n_entries)
626 : logError("The number of entries in the parameter '",
627 : param,
628 : "' (",
629 : value.size(),
630 : ") must be less than ",
631 : n_entries);
632 : }
633 :
634 : template <typename T>
635 : void
636 6343 : Component::checkSizeGreaterThan(const std::string & param, const unsigned int & n_entries) const
637 : {
638 12686 : insistParameterExists<std::vector<T>>(__FUNCTION__, param);
639 :
640 : const auto & value = getParam<std::vector<T>>(param);
641 6343 : if (value.size() <= n_entries)
642 0 : logError("The number of entries in the parameter '",
643 : param,
644 : "' (",
645 0 : value.size(),
646 : ") must be greater than ",
647 : n_entries);
648 6343 : }
649 :
650 : template <typename T1, typename T2>
651 : void
652 12891 : Component::checkEqualSize(const std::string & param1, const std::string & param2) const
653 : {
654 12891 : insistParameterExists<std::vector<T1>>(__FUNCTION__, param1);
655 25782 : insistParameterExists<std::vector<T2>>(__FUNCTION__, param2);
656 :
657 : const auto & value1 = getParam<std::vector<T1>>(param1);
658 : const auto & value2 = getParam<std::vector<T2>>(param2);
659 12891 : if (value1.size() != value2.size())
660 12 : logError("The number of entries in parameter '",
661 : param1,
662 : "' (",
663 24 : value1.size(),
664 : ") must equal the number of entries of parameter '",
665 : param2,
666 : "' (",
667 12 : value2.size(),
668 : ")");
669 12891 : }
670 :
671 : template <typename T>
672 : void
673 400 : Component::checkSizeEqualsValue(const std::string & param, const unsigned int & n_entries) const
674 : {
675 800 : insistParameterExists<std::vector<T>>(__FUNCTION__, param);
676 :
677 : const auto & param_value = getParam<std::vector<T>>(param);
678 400 : if (param_value.size() != n_entries)
679 0 : logError("The number of entries in parameter '",
680 : param,
681 : "' (",
682 0 : param_value.size(),
683 : ") must be equal to ",
684 : n_entries);
685 400 : }
686 :
687 : template <typename T>
688 : void
689 : Component::checkSizeEqualsValue(const std::string & param,
690 : const unsigned int & n_entries,
691 : const std::string & description) const
692 : {
693 : insistParameterExists<std::vector<T>>(__FUNCTION__, param);
694 :
695 : const auto & param_value = getParam<std::vector<T>>(param);
696 : if (param_value.size() != n_entries)
697 : logError("The number of entries in parameter '",
698 : param,
699 : "' (",
700 : param_value.size(),
701 : ") must be equal to ",
702 : description,
703 : " (",
704 : n_entries,
705 : ")");
706 : }
707 :
708 : template <typename T1, typename T2>
709 : void
710 : Component::checkSizeEqualsParameterValue(const std::string & param1,
711 : const std::string & param2) const
712 : {
713 : insistParameterExists<std::vector<T1>>(__FUNCTION__, param1);
714 : insistParameterExists<T2>(__FUNCTION__, param2);
715 :
716 : const auto & value1 = getParam<std::vector<T1>>(param1);
717 : const auto & value2 = getParam<T2>(param2);
718 : if (value1.size() != value2)
719 : logError("The number of entries in parameter '",
720 : param1,
721 : "' (",
722 : value1.size(),
723 : ") must be equal to the value of parameter '",
724 : param2,
725 : "' (",
726 : value2,
727 : ")");
728 : }
|