https://mooseframework.inl.gov
Loading...
Searching...
No Matches
Factory.C
Go to the documentation of this file.
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#include "Factory.h"
11#include "Registry.h"
12#include "InfixIterator.h"
14#include "FEProblemBase.h"
15// Just for testing...
16#include "Diffusion.h"
17
18Factory::Factory(MooseApp & app) : _app(app) {}
19
21
22void
23Factory::reg(std::shared_ptr<RegistryEntryBase> obj)
24{
25 const std::string obj_name = obj->name();
26 const std::string & label = obj->_label;
27 const std::string & deprecated_time = obj->_deprecated_time;
28 const std::string & replacement_name = obj->_replaced_by;
29 const std::string & file = obj->_file;
30 const int line = obj->_line;
31
32 // do nothing if we have already added this exact object before
33 auto key = std::make_pair(label, obj_name);
34 if (_objects_by_label.find(key) != _objects_by_label.end())
35 return;
36
37 /*
38 * If _registerable_objects has been set the user has requested that we only register some
39 * subset
40 * of the objects for a dynamically loaded application. The objects listed in *this*
41 * application's
42 * registerObjects() method will have already been registered before that member was set.
43 *
44 * If _registerable_objects is empty, the factory is unrestricted
45 */
46 if (_registerable_objects.empty() ||
47 _registerable_objects.find(obj_name) != _registerable_objects.end())
48 {
49 if (_name_to_object.find(obj_name) != _name_to_object.end())
50 mooseError("Object '" + obj_name + "' registered from multiple files: ",
51 file,
52 " and ",
53 _name_to_line.getInfo(obj_name).file());
54 _name_to_object[obj_name] = obj;
55 _objects_by_label.insert(key);
56 }
57 _name_to_line.addInfo(obj_name, file, line);
58
59 if (!replacement_name.empty())
60 _deprecated_name[obj_name] = replacement_name;
61 if (!deprecated_time.empty())
62 _deprecated_time[obj_name] = parseTime(deprecated_time);
63
64 // TODO: Possibly store and print information about objects that are skipped here?
65}
66
68Factory::getValidParams(const std::string & obj_name) const
69{
70 const auto it = _name_to_object.find(obj_name);
71
72 // Check if the object is registered
73 if (it == _name_to_object.end())
75
76 // Print out deprecated message, if it exists
77 deprecatedMessage(obj_name);
78
79 // Return the parameters
80 auto params = it->second->buildParameters();
81 params.addPrivateParam(MooseBase::app_param, &_app);
82
83 return params;
84}
85
86template <class ptr_type>
87ptr_type
88Factory::createTempl(const std::string & obj_name,
89 const std::string & name,
90 const InputParameters & parameters,
91 const THREAD_ID tid,
92 const std::optional<std::string> & deprecated_method_name)
93{
94 static_assert(std::is_same_v<ptr_type, std::unique_ptr<MooseObject>> ||
95 std::is_same_v<ptr_type, std::shared_ptr<MooseObject>>,
96 "Invalid ptr_type");
97
98 if (deprecated_method_name)
99 {
100 const std::string name = "Factory::" + *deprecated_method_name;
101 mooseDeprecated(name + "() is deprecated, please use name" + "<T>() instead");
102 }
103
104 // Build the parameters that are stored in the InputParameterWarehouse for this
105 // object, set a few other things and do a little error checking
106 auto & warehouse_params = initialize(obj_name, name, parameters, tid);
107
108 // Mark that we're constructing this object
109 _currently_constructing.push_back(&warehouse_params);
110
111 // Construct the object
112 auto & registry_entry = *_name_to_object.at(obj_name);
113 ptr_type obj;
114 if constexpr (std::is_same_v<ptr_type, std::unique_ptr<MooseObject>>)
115 obj = registry_entry.build(warehouse_params);
116 else
117 obj = registry_entry.buildShared(warehouse_params);
118
119 // Done constructing the object
120 _currently_constructing.pop_back();
121
122 finalize(obj_name, *obj);
123
124 return obj;
125}
126
127std::unique_ptr<MooseObject>
128Factory::createUnique(const std::string & obj_name,
129 const std::string & name,
130 const InputParameters & parameters,
131 THREAD_ID tid /* =0 */,
132 bool print_deprecated /* =true */)
133{
134 std::optional<std::string> deprecated_method_name;
135 if (print_deprecated)
136 deprecated_method_name = "createUnique";
137 return createTempl<std::unique_ptr<MooseObject>>(
138 obj_name, name, parameters, tid, deprecated_method_name);
139}
140
141std::shared_ptr<MooseObject>
142Factory::create(const std::string & obj_name,
143 const std::string & name,
144 const InputParameters & parameters,
145 THREAD_ID tid /* =0 */,
146 bool print_deprecated /* =true */)
147{
148 std::optional<std::string> deprecated_method_name;
149 if (print_deprecated)
150 deprecated_method_name = "create";
151 return createTempl<std::shared_ptr<MooseObject>>(
152 obj_name, name, parameters, tid, deprecated_method_name);
153}
154
155void
157{
159}
160
161void
162Factory::restrictRegisterableObjects(const std::vector<std::string> & names)
163{
164 _registerable_objects.insert(names.begin(), names.end());
165}
166
167std::time_t
168Factory::parseTime(const std::string t_str)
169{
170 // The string must be a certain length to be valid
171 if (t_str.size() != 16)
172 mooseError("The deprecated time not formatted correctly; it must be given as mm/dd/yyyy HH:MM");
173
174 // Store the time, the time must be specified as: mm/dd/yyyy HH:MM
175 std::time_t t_end;
176 struct tm * t_end_info;
177 time(&t_end);
178 t_end_info = localtime(&t_end);
179 t_end_info->tm_mon = std::atoi(t_str.substr(0, 2).c_str()) - 1;
180 t_end_info->tm_mday = std::atoi(t_str.substr(3, 2).c_str());
181 t_end_info->tm_year = std::atoi(t_str.substr(6, 4).c_str()) - 1900;
182 t_end_info->tm_hour = std::atoi(t_str.substr(11, 2).c_str()) + 1;
183 t_end_info->tm_min = std::atoi(t_str.substr(14, 2).c_str());
184 t_end_info->tm_sec = 0;
185 t_end = mktime(t_end_info);
186 return t_end;
187}
188
189void
190Factory::deprecatedMessage(const std::string obj_name) const
191{
192 const auto time_it = _deprecated_time.find(obj_name);
193
194 // If the object is not deprecated return
195 if (time_it == _deprecated_time.end())
196 return;
197
198 // If the message has already been printed, return
199 if (_deprecated_types.count(obj_name))
200 return;
201 _deprecated_types.emplace(obj_name);
202
203 // Get the current time
204 std::time_t now;
205 time(&now);
206
207 // Get the stop time
208 std::time_t t_end = time_it->second;
209
210 // Message storage
211 std::ostringstream msg;
212
213 const auto name_it = _deprecated_name.find(obj_name);
214
215 // Expired object
216 if (now > t_end)
217 {
218 msg << "***** Invalid Object: " << obj_name << " *****\n";
219 msg << "Expired on " << ctime(&t_end);
220
221 // Append replacement object, if it exists
222 if (name_it != _deprecated_name.end())
223 msg << "Update your application using the '" << name_it->second << "' object";
224
225 // Produce the error message
227 }
228
229 // Expiring object
230 else
231 {
232 // Build the basic message
233 msg << "Deprecated Object: " << obj_name << "\n";
234 msg << "This object will be removed on " << ctime(&t_end);
235
236 // Append replacement object, if it exists
237 if (name_it != _deprecated_name.end())
238 msg << "Replace " << obj_name << " with " << name_it->second;
239
240 // Produce the error message
241 mooseDeprecatedNoTrace(msg.str());
242 }
243}
244
245void
246Factory::reportUnregisteredError(const std::string & obj_name) const
247{
248 std::ostringstream oss;
249 std::set<std::string> paths = _app.getLoadedLibraryPaths();
250
251 oss << "A '" + obj_name + "' is not a registered object.\n";
252
253 if (!paths.empty())
254 {
255 oss << "\nWe loaded objects from the following libraries and still couldn't find your "
256 "object:\n\t";
257 std::copy(paths.begin(), paths.end(), infix_ostream_iterator<std::string>(oss, "\n\t"));
258 oss << '\n';
259 }
260
261 oss << "\nIf you are trying to find this object in a dynamically loaded library, make sure that\n"
262 "the library can be found either in your \"Problem/library_path\" parameter or in the\n"
263 "MOOSE_LIBRARY_PATH environment variable.";
264
265 mooseError(oss.str());
266}
267
268std::vector<std::string>
270{
271 std::vector<std::string> list;
272 for (const auto & name : _constructed_types)
273 list.push_back(name);
274 return list;
275}
276
277const InputParameters *
279{
280 return _currently_constructing.size() ? _currently_constructing.back() : nullptr;
281}
282
284Factory::getLineInfo(const std::string & name) const
285{
286 return _name_to_line.getInfo(name);
287}
288
289void
290Factory::associateNameToClass(const std::string & name, const std::string & class_name)
291{
292 _name_to_class[name] = class_name;
293}
294
295std::string
296Factory::associatedClassName(const std::string & name) const
297{
298 auto it = _name_to_class.find(name);
299 if (it == _name_to_class.end())
300 return "";
301 else
302 return it->second;
303}
304
306Factory::initialize(const std::string & type,
307 const std::string & name,
308 const InputParameters & from_params,
309 const THREAD_ID tid)
310{
311 // Pointer to the object constructor
312 const auto it = _name_to_object.find(type);
313
314 // Check if the object is registered
315 if (it == _name_to_object.end())
317
318 // Print out deprecated message, if it exists
319 deprecatedMessage(type);
320
321 // Create the actual parameters object that the object will reference
322 InputParameters & params =
323 _app.getInputParameterWarehouse().addInputParameters(name, from_params, tid, {});
324
325 // Add the hit node from the action if it isn't set already (it might be set
326 // already because someone had a better option than just the action)
327 // If it isn't set, it typically means that this object was created by a
328 // non-MooseObjectAction Action
329 if (!params.getHitNode() || params.getHitNode()->isRoot())
330 if (const auto hit_node = _app.getCurrentActionHitNode())
331 params.setHitNode(*hit_node, {});
332
333 // Set the type parameter
334 params.set<std::string>(MooseBase::type_param) = type;
335
336 // Check to make sure that all required parameters are supplied
337 params.finalize(name);
338
339 // register type name as constructed
340 _constructed_types.insert(type);
341
342 // add FEProblem pointers to object's params object
344 _app.actionWarehouse().problemBase()->setInputParametersFEProblem(params);
345
346 return params;
347}
348
349void
350Factory::finalize(const std::string & type, const MooseObject & object)
351{
352 // Make sure no unexpected parameters were added by the object's constructor or by the action
353 // initiating this create call. All parameters modified by the constructor must have already
354 // been specified in the object's validParams function.
355 InputParameters orig_params = getValidParams(type);
356 const auto & object_params = object.parameters();
357 if (orig_params.n_parameters() != object_params.n_parameters())
358 {
359 std::set<std::string> orig, populated;
360 for (const auto & it : orig_params)
361 orig.emplace(it.first);
362 for (const auto & it : object_params)
363 populated.emplace(it.first);
364
365 std::set<std::string> diff;
366 std::set_difference(populated.begin(),
367 populated.end(),
368 orig.begin(),
369 orig.end(),
370 std::inserter(diff, diff.begin()));
371
372 if (!diff.empty())
373 {
374 std::stringstream ss;
375 for (const auto & name : diff)
376 ss << ", " << name;
377 object.mooseError("Attempted to set unregistered parameter(s):\n ", ss.str().substr(2));
378 }
379 }
380}
381
382// Explicit instantiation for Factory::createTempl
383template std::unique_ptr<MooseObject>
384Factory::createTempl<std::unique_ptr<MooseObject>>(const std::string &,
385 const std::string &,
386 const InputParameters &,
387 const THREAD_ID,
388 const std::optional<std::string> &);
389template std::shared_ptr<MooseObject>
390Factory::createTempl<std::shared_ptr<MooseObject>>(const std::string &,
391 const std::string &,
392 const InputParameters &,
393 const THREAD_ID,
394 const std::optional<std::string> &);
void mooseDeprecatedNoTrace(Args &&... args)
Emit a deprecated code/feature message with the given stringified, concatenated args.
Definition MooseError.h:373
void mooseDeprecationExpiredNoTrace(Args &&... args)
Emit a deprecated code/feature message with the given stringified, concatenated args.
Definition MooseError.h:392
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
Definition MooseError.h:311
void mooseDeprecated(Args &&... args)
Emit a deprecated code/feature message with the given stringified, concatenated args.
Definition MooseError.h:363
unsigned int THREAD_ID
Definition MooseTypes.h:237
std::shared_ptr< FEProblemBase > & problemBase()
std::shared_ptr< MooseObject > create(const std::string &obj_name, const std::string &name, const InputParameters &parameters, THREAD_ID tid=0, bool print_deprecated=true)
Definition Factory.C:142
void reportUnregisteredError(const std::string &obj_name) const
Prints error information when an object is not registered.
Definition Factory.C:246
std::set< std::pair< std::string, std::string > > _objects_by_label
set<label/appname, objectname> used to track if an object previously added is being added again - whi...
Definition Factory.h:275
void finalize(const std::string &type, const MooseObject &object)
Finalizes the creaction of object of type type.
Definition Factory.C:350
std::map< std::string, std::string > _deprecated_name
Storage for the deprecated objects that have replacements.
Definition Factory.h:261
std::map< std::string, std::shared_ptr< RegistryEntryBase > > _name_to_object
Storage for pointers to the object registry entry.
Definition Factory.h:250
std::set< std::string > _registerable_objects
The list of objects that may be registered.
Definition Factory.h:264
FileLineInfoMap _name_to_line
Definition Factory.h:252
void deprecatedMessage(const std::string obj_name) const
Show the appropriate message for deprecated objects.
Definition Factory.C:190
std::set< std::string > _constructed_types
Constructed Moose Object types.
Definition Factory.h:267
std::set< std::string > _deprecated_types
Set of deprecated object types that have been printed.
Definition Factory.h:270
ptr_type createTempl(const std::string &obj_name, const std::string &name, const InputParameters &parameters, const THREAD_ID tid, const std::optional< std::string > &deprecated_method_name)
Internal method for creating a MooseObject, either as a shared_ptr or as a unique_ptr.
Definition Factory.C:88
std::map< std::string, std::string > _name_to_class
Object name to class name association.
Definition Factory.h:255
std::vector< const InputParameters * > _currently_constructing
The object's parameters that are currently being constructed (if any).
Definition Factory.h:280
void restrictRegisterableObjects(const std::vector< std::string > &names)
Calling this object with a non-empty vector will cause this factory to ignore registrations from any ...
Definition Factory.C:162
virtual ~Factory()
Definition Factory.C:20
void reg(std::shared_ptr< RegistryEntryBase > obj)
Definition Factory.C:23
MooseApp & _app
Reference to the application.
Definition Factory.h:247
const InputParameters * currentlyConstructing() const
Definition Factory.C:278
InputParameters getValidParams(const std::string &name) const
Get valid parameters for the object.
Definition Factory.C:68
std::time_t parseTime(std::string)
Parse time string (mm/dd/yyyy HH:MM)
Definition Factory.C:168
std::vector< std::string > getConstructedObjects() const
Get a list of all constructed Moose Object types.
Definition Factory.C:269
std::unique_ptr< MooseObject > createUnique(const std::string &obj_name, const std::string &name, const InputParameters &parameters, THREAD_ID tid=0, bool print_deprecated=true)
Build an object (must be registered) - THIS METHOD IS DEPRECATED (Use create<T>())
Definition Factory.C:128
void associateNameToClass(const std::string &name, const std::string &class_name)
Associates an object name with a class name.
Definition Factory.C:290
std::string associatedClassName(const std::string &name) const
Get the associated class name for an object name.
Definition Factory.C:296
std::map< std::string, std::time_t > _deprecated_time
Storage for deprecated object expiration dates.
Definition Factory.h:258
FileLineInfo getLineInfo(const std::string &name) const
Gets file and line information where an object was initially registered.
Definition Factory.C:284
InputParameters & initialize(const std::string &type, const std::string &name, const InputParameters &from_params, const THREAD_ID tid)
Initializes the data structures and the parameters (in the InputParameterWarehouse) for the object wi...
Definition Factory.C:306
void releaseSharedObjects(const MooseObject &moose_object, THREAD_ID tid=0)
Releases any shared resources created as a side effect of creating an object through the Factory::cre...
Definition Factory.C:156
Factory(MooseApp &app)
Definition Factory.C:18
void addInfo(const std::string &key0, const std::string &file, int line)
Associate a key with file/line info.
FileLineInfo getInfo(const std::string &key0) const
Get file/line info for a key.
Holds file and line information.
std::string file() const
void removeInputParameters(const MooseObject &moose_object, THREAD_ID tid, const AddRemoveParamsKey)
Allows for the deletion and cleanup of an object while the simulation is running.
InputParameters & addInputParameters(const std::string &name, const InputParameters &parameters, THREAD_ID tid, const AddRemoveParamsKey)
Method for adding a new InputParameters object.
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system.
void setHitNode(const std::string &param, const hit::Node &node, const SetParamHitNodeKey)
Sets the hit node associated with the parameter param to node.
void finalize(const std::string &parsing_syntax)
Finalizes the parameters, which must be done before constructing any objects with these parameters (t...
const hit::Node * getHitNode(const std::string &param) const
T & set(const std::string &name, bool quiet_mode=false)
Returns a writable reference to the named parameters.
Base class for MOOSE-based applications.
Definition MooseApp.h:110
ActionWarehouse & actionWarehouse()
Return a writable reference to the ActionWarehouse associated with this app.
Definition MooseApp.h:217
const hit::Node * getCurrentActionHitNode() const
Definition MooseApp.C:3062
std::set< std::string > getLoadedLibraryPaths() const
Return the paths of loaded libraries.
Definition MooseApp.C:2830
InputParameterWarehouse & getInputParameterWarehouse()
Get the InputParameterWarehouse for MooseObjects.
Definition MooseApp.C:2867
static const std::string type_param
The name of the parameter that contains the object type.
Definition MooseBase.h:53
static const std::string app_param
The name of the parameter that contains the MooseApp.
Definition MooseBase.h:59
Every object that can be built by the factory should be derived from this class.
Definition MooseObject.h:31
GCC9 currently hits a "no type named 'value_type'" error during build if this is removed and iterator...
std::size_t n_parameters() const