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 <set>
13 : #include <vector>
14 : #include <ctime>
15 :
16 : // MOOSE includes
17 : #include "Registry.h"
18 : #include "MooseObject.h"
19 : #include "MooseTypes.h"
20 : #include "FileLineInfo.h"
21 :
22 : // Forward declarations
23 : class InputParameters;
24 :
25 : /**
26 : * Generic factory class for build all sorts of objects
27 : */
28 : class Factory
29 : {
30 : public:
31 : Factory(MooseApp & app);
32 : virtual ~Factory();
33 :
34 : void reg(std::shared_ptr<RegistryEntryBase> obj);
35 :
36 : /**
37 : * Gets file and line information where an object was initially registered.
38 : * @param name Object name
39 : * @return The FileLineInfo associated with name
40 : */
41 : FileLineInfo getLineInfo(const std::string & name) const;
42 :
43 : /**
44 : * Associates an object name with a class name.
45 : * Primarily used with the registerNamed* macros to store the
46 : * mapping between the object name and the class that implements the object.
47 : */
48 : void associateNameToClass(const std::string & name, const std::string & class_name);
49 :
50 : /**
51 : * Get the associated class name for an object name.
52 : * This will return an empty string if the name was not previously
53 : * associated with a class name via associateNameToClass()
54 : */
55 : std::string associatedClassName(const std::string & name) const;
56 :
57 : /**
58 : * Get valid parameters for the object
59 : * @param name Name of the object whose parameter we are requesting
60 : * @return Parameters of the object
61 : */
62 : InputParameters getValidParams(const std::string & name) const;
63 :
64 : /**
65 : * Build an object (must be registered) - THIS METHOD IS DEPRECATED (Use create<T>())
66 : * @param obj_name Type of the object being constructed
67 : * @param name Name for the object
68 : * @param parameters Parameters this object should have
69 : * @param tid The thread id that this copy will be created for
70 : * @param print_deprecated controls the deprecated message
71 : * @return The created object
72 : */
73 : ///@{
74 : std::unique_ptr<MooseObject> createUnique(const std::string & obj_name,
75 : const std::string & name,
76 : const InputParameters & parameters,
77 : THREAD_ID tid = 0,
78 : bool print_deprecated = true);
79 : std::shared_ptr<MooseObject> create(const std::string & obj_name,
80 : const std::string & name,
81 : const InputParameters & parameters,
82 : THREAD_ID tid = 0,
83 : bool print_deprecated = true);
84 : ///@}
85 :
86 : /**
87 : * Build an object (must be registered)
88 : * @param obj_name Type of the object being constructed
89 : * @param name Name for the object
90 : * @param parameters Parameters this object should have
91 : * @param tid The thread id that this copy will be created for
92 : * @return The created object
93 : */
94 : ///@{
95 : template <typename T>
96 : std::unique_ptr<T> createUnique(const std::string & obj_name,
97 : const std::string & name,
98 : const InputParameters & parameters,
99 : const THREAD_ID tid = 0);
100 : template <typename T>
101 : std::shared_ptr<T> create(const std::string & obj_name,
102 : const std::string & name,
103 : const InputParameters & parameters,
104 : const THREAD_ID tid = 0);
105 : ///@}
106 :
107 : /**
108 : * Clones the object \p object.
109 : *
110 : * Under the hood, this creates a copy of the InputParameters from \p object
111 : * and constructs a new object with the copied parameters. The suffix _clone<i>
112 : * will be added to the object's name, where <i> is incremented each time
113 : * the object is cloned.
114 : */
115 : template <typename T>
116 : std::unique_ptr<T> clone(const T & object);
117 :
118 : /**
119 : * Copy constructs the object \p object.
120 : *
121 : * Under the hood, the new object's parameters will point to the same address
122 : * as the parameters in \p object. This can be dangerous and thus this is only
123 : * allowed for a subset of objects.
124 : */
125 : template <typename T>
126 : std::unique_ptr<T> copyConstruct(const T & object);
127 :
128 : /**
129 : * Releases any shared resources created as a side effect of creating an object through
130 : * the Factory::create method(s). Currently, this object just moves the InputParameters object
131 : * from the InputParameterWarehouse. Normally this method does not need to be explicitly called
132 : * during a normal simulation.
133 : */
134 : void releaseSharedObjects(const MooseObject & moose_object, THREAD_ID tid = 0);
135 :
136 : /**
137 : * Calling this object with a non-empty vector will cause this factory to ignore registrations
138 : * from any object
139 : * not contained within the list.
140 : * @param names a vector containing the names of objects that this factory will register
141 : */
142 : void restrictRegisterableObjects(const std::vector<std::string> & names);
143 :
144 : /**
145 : * Returns a reference to the map from names to RegistryEntryBase pointers
146 : */
147 14264 : const auto & registeredObjects() const { return _name_to_object; }
148 :
149 : /**
150 : * Returns a Boolean indicating whether an object type has been registered
151 : */
152 1152 : bool isRegistered(const std::string & obj_name) const { return _name_to_object.count(obj_name); }
153 :
154 : /**
155 : * Get a list of all constructed Moose Object types
156 : */
157 : std::vector<std::string> getConstructedObjects() const;
158 :
159 : MooseApp & app() { return _app; }
160 :
161 : /**
162 : * @return The InputParameters for the object that is currently being constructed,
163 : * if any.
164 : *
165 : * Can be used to ensure that all MooseObjects are created using the Factory
166 : */
167 : const InputParameters * currentlyConstructing() const;
168 :
169 : private:
170 : /**
171 : * Parse time string (mm/dd/yyyy HH:MM)
172 : * @param t_str String with the object expiration date, this must be in the form mm/dd/yyyy
173 : * HH:MM
174 : * @return A time_t object with the expiration date
175 : */
176 : std::time_t parseTime(std::string);
177 :
178 : /**
179 : * Show the appropriate message for deprecated objects
180 : * @param obj_name Name of the deprecated object
181 : */
182 : void deprecatedMessage(const std::string obj_name) const;
183 :
184 : /**
185 : * Prints error information when an object is not registered
186 : */
187 : void reportUnregisteredError(const std::string & obj_name) const;
188 :
189 : /**
190 : * Initializes the data structures and the parameters (in the InputParameterWarehouse)
191 : * for the object with the given state.
192 : */
193 : InputParameters & initialize(const std::string & type,
194 : const std::string & name,
195 : const InputParameters & from_params,
196 : const THREAD_ID tid);
197 :
198 : /**
199 : * Finalizes the creaction of \p object of type \p type.
200 : *
201 : * This will do some sanity checking on whether or not the parameters in the
202 : * created object match the valid paramters of the associated type.
203 : */
204 : void finalize(const std::string & type, const MooseObject & object);
205 :
206 : /// Reference to the application
207 : MooseApp & _app;
208 :
209 : /// Storage for pointers to the object registry entry
210 : std::map<std::string, std::shared_ptr<RegistryEntryBase>> _name_to_object;
211 :
212 : FileLineInfoMap _name_to_line;
213 :
214 : /// Object name to class name association
215 : std::map<std::string, std::string> _name_to_class;
216 :
217 : /// Storage for deprecated object expiration dates
218 : std::map<std::string, std::time_t> _deprecated_time;
219 :
220 : /// Storage for the deprecated objects that have replacements
221 : std::map<std::string, std::string> _deprecated_name;
222 :
223 : /// The list of objects that may be registered
224 : std::set<std::string> _registerable_objects;
225 :
226 : /// Constructed Moose Object types
227 : std::set<std::string> _constructed_types;
228 :
229 : /// Set of deprecated object types that have been printed
230 : mutable std::set<std::string> _deprecated_types;
231 :
232 : /// set<label/appname, objectname> used to track if an object previously added is being added
233 : /// again - which is okay/allowed, while still allowing us to detect/reject cases of duplicate
234 : /// object name registration where the label/appname is not identical.
235 : std::set<std::pair<std::string, std::string>> _objects_by_label;
236 :
237 : /// The object's parameters that are currently being constructed (if any).
238 : /// This is a vector because we create within create, thus the last entry is the
239 : /// one that is being constructed at the moment
240 : std::vector<const InputParameters *> _currently_constructing;
241 :
242 : /// Counter for keeping track of the number of times an object with a given name has
243 : /// been cloned so that we can continue to create objects with unique names
244 : std::map<const MooseObject *, unsigned int> _clone_counter;
245 : };
246 :
247 : template <typename T>
248 : std::unique_ptr<T>
249 1938910 : Factory::createUnique(const std::string & obj_name,
250 : const std::string & name,
251 : const InputParameters & parameters,
252 : const THREAD_ID tid)
253 : {
254 1938910 : auto object = createUnique(obj_name, name, parameters, tid, false);
255 1937116 : if (!dynamic_cast<T *>(object.get()))
256 4 : mooseError("We expected to create an object of type '" + libMesh::demangle(typeid(T).name()) +
257 : "'.\nInstead we received a parameters object for type '" + obj_name +
258 : "'.\nDid you call the wrong \"add\" method in your Action?");
259 :
260 3874224 : return std::unique_ptr<T>(static_cast<T *>(object.release()));
261 1937112 : }
262 :
263 : template <typename T>
264 : std::shared_ptr<T>
265 1937275 : Factory::create(const std::string & obj_name,
266 : const std::string & name,
267 : const InputParameters & parameters,
268 : const THREAD_ID tid)
269 : {
270 3872764 : return std::move(createUnique<T>(obj_name, name, parameters, tid));
271 : }
272 :
273 : template <typename T>
274 : std::unique_ptr<T>
275 3180 : Factory::clone(const T & object)
276 : {
277 : static_assert(std::is_base_of_v<MooseObject, T>, "Not a MooseObject");
278 :
279 3180 : const auto tid = object.template getParam<THREAD_ID>("_tid");
280 3180 : if (tid != 0)
281 0 : mooseError("Factory::clone(): The object ",
282 : object.typeAndName(),
283 : " is threaded but cloning does not work with threaded objects");
284 :
285 : // Clone the parameters; we can't copy construct InputParameters
286 3180 : InputParameters cloned_params = emptyInputParameters();
287 3180 : cloned_params += object.parameters();
288 3180 : if (const auto hit_node = object.parameters().getHitNode())
289 3168 : cloned_params.setHitNode(*hit_node, {});
290 :
291 : // Fill the new parameters in the warehouse
292 3180 : const auto type = static_cast<const MooseBase &>(object).type();
293 3180 : const auto clone_count = _clone_counter[&object]++;
294 3180 : const auto name = object.name() + "_clone" + std::to_string(clone_count);
295 3180 : const auto & params = initialize(type, name, cloned_params, 0);
296 :
297 : // Construct the object
298 3180 : _currently_constructing.push_back(¶ms);
299 3180 : auto cloned_object = std::make_unique<T>(params);
300 3180 : _currently_constructing.pop_back();
301 :
302 : // Do some sanity checking
303 3180 : finalize(type, *cloned_object);
304 :
305 6360 : return cloned_object;
306 3180 : }
307 :
308 : template <typename T>
309 : std::unique_ptr<T>
310 147599 : Factory::copyConstruct(const T & object)
311 : {
312 : static_assert(std::is_base_of_v<MooseObject, T>, "Not a MooseObject");
313 :
314 147599 : const auto type = static_cast<const MooseBase &>(object).type();
315 147599 : const auto base = object.parameters().getBase();
316 147599 : if (!base || (*base != "MooseMesh" && *base != "RelationshipManager"))
317 0 : mooseError("Copy construction of ", type, " objects is not supported.");
318 :
319 147599 : _currently_constructing.push_back(&object.parameters());
320 147599 : auto cloned_object = std::make_unique<T>(object);
321 147599 : _currently_constructing.pop_back();
322 :
323 147599 : finalize(type, *cloned_object);
324 :
325 295198 : return cloned_object;
326 147599 : }
|