www.mooseframework.org
Factory.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://www.mooseframework.org
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 "InfixIterator.h"
13 // Just for testing...
14 #include "Diffusion.h"
15 
16 Factory::Factory(MooseApp & app) : _app(app) {}
17 
19 
20 void
21 Factory::reg(const std::string & label,
22  const std::string & obj_name,
23  const buildPtr & build_ptr,
24  const paramsPtr & params_ptr,
25  const std::string & deprecated_time,
26  const std::string & replacement_name,
27  const std::string & file,
28  int line)
29 {
30  // do nothing if we have already added this exact object before
31  auto key = std::make_pair(label, obj_name);
32  if (_objects_by_label.find(key) != _objects_by_label.end())
33  return;
34 
35  /*
36  * If _registerable_objects has been set the user has requested that we only register some
37  * subset
38  * of the objects for a dynamically loaded application. The objects listed in *this*
39  * application's
40  * registerObjects() method will have already been registered before that member was set.
41  *
42  * If _registerable_objects is empty, the factory is unrestricted
43  */
44  if (_registerable_objects.empty() ||
45  _registerable_objects.find(obj_name) != _registerable_objects.end())
46  {
47  if (_name_to_build_pointer.find(obj_name) != _name_to_build_pointer.end())
48  mooseError("Object '" + obj_name + "' registered from multiple files: ",
49  file,
50  " and ",
51  _name_to_line.getInfo(obj_name).file());
52  _name_to_build_pointer[obj_name] = build_ptr;
53  _name_to_params_pointer[obj_name] = params_ptr;
54  _objects_by_label.insert(key);
55  }
56  _name_to_line.addInfo(obj_name, file, line);
57 
58  if (!replacement_name.empty())
59  _deprecated_name[obj_name] = replacement_name;
60  if (!deprecated_time.empty())
61  _deprecated_time[obj_name] = parseTime(deprecated_time);
62 
63  // TODO: Possibly store and print information about objects that are skipped here?
64 }
65 
67 Factory::getValidParams(const std::string & obj_name)
68 {
69  std::map<std::string, paramsPtr>::iterator it = _name_to_params_pointer.find(obj_name);
70 
71  // Check if the object is registered
72  if (it == _name_to_params_pointer.end())
73  reportUnregisteredError(obj_name);
74 
75  // Print out deprecated message, if it exists
76  deprecatedMessage(obj_name);
77 
78  // Return the parameters
79  paramsPtr & func = it->second;
80  InputParameters params = (*func)();
81  params.addPrivateParam("_moose_app", &_app);
82 
83  return params;
84 }
85 
87 Factory::create(const std::string & obj_name,
88  const std::string & name,
89  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  // Pointer to the object constructor
97  std::map<std::string, buildPtr>::iterator it = _name_to_build_pointer.find(obj_name);
98 
99  // Check if the object is registered
100  if (it == _name_to_build_pointer.end())
101  reportUnregisteredError(obj_name);
102 
103  // Print out deprecated message, if it exists
104  deprecatedMessage(obj_name);
105 
106  // Create the actual parameters object that the object will reference
107  InputParameters & params =
108  _app.getInputParameterWarehouse().addInputParameters(name, parameters, tid);
109 
110  // Set the _type parameter
111  params.set<std::string>("_type") = obj_name;
112 
113  // Check to make sure that all required parameters are supplied
114  params.checkParams(name);
115 
116  // register type name as constructed
117  _constructed_types.insert(obj_name);
118 
119  // add FEProblem pointers to object's params object
121  _app.actionWarehouse().problemBase()->setInputParametersFEProblem(params);
122 
123  // call the function pointer to build the object
124  buildPtr & func = it->second;
125  auto obj = (*func)(params);
126 
127  auto fep = std::dynamic_pointer_cast<FEProblemBase>(obj);
128  if (fep)
129  _app.actionWarehouse().problemBase() = fep;
130 
131  // Make sure no unexpected parameters were added by the object's constructor or by the action
132  // initiating this create call. All parameters modified by the constructor must have already
133  // been specified in the object's validParams function.
134  InputParameters orig_params = getValidParams(obj_name);
135  if (orig_params.n_parameters() != parameters.n_parameters())
136  {
137  std::set<std::string> orig, populated;
138  for (const auto & it : orig_params)
139  orig.emplace(it.first);
140  for (const auto & it : parameters)
141  populated.emplace(it.first);
142 
143  std::set<std::string> diff;
144  std::set_difference(populated.begin(),
145  populated.end(),
146  orig.begin(),
147  orig.end(),
148  std::inserter(diff, diff.begin()));
149 
150  if (!diff.empty())
151  {
152  std::stringstream ss;
153  for (const auto & name : diff)
154  ss << ", " << name;
155  mooseError("attempted to set unregistered parameter(s) for ",
156  obj_name,
157  " object:\n ",
158  ss.str().substr(2));
159  }
160  }
161 
162  return obj;
163 }
164 
165 void
167 {
169 }
170 
171 void
172 Factory::restrictRegisterableObjects(const std::vector<std::string> & names)
173 {
174  _registerable_objects.insert(names.begin(), names.end());
175 }
176 
177 std::time_t
178 Factory::parseTime(const std::string t_str)
179 {
180  // The string must be a certain length to be valid
181  if (t_str.size() != 16)
182  mooseError("The deprecated time not formatted correctly; it must be given as mm/dd/yyyy HH:MM");
183 
184  // Store the time, the time must be specified as: mm/dd/yyyy HH:MM
185  std::time_t t_end;
186  struct tm * t_end_info;
187  time(&t_end);
188  t_end_info = localtime(&t_end);
189  t_end_info->tm_mon = std::atoi(t_str.substr(0, 2).c_str()) - 1;
190  t_end_info->tm_mday = std::atoi(t_str.substr(3, 2).c_str());
191  t_end_info->tm_year = std::atoi(t_str.substr(6, 4).c_str()) - 1900;
192  t_end_info->tm_hour = std::atoi(t_str.substr(11, 2).c_str()) + 1;
193  t_end_info->tm_min = std::atoi(t_str.substr(14, 2).c_str());
194  t_end_info->tm_sec = 0;
195  t_end = mktime(t_end_info);
196  return t_end;
197 }
198 
199 void
200 Factory::deprecatedMessage(const std::string obj_name)
201 {
202  std::map<std::string, std::time_t>::iterator time_it = _deprecated_time.find(obj_name);
203 
204  // If the object is not deprecated return
205  if (time_it == _deprecated_time.end())
206  return;
207 
208  // Get the current time
209  std::time_t now;
210  time(&now);
211 
212  // Get the stop time
213  std::time_t t_end = time_it->second;
214 
215  // Message storage
216  std::ostringstream msg;
217 
218  std::map<std::string, std::string>::iterator name_it = _deprecated_name.find(obj_name);
219 
220  // Expired object
221  if (now > t_end)
222  {
223  msg << "***** Invalid Object: " << obj_name << " *****\n";
224  msg << "Expired on " << ctime(&t_end);
225 
226  // Append replacement object, if it exsits
227  if (name_it != _deprecated_name.end())
228  msg << "Update your application using the '" << name_it->second << "' object";
229 
230  // Produce the error message
231  mooseDeprecationExpired(msg.str());
232  }
233 
234  // Expiring object
235  else
236  {
237  // Build the basic message
238  msg << "Deprecated Object: " << obj_name << "\n";
239  msg << "This object will be removed on " << ctime(&t_end);
240 
241  // Append replacement object, if it exsits
242  if (name_it != _deprecated_name.end())
243  msg << "Replace " << obj_name << " with " << name_it->second;
244 
245  // Produce the error message
246  mooseDeprecated(msg.str());
247  }
248 }
249 
250 void
251 Factory::reportUnregisteredError(const std::string & obj_name) const
252 {
253  // Make sure that we don't have an improperly registered object first
255 
256  std::ostringstream oss;
257  std::set<std::string> paths = _app.getLoadedLibraryPaths();
258 
259  oss << "A '" + obj_name + "' is not a registered object.\n";
260 
261  if (!paths.empty())
262  {
263  oss << "\nWe loaded objects from the following libraries and still couldn't find your "
264  "object:\n\t";
265  std::copy(paths.begin(), paths.end(), infix_ostream_iterator<std::string>(oss, "\n\t"));
266  oss << '\n';
267  }
268 
269  oss << "\nIf you are trying to find this object in a dynamically linked library, make sure that\n"
270  "the library can be found either in your \"Problem/library_path\" parameter or in the\n"
271  "MOOSE_LIBRARY_PATH environment variable.";
272 
273  mooseError(oss.str());
274 }
275 
276 std::vector<std::string>
278 {
279  std::vector<std::string> list;
280  for (const auto & name : _constructed_types)
281  list.push_back(name);
282  return list;
283 }
284 
286 Factory::getLineInfo(const std::string & name) const
287 {
288  return _name_to_line.getInfo(name);
289 }
290 
291 void
292 Factory::associateNameToClass(const std::string & name, const std::string & class_name)
293 {
294  _name_to_class[name] = class_name;
295 }
296 
297 std::string
298 Factory::associatedClassName(const std::string & name) const
299 {
300  auto it = _name_to_class.find(name);
301  if (it == _name_to_class.end())
302  return "";
303  else
304  return it->second;
305 }
306 
307 void
309 {
310  _app.addExecFlag(flag);
311 }
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:404
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:172
void reportUnregisteredError(const std::string &obj_name) const
Prints error information when an object is not registered.
Definition: Factory.C:251
std::shared_ptr< MooseObject > create(const std::string &obj_name, const std::string &name, 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
MooseApp & _app
Reference to the application.
Definition: Factory.h:373
Factory(MooseApp &app)
Definition: Factory.C:16
void addPrivateParam(const std::string &name, const T &value)
These method add a parameter to the InputParameters object which can be retrieved like any other para...
std::time_t parseTime(std::string)
Parse time string (mm/dd/yyyy HH:MM)
Definition: Factory.C:178
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:207
InputParameters getValidParams(const std::string &name)
Get valid parameters for the object.
Definition: Factory.C:67
InputParameterWarehouse & getInputParameterWarehouse()
Get the InputParameterWarehouse for MooseObjects.
Definition: MooseApp.C:1341
std::string associatedClassName(const std::string &name) const
Get the associated class name for an object name.
Definition: Factory.C:298
FileLineInfoMap _name_to_line
Definition: Factory.h:381
virtual ~Factory()
Definition: Factory.C:18
T & set(const std::string &name, bool quiet_mode=false)
Returns a writable reference to the named parameters.
void mooseDeprecationExpired(Args &&... args)
Emit a deprecated code/feature message with the given stringified, concatenated args.
Definition: MooseError.h:244
Base class for MOOSE-based applications.
Definition: MooseApp.h:59
void regExecFlag(const ExecFlagType &flag)
Add a new flag to the app.
Definition: Factory.C:308
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
std::unique_ptr< T_DEST, T_DELETER > dynamic_pointer_cast(std::unique_ptr< T_SRC, T_DELETER > &src)
These are reworked from https://stackoverflow.com/a/11003103.
MooseObjectPtr(*)(const InputParameters &parameters) buildPtr
alias for method to build objects
Definition: Factory.h:133
FileLineInfo getInfo(const std::string &key0) const
Get file/line info for a key.
Definition: FileLineInfo.C:76
Specialization of SubProblem for solving nonlinear equations plus auxiliary equations.
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:286
std::shared_ptr< FEProblemBase > & problemBase()
std::map< std::string, std::time_t > _deprecated_time
Storage for deprecated object experiation dates.
Definition: Factory.h:387
void associateNameToClass(const std::string &name, const std::string &class_name)
Associates an object name with a class name.
Definition: Factory.C:292
std::set< std::string > _registerable_objects
The list of objects that may be registered.
Definition: Factory.h:393
Every object that can be built by the factory should be derived from this class.
Definition: MooseObject.h:42
void deprecatedMessage(const std::string obj_name)
Show the appropriate message for deprecated objects.
Definition: Factory.C:200
ActionWarehouse & actionWarehouse()
Definition: MooseApp.h:146
void mooseDeprecated(Args &&... args)
Emit a deprecated code/feature message with the given stringified, concatenated args.
Definition: MooseError.h:236
void reg(const std::string &obj_name, const std::string &file="", int line=-1)
Register a new object.
Definition: Factory.h:164
void checkParams(const std::string &parsing_syntax)
This function checks parameters stored in the object to make sure they are in the correct state as th...
InputParameters & addInputParameters(const std::string &name, InputParameters parameters, THREAD_ID tid=0)
Method for adding a new InputParameters object.
std::map< std::string, std::string > _deprecated_name
Storage for the deprecated objects that have replacements.
Definition: Factory.h:390
Holds file and line information.
Definition: FileLineInfo.h:18
std::map< std::string, paramsPtr > _name_to_params_pointer
Storage for pointers to the parameters objects.
Definition: Factory.h:379
std::map< std::string, std::string > _name_to_class
Object name to class name association.
Definition: Factory.h:384
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:166
void removeInputParameters(const MooseObject &moose_object, THREAD_ID tid=0)
Allows for the deletion and cleanup of an object while the simulation is running. ...
Class for containing MooseEnum item information.
Definition: MooseEnumItem.h:21
std::string file() const
Definition: FileLineInfo.C:29
std::vector< std::string > getConstructedObjects() const
Get a list of all constructed Moose Object types.
Definition: Factory.C:277
std::set< std::string > _constructed_types
Constructed Moose Object types.
Definition: Factory.h:399
void addExecFlag(const ExecFlagType &flag)
WARNING: This is an internal method for MOOSE, if you need the add new ExecFlagTypes then use the reg...
Definition: MooseApp.C:1661
std::map< std::string, buildPtr > _name_to_build_pointer
Storage for pointers to the object.
Definition: Factory.h:376
virtual void checkRegistryLabels()
Definition: MooseApp.C:409
std::shared_ptr< MooseObject > MooseObjectPtr
alias to wrap shared pointer type
Definition: Factory.h:123
InputParameters(*)() paramsPtr
alias for validParams function
Definition: AppFactory.h:32
unsigned int THREAD_ID
Definition: MooseTypes.h:161
std::set< std::string > getLoadedLibraryPaths() const
Return the loaded library filenames in a std::vector.
Definition: MooseApp.C:1330