LCOV - code coverage report
Current view: top level - src/base - Factory.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: #31706 (f8ed4a) with base bb0a08 Lines: 147 169 87.0 %
Date: 2025-11-03 17:23:24 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       70055 : Factory::Factory(MooseApp & app) : _app(app) {}
      19             : 
      20       64287 : Factory::~Factory() {}
      21             : 
      22             : void
      23   109442464 : Factory::reg(std::shared_ptr<RegistryEntryBase> obj)
      24             : {
      25   109442464 :   const std::string obj_name = obj->name();
      26   109442464 :   const std::string & label = obj->_label;
      27   109442464 :   const std::string & deprecated_time = obj->_deprecated_time;
      28   109442464 :   const std::string & replacement_name = obj->_replaced_by;
      29   109442464 :   const std::string & file = obj->_file;
      30   109442464 :   const int line = obj->_line;
      31             : 
      32             :   // do nothing if we have already added this exact object before
      33   109442464 :   auto key = std::make_pair(label, obj_name);
      34   109442464 :   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   109443001 :   if (_registerable_objects.empty() ||
      47   109443001 :       _registerable_objects.find(obj_name) != _registerable_objects.end())
      48             :   {
      49   109441924 :     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   109441924 :     _name_to_object[obj_name] = obj;
      55   109441924 :     _objects_by_label.insert(key);
      56             :   }
      57   109442461 :   _name_to_line.addInfo(obj_name, file, line);
      58             : 
      59   109442461 :   if (!replacement_name.empty())
      60     3712474 :     _deprecated_name[obj_name] = replacement_name;
      61   109442461 :   if (!deprecated_time.empty())
      62     4342168 :     _deprecated_time[obj_name] = parseTime(deprecated_time);
      63             : 
      64             :   // TODO: Possibly store and print information about objects that are skipped here?
      65   109442467 : }
      66             : 
      67             : InputParameters
      68     4545762 : Factory::getValidParams(const std::string & obj_name) const
      69             : {
      70     4545762 :   const auto it = _name_to_object.find(obj_name);
      71             : 
      72             :   // Check if the object is registered
      73     4545762 :   if (it == _name_to_object.end())
      74          19 :     reportUnregisteredError(obj_name);
      75             : 
      76             :   // Print out deprecated message, if it exists
      77     4545743 :   deprecatedMessage(obj_name);
      78             : 
      79             :   // Return the parameters
      80     4545739 :   auto params = it->second->buildParameters();
      81     4545739 :   params.addPrivateParam(MooseBase::app_param, &_app);
      82             : 
      83     9091478 :   return params;
      84           0 : }
      85             : 
      86             : template <class ptr_type>
      87             : ptr_type
      88     2191615 : 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     2191615 :   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     2191615 :   auto & warehouse_params = initialize(obj_name, name, parameters, tid);
     107             : 
     108             :   // Mark that we're constructing this object
     109     2191575 :   _currently_constructing.push_back(&warehouse_params);
     110             : 
     111             :   // Construct the object
     112     2191575 :   auto & registry_entry = *_name_to_object.at(obj_name);
     113     2191575 :   ptr_type obj;
     114             :   if constexpr (std::is_same_v<ptr_type, std::unique_ptr<MooseObject>>)
     115        1956 :     obj = registry_entry.build(warehouse_params);
     116             :   else
     117     2189619 :     obj = registry_entry.buildShared(warehouse_params);
     118             : 
     119             :   // Done constructing the object
     120     2189820 :   _currently_constructing.pop_back();
     121             : 
     122     2189820 :   finalize(obj_name, *obj);
     123             : 
     124     2189820 :   return obj;
     125          12 : }
     126             : 
     127             : std::unique_ptr<MooseObject>
     128        1956 : 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        1956 :   std::optional<std::string> deprecated_method_name;
     135        1956 :   if (print_deprecated)
     136           0 :     deprecated_method_name = "createUnique";
     137             :   return createTempl<std::unique_ptr<MooseObject>>(
     138        3900 :       obj_name, name, parameters, tid, deprecated_method_name);
     139        1944 : }
     140             : 
     141             : std::shared_ptr<MooseObject>
     142     2189659 : 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     2189659 :   std::optional<std::string> deprecated_method_name;
     149     2189659 :   if (print_deprecated)
     150           0 :     deprecated_method_name = "create";
     151             :   return createTempl<std::shared_ptr<MooseObject>>(
     152     4377535 :       obj_name, name, parameters, tid, deprecated_method_name);
     153     2187900 : }
     154             : 
     155             : void
     156      500540 : Factory::releaseSharedObjects(const MooseObject & moose_object, THREAD_ID tid)
     157             : {
     158      500540 :   _app.getInputParameterWarehouse().removeInputParameters(moose_object, tid, {});
     159      500540 : }
     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     4342168 : Factory::parseTime(const std::string t_str)
     169             : {
     170             :   // The string must be a certain length to be valid
     171     4342168 :   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     4342168 :   time(&t_end);
     178     4342168 :   t_end_info = localtime(&t_end);
     179     4342168 :   t_end_info->tm_mon = std::atoi(t_str.substr(0, 2).c_str()) - 1;
     180     4342168 :   t_end_info->tm_mday = std::atoi(t_str.substr(3, 2).c_str());
     181     4342168 :   t_end_info->tm_year = std::atoi(t_str.substr(6, 4).c_str()) - 1900;
     182     4342168 :   t_end_info->tm_hour = std::atoi(t_str.substr(11, 2).c_str()) + 1;
     183     4342168 :   t_end_info->tm_min = std::atoi(t_str.substr(14, 2).c_str());
     184     4342168 :   t_end_info->tm_sec = 0;
     185     4342168 :   t_end = mktime(t_end_info);
     186     4342168 :   return t_end;
     187             : }
     188             : 
     189             : void
     190     6740835 : Factory::deprecatedMessage(const std::string obj_name) const
     191             : {
     192     6740835 :   const auto time_it = _deprecated_time.find(obj_name);
     193             : 
     194             :   // If the object is not deprecated return
     195     6740835 :   if (time_it == _deprecated_time.end())
     196     6739119 :     return;
     197             : 
     198             :   // If the message has already been printed, return
     199        9756 :   if (_deprecated_types.count(obj_name))
     200        8040 :     return;
     201        1716 :   _deprecated_types.emplace(obj_name);
     202             : 
     203             :   // We dont need a backtrace on this, this is user-facing
     204        1716 :   const auto current_show_trace = Moose::show_trace;
     205        1716 :   Moose::show_trace = false;
     206             : 
     207             :   // Get the current time
     208             :   std::time_t now;
     209        1716 :   time(&now);
     210             : 
     211             :   // Get the stop time
     212        1716 :   std::time_t t_end = time_it->second;
     213             : 
     214             :   // Message storage
     215        1716 :   std::ostringstream msg;
     216             : 
     217        1716 :   const auto name_it = _deprecated_name.find(obj_name);
     218             : 
     219             :   // Expired object
     220        1716 :   if (now > t_end)
     221             :   {
     222        1149 :     msg << "***** Invalid Object: " << obj_name << " *****\n";
     223        1149 :     msg << "Expired on " << ctime(&t_end);
     224             : 
     225             :     // Append replacement object, if it exists
     226        1149 :     if (name_it != _deprecated_name.end())
     227         453 :       msg << "Update your application using the '" << name_it->second << "' object";
     228             : 
     229             :     // Produce the error message
     230        1149 :     mooseDeprecationExpired(msg.str());
     231             :   }
     232             : 
     233             :   // Expiring object
     234             :   else
     235             :   {
     236             :     // Build the basic message
     237         567 :     msg << "Deprecated Object: " << obj_name << "\n";
     238         567 :     msg << "This object will be removed on " << ctime(&t_end);
     239             : 
     240             :     // Append replacement object, if it exists
     241         567 :     if (name_it != _deprecated_name.end())
     242         196 :       msg << "Replace " << obj_name << " with " << name_it->second;
     243             : 
     244             :     // Produce the error message
     245         567 :     mooseDeprecated(msg.str());
     246             :   }
     247        1712 :   Moose::show_trace = current_show_trace;
     248        1712 : }
     249             : 
     250             : void
     251          19 : Factory::reportUnregisteredError(const std::string & obj_name) const
     252             : {
     253          19 :   std::ostringstream oss;
     254          19 :   std::set<std::string> paths = _app.getLoadedLibraryPaths();
     255             : 
     256          19 :   oss << "A '" + obj_name + "' is not a registered object.\n";
     257             : 
     258          19 :   if (!paths.empty())
     259             :   {
     260             :     oss << "\nWe loaded objects from the following libraries and still couldn't find your "
     261           2 :            "object:\n\t";
     262           2 :     std::copy(paths.begin(), paths.end(), infix_ostream_iterator<std::string>(oss, "\n\t"));
     263           2 :     oss << '\n';
     264             :   }
     265             : 
     266             :   oss << "\nIf you are trying to find this object in a dynamically loaded library, make sure that\n"
     267             :          "the library can be found either in your \"Problem/library_path\" parameter or in the\n"
     268          19 :          "MOOSE_LIBRARY_PATH environment variable.";
     269             : 
     270          19 :   mooseError(oss.str());
     271           0 : }
     272             : 
     273             : std::vector<std::string>
     274           0 : Factory::getConstructedObjects() const
     275             : {
     276           0 :   std::vector<std::string> list;
     277           0 :   for (const auto & name : _constructed_types)
     278           0 :     list.push_back(name);
     279           0 :   return list;
     280           0 : }
     281             : 
     282             : const InputParameters *
     283     2487906 : Factory::currentlyConstructing() const
     284             : {
     285     2487906 :   return _currently_constructing.size() ? _currently_constructing.back() : nullptr;
     286             : }
     287             : 
     288             : FileLineInfo
     289      491388 : Factory::getLineInfo(const std::string & name) const
     290             : {
     291      491388 :   return _name_to_line.getInfo(name);
     292             : }
     293             : 
     294             : void
     295     4879582 : Factory::associateNameToClass(const std::string & name, const std::string & class_name)
     296             : {
     297     4879582 :   _name_to_class[name] = class_name;
     298     4879582 : }
     299             : 
     300             : std::string
     301      491386 : Factory::associatedClassName(const std::string & name) const
     302             : {
     303      491386 :   auto it = _name_to_class.find(name);
     304      491386 :   if (it == _name_to_class.end())
     305      940936 :     return "";
     306             :   else
     307       20918 :     return it->second;
     308             : }
     309             : 
     310             : InputParameters &
     311     2195092 : Factory::initialize(const std::string & type,
     312             :                     const std::string & name,
     313             :                     const InputParameters & from_params,
     314             :                     const THREAD_ID tid)
     315             : {
     316             :   // Pointer to the object constructor
     317     2195092 :   const auto it = _name_to_object.find(type);
     318             : 
     319             :   // Check if the object is registered
     320     2195092 :   if (it == _name_to_object.end())
     321           0 :     reportUnregisteredError(type);
     322             : 
     323             :   // Print out deprecated message, if it exists
     324     2195092 :   deprecatedMessage(type);
     325             : 
     326             :   // Create the actual parameters object that the object will reference
     327             :   InputParameters & params =
     328     2195092 :       _app.getInputParameterWarehouse().addInputParameters(name, from_params, tid, {});
     329             : 
     330             :   // Add the hit node from the action if it isn't set already (it might be set
     331             :   // already because someone had a better option than just the action)
     332             :   // If it isn't set, it typically means that this object was created by a
     333             :   // non-MooseObjectAction Action
     334     2195080 :   if (!params.getHitNode() || params.getHitNode()->isRoot())
     335      968714 :     if (const auto hit_node = _app.getCurrentActionHitNode())
     336      967523 :       params.setHitNode(*hit_node, {});
     337             : 
     338             :   // Set the type parameter
     339     2195080 :   params.set<std::string>(MooseBase::type_param) = type;
     340             : 
     341             :   // Check to make sure that all required parameters are supplied
     342     2195080 :   params.finalize(name);
     343             : 
     344             :   // register type name as constructed
     345     2195052 :   _constructed_types.insert(type);
     346             : 
     347             :   // add FEProblem pointers to object's params object
     348     2195052 :   if (_app.actionWarehouse().problemBase())
     349     1790997 :     _app.actionWarehouse().problemBase()->setInputParametersFEProblem(params);
     350             : 
     351     2195052 :   return params;
     352             : }
     353             : 
     354             : void
     355     2357657 : Factory::finalize(const std::string & type, const MooseObject & object)
     356             : {
     357             :   // Make sure no unexpected parameters were added by the object's constructor or by the action
     358             :   // initiating this create call.  All parameters modified by the constructor must have already
     359             :   // been specified in the object's validParams function.
     360     2357657 :   InputParameters orig_params = getValidParams(type);
     361     2357657 :   const auto & object_params = object.parameters();
     362     2357657 :   if (orig_params.n_parameters() != object_params.n_parameters())
     363             :   {
     364        1784 :     std::set<std::string> orig, populated;
     365       71360 :     for (const auto & it : orig_params)
     366       69576 :       orig.emplace(it.first);
     367       66008 :     for (const auto & it : object_params)
     368       64224 :       populated.emplace(it.first);
     369             : 
     370        1784 :     std::set<std::string> diff;
     371        1784 :     std::set_difference(populated.begin(),
     372             :                         populated.end(),
     373             :                         orig.begin(),
     374             :                         orig.end(),
     375             :                         std::inserter(diff, diff.begin()));
     376             : 
     377        1784 :     if (!diff.empty())
     378             :     {
     379           0 :       std::stringstream ss;
     380           0 :       for (const auto & name : diff)
     381           0 :         ss << ", " << name;
     382           0 :       object.mooseError("Attempted to set unregistered parameter(s):\n    ", ss.str().substr(2));
     383           0 :     }
     384        1784 :   }
     385     2357657 : }
     386             : 
     387             : // Explicit instantiation for Factory::createTempl
     388             : template std::unique_ptr<MooseObject>
     389             : Factory::createTempl<std::unique_ptr<MooseObject>>(const std::string &,
     390             :                                                    const std::string &,
     391             :                                                    const InputParameters &,
     392             :                                                    const THREAD_ID,
     393             :                                                    const std::optional<std::string> &);
     394             : template std::shared_ptr<MooseObject>
     395             : Factory::createTempl<std::shared_ptr<MooseObject>>(const std::string &,
     396             :                                                    const std::string &,
     397             :                                                    const InputParameters &,
     398             :                                                    const THREAD_ID,
     399             :                                                    const std::optional<std::string> &);

Generated by: LCOV version 1.14