https://mooseframework.inl.gov
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 
18 Factory::Factory(MooseApp & app) : _app(app) {}
19 
21 
22 void
23 Factory::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 
68 Factory::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())
74  reportUnregisteredError(obj_name);
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("_moose_app", &_app);
82 
83  return params;
84 }
85 
86 std::unique_ptr<MooseObject>
87 Factory::createUnique(const std::string & obj_name,
88  const std::string & name,
89  const InputParameters & parameters,
90  THREAD_ID tid /* =0 */,
91  bool print_deprecated /* =true */)
92 {
93  if (print_deprecated)
94  mooseDeprecated("Factory::create() is deprecated, please use Factory::create<T>() instead");
95 
96  // Build the parameters that are stored in the InputParameterWarehouse for this
97  // object, set a few other things and do a little error checking
98  auto & warehouse_params = initialize(obj_name, name, parameters, tid);
99 
100  // call the function pointer to build the object
101  _currently_constructing.push_back(&warehouse_params);
102  auto obj = _name_to_object.at(obj_name)->build(warehouse_params);
103  _currently_constructing.pop_back();
104 
105  finalize(obj_name, *obj);
106 
107  return obj;
108 }
109 
110 std::shared_ptr<MooseObject>
111 Factory::create(const std::string & obj_name,
112  const std::string & name,
113  const InputParameters & parameters,
114  THREAD_ID tid /* =0 */,
115  bool print_deprecated /* =true */)
116 {
117  std::shared_ptr<MooseObject> object =
118  createUnique(obj_name, name, parameters, tid, print_deprecated);
119 
120  if (auto fep = std::dynamic_pointer_cast<FEProblemBase>(object))
121  _app.actionWarehouse().problemBase() = fep;
122 
123  return object;
124 }
125 
126 void
128 {
129  _app.getInputParameterWarehouse().removeInputParameters(moose_object, tid, {});
130 }
131 
132 void
133 Factory::restrictRegisterableObjects(const std::vector<std::string> & names)
134 {
135  _registerable_objects.insert(names.begin(), names.end());
136 }
137 
138 std::time_t
139 Factory::parseTime(const std::string t_str)
140 {
141  // The string must be a certain length to be valid
142  if (t_str.size() != 16)
143  mooseError("The deprecated time not formatted correctly; it must be given as mm/dd/yyyy HH:MM");
144 
145  // Store the time, the time must be specified as: mm/dd/yyyy HH:MM
146  std::time_t t_end;
147  struct tm * t_end_info;
148  time(&t_end);
149  t_end_info = localtime(&t_end);
150  t_end_info->tm_mon = std::atoi(t_str.substr(0, 2).c_str()) - 1;
151  t_end_info->tm_mday = std::atoi(t_str.substr(3, 2).c_str());
152  t_end_info->tm_year = std::atoi(t_str.substr(6, 4).c_str()) - 1900;
153  t_end_info->tm_hour = std::atoi(t_str.substr(11, 2).c_str()) + 1;
154  t_end_info->tm_min = std::atoi(t_str.substr(14, 2).c_str());
155  t_end_info->tm_sec = 0;
156  t_end = mktime(t_end_info);
157  return t_end;
158 }
159 
160 void
161 Factory::deprecatedMessage(const std::string obj_name) const
162 {
163  const auto time_it = _deprecated_time.find(obj_name);
164 
165  // If the object is not deprecated return
166  if (time_it == _deprecated_time.end())
167  return;
168 
169  // If the message has already been printed, return
170  if (_deprecated_types.count(obj_name))
171  return;
172  _deprecated_types.emplace(obj_name);
173 
174  // We dont need a backtrace on this, this is user-facing
175  const auto current_show_trace = Moose::show_trace;
176  Moose::show_trace = false;
177 
178  // Get the current time
179  std::time_t now;
180  time(&now);
181 
182  // Get the stop time
183  std::time_t t_end = time_it->second;
184 
185  // Message storage
186  std::ostringstream msg;
187 
188  const auto name_it = _deprecated_name.find(obj_name);
189 
190  // Expired object
191  if (now > t_end)
192  {
193  msg << "***** Invalid Object: " << obj_name << " *****\n";
194  msg << "Expired on " << ctime(&t_end);
195 
196  // Append replacement object, if it exists
197  if (name_it != _deprecated_name.end())
198  msg << "Update your application using the '" << name_it->second << "' object";
199 
200  // Produce the error message
201  mooseDeprecationExpired(msg.str());
202  }
203 
204  // Expiring object
205  else
206  {
207  // Build the basic message
208  msg << "Deprecated Object: " << obj_name << "\n";
209  msg << "This object will be removed on " << ctime(&t_end);
210 
211  // Append replacement object, if it exists
212  if (name_it != _deprecated_name.end())
213  msg << "Replace " << obj_name << " with " << name_it->second;
214 
215  // Produce the error message
216  mooseDeprecated(msg.str());
217  }
218  Moose::show_trace = current_show_trace;
219 }
220 
221 void
222 Factory::reportUnregisteredError(const std::string & obj_name) const
223 {
224  std::ostringstream oss;
225  std::set<std::string> paths = _app.getLoadedLibraryPaths();
226 
227  oss << "A '" + obj_name + "' is not a registered object.\n";
228 
229  if (!paths.empty())
230  {
231  oss << "\nWe loaded objects from the following libraries and still couldn't find your "
232  "object:\n\t";
233  std::copy(paths.begin(), paths.end(), infix_ostream_iterator<std::string>(oss, "\n\t"));
234  oss << '\n';
235  }
236 
237  oss << "\nIf you are trying to find this object in a dynamically loaded library, make sure that\n"
238  "the library can be found either in your \"Problem/library_path\" parameter or in the\n"
239  "MOOSE_LIBRARY_PATH environment variable.";
240 
241  mooseError(oss.str());
242 }
243 
244 std::vector<std::string>
246 {
247  std::vector<std::string> list;
248  for (const auto & name : _constructed_types)
249  list.push_back(name);
250  return list;
251 }
252 
253 const InputParameters *
255 {
256  return _currently_constructing.size() ? _currently_constructing.back() : nullptr;
257 }
258 
260 Factory::getLineInfo(const std::string & name) const
261 {
262  return _name_to_line.getInfo(name);
263 }
264 
265 void
266 Factory::associateNameToClass(const std::string & name, const std::string & class_name)
267 {
268  _name_to_class[name] = class_name;
269 }
270 
271 std::string
272 Factory::associatedClassName(const std::string & name) const
273 {
274  auto it = _name_to_class.find(name);
275  if (it == _name_to_class.end())
276  return "";
277  else
278  return it->second;
279 }
280 
282 Factory::initialize(const std::string & type,
283  const std::string & name,
284  const InputParameters & from_params,
285  const THREAD_ID tid)
286 {
287  // Pointer to the object constructor
288  const auto it = _name_to_object.find(type);
289 
290  // Check if the object is registered
291  if (it == _name_to_object.end())
293 
294  // Print out deprecated message, if it exists
295  deprecatedMessage(type);
296 
297  // Create the actual parameters object that the object will reference
298  InputParameters & params =
299  _app.getInputParameterWarehouse().addInputParameters(name, from_params, tid, {});
300 
301  // Add the hit node from the action if it isn't set already (it might be set
302  // already because someone had a better option than just the action)
303  // If it isn't set, it typically means that this object was created by a
304  // non-MooseObjectAction Action
305  if (!params.getHitNode() || params.getHitNode()->isRoot())
306  if (const auto hit_node = _app.getCurrentActionHitNode())
307  params.setHitNode(*hit_node, {});
308 
309  // Set the _type parameter
310  params.set<std::string>("_type") = type;
311 
312  // Check to make sure that all required parameters are supplied
313  params.finalize(name);
314 
315  // register type name as constructed
316  _constructed_types.insert(type);
317 
318  // add FEProblem pointers to object's params object
320  _app.actionWarehouse().problemBase()->setInputParametersFEProblem(params);
321 
322  return params;
323 }
324 
325 void
326 Factory::finalize(const std::string & type, const MooseObject & object)
327 {
328  // Make sure no unexpected parameters were added by the object's constructor or by the action
329  // initiating this create call. All parameters modified by the constructor must have already
330  // been specified in the object's validParams function.
331  InputParameters orig_params = getValidParams(type);
332  const auto & object_params = object.parameters();
333  if (orig_params.n_parameters() != object_params.n_parameters())
334  {
335  std::set<std::string> orig, populated;
336  for (const auto & it : orig_params)
337  orig.emplace(it.first);
338  for (const auto & it : object_params)
339  populated.emplace(it.first);
340 
341  std::set<std::string> diff;
342  std::set_difference(populated.begin(),
343  populated.end(),
344  orig.begin(),
345  orig.end(),
346  std::inserter(diff, diff.begin()));
347 
348  if (!diff.empty())
349  {
350  std::stringstream ss;
351  for (const auto & name : diff)
352  ss << ", " << name;
353  object.mooseError("Attempted to set unregistered parameter(s):\n ", ss.str().substr(2));
354  }
355  }
356 }
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:235
std::string name(const ElemQuality q)
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:133
void reportUnregisteredError(const std::string &obj_name) const
Prints error information when an object is not registered.
Definition: Factory.C:222
bool show_trace
Set to true (the default) to print the stack trace with error and warning messages - false to omit it...
Definition: Moose.C:765
const hit::Node * getHitNode(const std::string &param) const
std::set< std::string > _deprecated_types
Set of deprecated object types that have been printed.
Definition: Factory.h:230
MooseApp & _app
Reference to the application.
Definition: Factory.h:207
Factory(MooseApp &app)
Definition: Factory.C:18
std::time_t parseTime(std::string)
Parse time string (mm/dd/yyyy HH:MM)
Definition: Factory.C:139
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:302
InputParameterWarehouse & getInputParameterWarehouse()
Get the InputParameterWarehouse for MooseObjects.
Definition: MooseApp.C:2872
std::string associatedClassName(const std::string &name) const
Get the associated class name for an object name.
Definition: Factory.C:272
FileLineInfoMap _name_to_line
Definition: Factory.h:212
InputParameters & addInputParameters(const std::string &name, const InputParameters &parameters, THREAD_ID tid, const AddRemoveParamsKey)
Method for adding a new InputParameters object.
virtual ~Factory()
Definition: Factory.C:20
T & set(const std::string &name, bool quiet_mode=false)
Returns a writable reference to the named parameters.
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:111
void mooseDeprecationExpired(Args &&... args)
Emit a deprecated code/feature message with the given stringified, concatenated args.
Definition: MooseError.h:361
InputParameters getValidParams(const std::string &name) const
Get valid parameters for the object.
Definition: Factory.C:68
Base class for MOOSE-based applications.
Definition: MooseApp.h:96
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
const hit::Node * getCurrentActionHitNode() const
Definition: MooseApp.C:3067
void finalize(const std::string &parsing_syntax)
Finalizes the parameters, which must be done before constructing any objects with these parameters (t...
FileLineInfo getInfo(const std::string &key0) const
Get file/line info for a key.
Definition: FileLineInfo.C:76
void addInfo(const std::string &key0, const std::string &file, int line)
Associate a key with file/line info.
Definition: FileLineInfo.C:35
FileLineInfo getLineInfo(const std::string &name) const
Gets file and line information where an object was initially registered.
Definition: Factory.C:260
std::shared_ptr< FEProblemBase > & problemBase()
void deprecatedMessage(const std::string obj_name) const
Show the appropriate message for deprecated objects.
Definition: Factory.C:161
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:282
std::map< std::string, std::time_t > _deprecated_time
Storage for deprecated object expiration dates.
Definition: Factory.h:218
void reg(std::shared_ptr< RegistryEntryBase > obj)
Definition: Factory.C:23
void associateNameToClass(const std::string &name, const std::string &class_name)
Associates an object name with a class name.
Definition: Factory.C:266
std::set< std::string > _registerable_objects
The list of objects that may be registered.
Definition: Factory.h:224
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. ...
Every object that can be built by the factory should be derived from this class.
Definition: MooseObject.h:28
ActionWarehouse & actionWarehouse()
Return a writable reference to the ActionWarehouse associated with this app.
Definition: MooseApp.h:237
void mooseDeprecated(Args &&... args)
Emit a deprecated code/feature message with the given stringified, concatenated args.
Definition: MooseError.h:353
std::vector< const InputParameters * > _currently_constructing
The object&#39;s parameters that are currently being constructed (if any).
Definition: Factory.h:240
std::map< std::string, std::string > _deprecated_name
Storage for the deprecated objects that have replacements.
Definition: Factory.h:221
Holds file and line information.
Definition: FileLineInfo.h:18
std::map< std::string, std::string > _name_to_class
Object name to class name association.
Definition: Factory.h:215
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:127
std::map< std::string, std::shared_ptr< RegistryEntryBase > > _name_to_object
Storage for pointers to the object registry entry.
Definition: Factory.h:210
std::string file() const
Definition: FileLineInfo.C:29
void finalize(const std::string &type, const MooseObject &object)
Finalizes the creaction of object of type type.
Definition: Factory.C:326
std::vector< std::string > getConstructedObjects() const
Get a list of all constructed Moose Object types.
Definition: Factory.C:245
std::set< std::string > _constructed_types
Constructed Moose Object types.
Definition: Factory.h:227
void setHitNode(const std::string &param, const hit::Node &node, const SetParamHitNodeKey)
Sets the hit node associated with the parameter param to node.
std::size_t n_parameters() const
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:87
const InputParameters * currentlyConstructing() const
Definition: Factory.C:254
unsigned int THREAD_ID
Definition: MooseTypes.h:209
std::set< std::string > getLoadedLibraryPaths() const
Return the paths of loaded libraries.
Definition: MooseApp.C:2835