LCOV - code coverage report
Current view: top level - src/base - Factory.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 133 157 84.7 %
Date: 2025-07-17 01:28:37 Functions: 16 19 84.2 %
Legend: Lines: hit not hit

          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             : #include "Factory.h"
      11             : #include "Registry.h"
      12             : #include "InfixIterator.h"
      13             : #include "InputParameterWarehouse.h"
      14             : #include "FEProblemBase.h"
      15             : // Just for testing...
      16             : #include "Diffusion.h"
      17             : 
      18       62755 : Factory::Factory(MooseApp & app) : _app(app) {}
      19             : 
      20       57254 : Factory::~Factory() {}
      21             : 
      22             : void
      23    93588376 : Factory::reg(std::shared_ptr<RegistryEntryBase> obj)
      24             : {
      25    93588376 :   const std::string obj_name = obj->name();
      26    93588376 :   const std::string & label = obj->_label;
      27    93588376 :   const std::string & deprecated_time = obj->_deprecated_time;
      28    93588376 :   const std::string & replacement_name = obj->_replaced_by;
      29    93588376 :   const std::string & file = obj->_file;
      30    93588376 :   const int line = obj->_line;
      31             : 
      32             :   // do nothing if we have already added this exact object before
      33    93588376 :   auto key = std::make_pair(label, obj_name);
      34    93588376 :   if (_objects_by_label.find(key) != _objects_by_label.end())
      35           3 :     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    93588885 :   if (_registerable_objects.empty() ||
      47    93588885 :       _registerable_objects.find(obj_name) != _registerable_objects.end())
      48             :   {
      49    93587864 :     if (_name_to_object.find(obj_name) != _name_to_object.end())
      50           0 :       mooseError("Object '" + obj_name + "' registered from multiple files: ",
      51             :                  file,
      52             :                  " and ",
      53           0 :                  _name_to_line.getInfo(obj_name).file());
      54    93587864 :     _name_to_object[obj_name] = obj;
      55    93587864 :     _objects_by_label.insert(key);
      56             :   }
      57    93588373 :   _name_to_line.addInfo(obj_name, file, line);
      58             : 
      59    93588373 :   if (!replacement_name.empty())
      60     3263072 :     _deprecated_name[obj_name] = replacement_name;
      61    93588373 :   if (!deprecated_time.empty())
      62     3701965 :     _deprecated_time[obj_name] = parseTime(deprecated_time);
      63             : 
      64             :   // TODO: Possibly store and print information about objects that are skipped here?
      65    93588379 : }
      66             : 
      67             : InputParameters
      68     4022060 : Factory::getValidParams(const std::string & obj_name) const
      69             : {
      70     4022060 :   const auto it = _name_to_object.find(obj_name);
      71             : 
      72             :   // Check if the object is registered
      73     4022060 :   if (it == _name_to_object.end())
      74          19 :     reportUnregisteredError(obj_name);
      75             : 
      76             :   // Print out deprecated message, if it exists
      77     4022041 :   deprecatedMessage(obj_name);
      78             : 
      79             :   // Return the parameters
      80     4022037 :   auto params = it->second->buildParameters();
      81     4022037 :   params.addPrivateParam("_moose_app", &_app);
      82             : 
      83     8044074 :   return params;
      84           0 : }
      85             : 
      86             : std::unique_ptr<MooseObject>
      87     1938910 : 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     1938910 :   if (print_deprecated)
      94           0 :     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     1938910 :   auto & warehouse_params = initialize(obj_name, name, parameters, tid);
      99             : 
     100             :   // call the function pointer to build the object
     101     1938840 :   _currently_constructing.push_back(&warehouse_params);
     102     1938840 :   auto obj = _name_to_object.at(obj_name)->build(warehouse_params);
     103     1937116 :   _currently_constructing.pop_back();
     104             : 
     105     1937116 :   finalize(obj_name, *obj);
     106             : 
     107     1937116 :   return obj;
     108           0 : }
     109             : 
     110             : std::shared_ptr<MooseObject>
     111           0 : 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           0 :       createUnique(obj_name, name, parameters, tid, print_deprecated);
     119             : 
     120           0 :   if (auto fep = std::dynamic_pointer_cast<FEProblemBase>(object))
     121           0 :     _app.actionWarehouse().problemBase() = fep;
     122             : 
     123           0 :   return object;
     124             : }
     125             : 
     126             : void
     127      451897 : Factory::releaseSharedObjects(const MooseObject & moose_object, THREAD_ID tid)
     128             : {
     129      451897 :   _app.getInputParameterWarehouse().removeInputParameters(moose_object, tid, {});
     130      451897 : }
     131             : 
     132             : void
     133           2 : Factory::restrictRegisterableObjects(const std::vector<std::string> & names)
     134             : {
     135           2 :   _registerable_objects.insert(names.begin(), names.end());
     136           2 : }
     137             : 
     138             : std::time_t
     139     3701965 : Factory::parseTime(const std::string t_str)
     140             : {
     141             :   // The string must be a certain length to be valid
     142     3701965 :   if (t_str.size() != 16)
     143           0 :     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     3701965 :   time(&t_end);
     149     3701965 :   t_end_info = localtime(&t_end);
     150     3701965 :   t_end_info->tm_mon = std::atoi(t_str.substr(0, 2).c_str()) - 1;
     151     3701965 :   t_end_info->tm_mday = std::atoi(t_str.substr(3, 2).c_str());
     152     3701965 :   t_end_info->tm_year = std::atoi(t_str.substr(6, 4).c_str()) - 1900;
     153     3701965 :   t_end_info->tm_hour = std::atoi(t_str.substr(11, 2).c_str()) + 1;
     154     3701965 :   t_end_info->tm_min = std::atoi(t_str.substr(14, 2).c_str());
     155     3701965 :   t_end_info->tm_sec = 0;
     156     3701965 :   t_end = mktime(t_end_info);
     157     3701965 :   return t_end;
     158             : }
     159             : 
     160             : void
     161     5964131 : Factory::deprecatedMessage(const std::string obj_name) const
     162             : {
     163     5964131 :   const auto time_it = _deprecated_time.find(obj_name);
     164             : 
     165             :   // If the object is not deprecated return
     166     5964131 :   if (time_it == _deprecated_time.end())
     167     5962780 :     return;
     168             : 
     169             :   // If the message has already been printed, return
     170        8168 :   if (_deprecated_types.count(obj_name))
     171        6817 :     return;
     172        1351 :   _deprecated_types.emplace(obj_name);
     173             : 
     174             :   // We dont need a backtrace on this, this is user-facing
     175        1351 :   const auto current_show_trace = Moose::show_trace;
     176        1351 :   Moose::show_trace = false;
     177             : 
     178             :   // Get the current time
     179             :   std::time_t now;
     180        1351 :   time(&now);
     181             : 
     182             :   // Get the stop time
     183        1351 :   std::time_t t_end = time_it->second;
     184             : 
     185             :   // Message storage
     186        1351 :   std::ostringstream msg;
     187             : 
     188        1351 :   const auto name_it = _deprecated_name.find(obj_name);
     189             : 
     190             :   // Expired object
     191        1351 :   if (now > t_end)
     192             :   {
     193        1018 :     msg << "***** Invalid Object: " << obj_name << " *****\n";
     194        1018 :     msg << "Expired on " << ctime(&t_end);
     195             : 
     196             :     // Append replacement object, if it exists
     197        1018 :     if (name_it != _deprecated_name.end())
     198         374 :       msg << "Update your application using the '" << name_it->second << "' object";
     199             : 
     200             :     // Produce the error message
     201        1018 :     mooseDeprecationExpired(msg.str());
     202             :   }
     203             : 
     204             :   // Expiring object
     205             :   else
     206             :   {
     207             :     // Build the basic message
     208         333 :     msg << "Deprecated Object: " << obj_name << "\n";
     209         333 :     msg << "This object will be removed on " << ctime(&t_end);
     210             : 
     211             :     // Append replacement object, if it exists
     212         333 :     if (name_it != _deprecated_name.end())
     213          22 :       msg << "Replace " << obj_name << " with " << name_it->second;
     214             : 
     215             :     // Produce the error message
     216         333 :     mooseDeprecated(msg.str());
     217             :   }
     218        1347 :   Moose::show_trace = current_show_trace;
     219        1347 : }
     220             : 
     221             : void
     222          19 : Factory::reportUnregisteredError(const std::string & obj_name) const
     223             : {
     224          19 :   std::ostringstream oss;
     225          19 :   std::set<std::string> paths = _app.getLoadedLibraryPaths();
     226             : 
     227          19 :   oss << "A '" + obj_name + "' is not a registered object.\n";
     228             : 
     229          19 :   if (!paths.empty())
     230             :   {
     231             :     oss << "\nWe loaded objects from the following libraries and still couldn't find your "
     232           2 :            "object:\n\t";
     233           2 :     std::copy(paths.begin(), paths.end(), infix_ostream_iterator<std::string>(oss, "\n\t"));
     234           2 :     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          19 :          "MOOSE_LIBRARY_PATH environment variable.";
     240             : 
     241          19 :   mooseError(oss.str());
     242           0 : }
     243             : 
     244             : std::vector<std::string>
     245           0 : Factory::getConstructedObjects() const
     246             : {
     247           0 :   std::vector<std::string> list;
     248           0 :   for (const auto & name : _constructed_types)
     249           0 :     list.push_back(name);
     250           0 :   return list;
     251           0 : }
     252             : 
     253             : const InputParameters *
     254     2204805 : Factory::currentlyConstructing() const
     255             : {
     256     2204805 :   return _currently_constructing.size() ? _currently_constructing.back() : nullptr;
     257             : }
     258             : 
     259             : FileLineInfo
     260      404511 : Factory::getLineInfo(const std::string & name) const
     261             : {
     262      404511 :   return _name_to_line.getInfo(name);
     263             : }
     264             : 
     265             : void
     266     4204397 : Factory::associateNameToClass(const std::string & name, const std::string & class_name)
     267             : {
     268     4204397 :   _name_to_class[name] = class_name;
     269     4204397 : }
     270             : 
     271             : std::string
     272      404510 : Factory::associatedClassName(const std::string & name) const
     273             : {
     274      404510 :   auto it = _name_to_class.find(name);
     275      404510 :   if (it == _name_to_class.end())
     276      386618 :     return "";
     277             :   else
     278       17892 :     return it->second;
     279             : }
     280             : 
     281             : InputParameters &
     282     1942090 : 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     1942090 :   const auto it = _name_to_object.find(type);
     289             : 
     290             :   // Check if the object is registered
     291     1942090 :   if (it == _name_to_object.end())
     292           0 :     reportUnregisteredError(type);
     293             : 
     294             :   // Print out deprecated message, if it exists
     295     1942090 :   deprecatedMessage(type);
     296             : 
     297             :   // Create the actual parameters object that the object will reference
     298             :   InputParameters & params =
     299     1942090 :       _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     1942084 :   if (!params.getHitNode() || params.getHitNode()->isRoot())
     306      873883 :     if (const auto hit_node = _app.getCurrentActionHitNode())
     307      873241 :       params.setHitNode(*hit_node, {});
     308             : 
     309             :   // Set the _type parameter
     310     1942084 :   params.set<std::string>("_type") = type;
     311             : 
     312             :   // Check to make sure that all required parameters are supplied
     313     1942084 :   params.finalize(name);
     314             : 
     315             :   // register type name as constructed
     316     1942020 :   _constructed_types.insert(type);
     317             : 
     318             :   // add FEProblem pointers to object's params object
     319     1942020 :   if (_app.actionWarehouse().problemBase())
     320     1579400 :     _app.actionWarehouse().problemBase()->setInputParametersFEProblem(params);
     321             : 
     322     1942020 :   return params;
     323             : }
     324             : 
     325             : void
     326     2087895 : 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     2087895 :   InputParameters orig_params = getValidParams(type);
     332     2087895 :   const auto & object_params = object.parameters();
     333     2087895 :   if (orig_params.n_parameters() != object_params.n_parameters())
     334             :   {
     335        1674 :     std::set<std::string> orig, populated;
     336       66960 :     for (const auto & it : orig_params)
     337       65286 :       orig.emplace(it.first);
     338       61938 :     for (const auto & it : object_params)
     339       60264 :       populated.emplace(it.first);
     340             : 
     341        1674 :     std::set<std::string> diff;
     342        1674 :     std::set_difference(populated.begin(),
     343             :                         populated.end(),
     344             :                         orig.begin(),
     345             :                         orig.end(),
     346             :                         std::inserter(diff, diff.begin()));
     347             : 
     348        1674 :     if (!diff.empty())
     349             :     {
     350           0 :       std::stringstream ss;
     351           0 :       for (const auto & name : diff)
     352           0 :         ss << ", " << name;
     353           0 :       object.mooseError("Attempted to set unregistered parameter(s):\n    ", ss.str().substr(2));
     354           0 :     }
     355        1674 :   }
     356     2087895 : }

Generated by: LCOV version 1.14