LCOV - code coverage report
Current view: top level - src/base - Factory.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: #32971 (54bef8) with base c6cf66 Lines: 144 166 86.7 %
Date: 2026-05-29 20:35:17 Functions: 19 21 90.5 %
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       66995 : Factory::Factory(MooseApp & app) : _app(app) {}
      19             : 
      20       62876 : Factory::~Factory() {}
      21             : 
      22             : void
      23   112247459 : Factory::reg(std::shared_ptr<RegistryEntryBase> obj)
      24             : {
      25   112247459 :   const std::string obj_name = obj->name();
      26   112247459 :   const std::string & label = obj->_label;
      27   112247459 :   const std::string & deprecated_time = obj->_deprecated_time;
      28   112247459 :   const std::string & replacement_name = obj->_replaced_by;
      29   112247459 :   const std::string & file = obj->_file;
      30   112247459 :   const int line = obj->_line;
      31             : 
      32             :   // do nothing if we have already added this exact object before
      33   112247459 :   auto key = std::make_pair(label, obj_name);
      34   112247459 :   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   112247998 :   if (_registerable_objects.empty() ||
      47   112247998 :       _registerable_objects.find(obj_name) != _registerable_objects.end())
      48             :   {
      49   112246917 :     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   112246917 :     _name_to_object[obj_name] = obj;
      55   112246917 :     _objects_by_label.insert(key);
      56             :   }
      57   112247456 :   _name_to_line.addInfo(obj_name, file, line);
      58             : 
      59   112247456 :   if (!replacement_name.empty())
      60     3751118 :     _deprecated_name[obj_name] = replacement_name;
      61   112247456 :   if (!deprecated_time.empty())
      62     4352959 :     _deprecated_time[obj_name] = parseTime(deprecated_time);
      63             : 
      64             :   // TODO: Possibly store and print information about objects that are skipped here?
      65   112247462 : }
      66             : 
      67             : InputParameters
      68     4315684 : Factory::getValidParams(const std::string & obj_name) const
      69             : {
      70     4315684 :   const auto it = _name_to_object.find(obj_name);
      71             : 
      72             :   // Check if the object is registered
      73     4315684 :   if (it == _name_to_object.end())
      74          15 :     reportUnregisteredError(obj_name);
      75             : 
      76             :   // Print out deprecated message, if it exists
      77     4315669 :   deprecatedMessage(obj_name);
      78             : 
      79             :   // Return the parameters
      80     4315666 :   auto params = it->second->buildParameters();
      81     4315666 :   params.addPrivateParam(MooseBase::app_param, &_app);
      82             : 
      83     8631332 :   return params;
      84           0 : }
      85             : 
      86             : template <class ptr_type>
      87             : ptr_type
      88     2089382 : Factory::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     2089382 :   if (deprecated_method_name)
      99             :   {
     100           0 :     const std::string name = "Factory::" + *deprecated_method_name;
     101           0 :     mooseDeprecated(name + "() is deprecated, please use name" + "<T>() instead");
     102           0 :   }
     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     2089382 :   auto & warehouse_params = initialize(obj_name, name, parameters, tid);
     107             : 
     108             :   // Mark that we're constructing this object
     109     2089347 :   _currently_constructing.push_back(&warehouse_params);
     110             : 
     111             :   // Construct the object
     112     2089347 :   auto & registry_entry = *_name_to_object.at(obj_name);
     113     2089347 :   ptr_type obj;
     114             :   if constexpr (std::is_same_v<ptr_type, std::unique_ptr<MooseObject>>)
     115        1939 :     obj = registry_entry.build(warehouse_params);
     116             :   else
     117     2087408 :     obj = registry_entry.buildShared(warehouse_params);
     118             : 
     119             :   // Done constructing the object
     120     2087978 :   _currently_constructing.pop_back();
     121             : 
     122     2087978 :   finalize(obj_name, *obj);
     123             : 
     124     2087978 :   return obj;
     125          18 : }
     126             : 
     127             : std::unique_ptr<MooseObject>
     128        1939 : Factory::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        1939 :   std::optional<std::string> deprecated_method_name;
     135        1939 :   if (print_deprecated)
     136           0 :     deprecated_method_name = "createUnique";
     137             :   return createTempl<std::unique_ptr<MooseObject>>(
     138        3869 :       obj_name, name, parameters, tid, deprecated_method_name);
     139        1930 : }
     140             : 
     141             : std::shared_ptr<MooseObject>
     142     2087443 : Factory::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     2087443 :   std::optional<std::string> deprecated_method_name;
     149     2087443 :   if (print_deprecated)
     150           0 :     deprecated_method_name = "create";
     151             :   return createTempl<std::shared_ptr<MooseObject>>(
     152     4173491 :       obj_name, name, parameters, tid, deprecated_method_name);
     153     2086080 : }
     154             : 
     155             : void
     156      474734 : Factory::releaseSharedObjects(const MooseObject & moose_object, THREAD_ID tid)
     157             : {
     158      474734 :   _app.getInputParameterWarehouse().removeInputParameters(moose_object, tid, {});
     159      474734 : }
     160             : 
     161             : void
     162           2 : Factory::restrictRegisterableObjects(const std::vector<std::string> & names)
     163             : {
     164           2 :   _registerable_objects.insert(names.begin(), names.end());
     165           2 : }
     166             : 
     167             : std::time_t
     168     4352959 : Factory::parseTime(const std::string t_str)
     169             : {
     170             :   // The string must be a certain length to be valid
     171     4352959 :   if (t_str.size() != 16)
     172           0 :     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     4352959 :   time(&t_end);
     178     4352959 :   t_end_info = localtime(&t_end);
     179     4352959 :   t_end_info->tm_mon = std::atoi(t_str.substr(0, 2).c_str()) - 1;
     180     4352959 :   t_end_info->tm_mday = std::atoi(t_str.substr(3, 2).c_str());
     181     4352959 :   t_end_info->tm_year = std::atoi(t_str.substr(6, 4).c_str()) - 1900;
     182     4352959 :   t_end_info->tm_hour = std::atoi(t_str.substr(11, 2).c_str()) + 1;
     183     4352959 :   t_end_info->tm_min = std::atoi(t_str.substr(14, 2).c_str());
     184     4352959 :   t_end_info->tm_sec = 0;
     185     4352959 :   t_end = mktime(t_end_info);
     186     4352959 :   return t_end;
     187             : }
     188             : 
     189             : void
     190     6408161 : Factory::deprecatedMessage(const std::string obj_name) const
     191             : {
     192     6408161 :   const auto time_it = _deprecated_time.find(obj_name);
     193             : 
     194             :   // If the object is not deprecated return
     195     6408161 :   if (time_it == _deprecated_time.end())
     196     6406135 :     return;
     197             : 
     198             :   // If the message has already been printed, return
     199       10768 :   if (_deprecated_types.count(obj_name))
     200        8742 :     return;
     201        2026 :   _deprecated_types.emplace(obj_name);
     202             : 
     203             :   // Get the current time
     204             :   std::time_t now;
     205        2026 :   time(&now);
     206             : 
     207             :   // Get the stop time
     208        2026 :   std::time_t t_end = time_it->second;
     209             : 
     210             :   // Message storage
     211        2026 :   std::ostringstream msg;
     212             : 
     213        2026 :   const auto name_it = _deprecated_name.find(obj_name);
     214             : 
     215             :   // Expired object
     216        2026 :   if (now > t_end)
     217             :   {
     218        1350 :     msg << "***** Invalid Object: " << obj_name << " *****\n";
     219        1350 :     msg << "Expired on " << ctime(&t_end);
     220             : 
     221             :     // Append replacement object, if it exists
     222        1350 :     if (name_it != _deprecated_name.end())
     223         413 :       msg << "Update your application using the '" << name_it->second << "' object";
     224             : 
     225             :     // Produce the error message
     226        1350 :     mooseDeprecationExpiredNoTrace(msg.str());
     227             :   }
     228             : 
     229             :   // Expiring object
     230             :   else
     231             :   {
     232             :     // Build the basic message
     233         676 :     msg << "Deprecated Object: " << obj_name << "\n";
     234         676 :     msg << "This object will be removed on " << ctime(&t_end);
     235             : 
     236             :     // Append replacement object, if it exists
     237         676 :     if (name_it != _deprecated_name.end())
     238         655 :       msg << "Replace " << obj_name << " with " << name_it->second;
     239             : 
     240             :     // Produce the error message
     241         676 :     mooseDeprecatedNoTrace(msg.str());
     242             :   }
     243        2023 : }
     244             : 
     245             : void
     246          15 : Factory::reportUnregisteredError(const std::string & obj_name) const
     247             : {
     248          15 :   std::ostringstream oss;
     249          15 :   std::set<std::string> paths = _app.getLoadedLibraryPaths();
     250             : 
     251          15 :   oss << "A '" + obj_name + "' is not a registered object.\n";
     252             : 
     253          15 :   if (!paths.empty())
     254             :   {
     255             :     oss << "\nWe loaded objects from the following libraries and still couldn't find your "
     256           2 :            "object:\n\t";
     257           2 :     std::copy(paths.begin(), paths.end(), infix_ostream_iterator<std::string>(oss, "\n\t"));
     258           2 :     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          15 :          "MOOSE_LIBRARY_PATH environment variable.";
     264             : 
     265          15 :   mooseError(oss.str());
     266           0 : }
     267             : 
     268             : std::vector<std::string>
     269           0 : Factory::getConstructedObjects() const
     270             : {
     271           0 :   std::vector<std::string> list;
     272           0 :   for (const auto & name : _constructed_types)
     273           0 :     list.push_back(name);
     274           0 :   return list;
     275           0 : }
     276             : 
     277             : const InputParameters *
     278     2371429 : Factory::currentlyConstructing() const
     279             : {
     280     2371429 :   return _currently_constructing.size() ? _currently_constructing.back() : nullptr;
     281             : }
     282             : 
     283             : FileLineInfo
     284       63403 : Factory::getLineInfo(const std::string & name) const
     285             : {
     286       63403 :   return _name_to_line.getInfo(name);
     287             : }
     288             : 
     289             : void
     290     4689035 : Factory::associateNameToClass(const std::string & name, const std::string & class_name)
     291             : {
     292     4689035 :   _name_to_class[name] = class_name;
     293     4689035 : }
     294             : 
     295             : std::string
     296       63401 : Factory::associatedClassName(const std::string & name) const
     297             : {
     298       63401 :   auto it = _name_to_class.find(name);
     299       63401 :   if (it == _name_to_class.end())
     300      121698 :     return "";
     301             :   else
     302        2552 :     return it->second;
     303             : }
     304             : 
     305             : InputParameters &
     306     2092492 : Factory::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     2092492 :   const auto it = _name_to_object.find(type);
     313             : 
     314             :   // Check if the object is registered
     315     2092492 :   if (it == _name_to_object.end())
     316           0 :     reportUnregisteredError(type);
     317             : 
     318             :   // Print out deprecated message, if it exists
     319     2092492 :   deprecatedMessage(type);
     320             : 
     321             :   // Create the actual parameters object that the object will reference
     322             :   InputParameters & params =
     323     2092492 :       _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     2092480 :   if (!params.getHitNode() || params.getHitNode()->isRoot())
     330      932802 :     if (const auto hit_node = _app.getCurrentActionHitNode())
     331      931229 :       params.setHitNode(*hit_node, {});
     332             : 
     333             :   // Set the type parameter
     334     2092480 :   params.set<std::string>(MooseBase::type_param) = type;
     335             : 
     336             :   // Check to make sure that all required parameters are supplied
     337     2092480 :   params.finalize(name);
     338             : 
     339             :   // register type name as constructed
     340     2092457 :   _constructed_types.insert(type);
     341             : 
     342             :   // add FEProblem pointers to object's params object
     343     2092457 :   if (_app.actionWarehouse().problemBase())
     344     1707199 :     _app.actionWarehouse().problemBase()->setInputParametersFEProblem(params);
     345             : 
     346     2092457 :   return params;
     347             : }
     348             : 
     349             : void
     350     2247854 : Factory::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     2247854 :   InputParameters orig_params = getValidParams(type);
     356     2247854 :   const auto & object_params = object.parameters();
     357     2247854 :   if (orig_params.n_parameters() != object_params.n_parameters())
     358             :   {
     359        1602 :     std::set<std::string> orig, populated;
     360       64080 :     for (const auto & it : orig_params)
     361       62478 :       orig.emplace(it.first);
     362       59274 :     for (const auto & it : object_params)
     363       57672 :       populated.emplace(it.first);
     364             : 
     365        1602 :     std::set<std::string> diff;
     366        1602 :     std::set_difference(populated.begin(),
     367             :                         populated.end(),
     368             :                         orig.begin(),
     369             :                         orig.end(),
     370             :                         std::inserter(diff, diff.begin()));
     371             : 
     372        1602 :     if (!diff.empty())
     373             :     {
     374           0 :       std::stringstream ss;
     375           0 :       for (const auto & name : diff)
     376           0 :         ss << ", " << name;
     377           0 :       object.mooseError("Attempted to set unregistered parameter(s):\n    ", ss.str().substr(2));
     378           0 :     }
     379        1602 :   }
     380     2247854 : }
     381             : 
     382             : // Explicit instantiation for Factory::createTempl
     383             : template std::unique_ptr<MooseObject>
     384             : Factory::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> &);
     389             : template std::shared_ptr<MooseObject>
     390             : Factory::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> &);

Generated by: LCOV version 1.14