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 : #pragma once 11 : 12 : #include <vector> 13 : 14 : #include "MooseApp.h" 15 : 16 : #ifdef MOOSE_UNIT_TEST 17 : #include "gtest/gtest.h" 18 : class GTEST_TEST_CLASS_NAME_(AppFactoryTest, manageAppParams); 19 : class GTEST_TEST_CLASS_NAME_(AppFactoryTest, appCopyConstructParams); 20 : class GTEST_TEST_CLASS_NAME_(AppFactoryTest, createNotRegistered); 21 : #endif 22 : 23 : /** 24 : * Macros 25 : */ 26 : #define registerApp(name) AppFactory::instance().reg<name>(#name) 27 : 28 : /** 29 : * Polymorphic data structure with parameter and object build access. 30 : */ 31 : struct AppFactoryBuildInfoBase 32 : { 33 : virtual std::unique_ptr<MooseApp> build(const InputParameters & params) = 0; 34 : virtual InputParameters buildParameters() = 0; 35 2 : virtual ~AppFactoryBuildInfoBase() = default; 36 : 37 : std::size_t _app_creation_count = 0; 38 : }; 39 : template <typename T> 40 : struct AppFactoryBuildInfo : public AppFactoryBuildInfoBase 41 : { 42 66970 : virtual std::unique_ptr<MooseApp> build(const InputParameters & params) override 43 : { 44 66970 : return std::make_unique<T>(params); 45 : } 46 66947 : virtual InputParameters buildParameters() override { return T::validParams(); } 47 : }; 48 : 49 : using AppFactoryBuildInfoMap = std::map<std::string, std::unique_ptr<AppFactoryBuildInfoBase>>; 50 : 51 : /** 52 : * Generic AppFactory class for building Application objects 53 : */ 54 : class AppFactory 55 : { 56 : public: 57 : /** 58 : * Get the instance of the AppFactory 59 : * @return Reference to the AppFactory instance 60 : */ 61 : static AppFactory & instance(); 62 : 63 : virtual ~AppFactory(); 64 : 65 : static InputParameters validParams(); 66 : 67 : /// The name for the "main" moose application 68 : static const std::string main_app_name; 69 : 70 : /** 71 : * Create an app with no input and command line arguments. 72 : * 73 : * Useful for unit testing. 74 : */ 75 : static std::unique_ptr<MooseApp> create(const std::string & app_type, 76 : const std::vector<std::string> & cli_args = {}); 77 : 78 : /** 79 : * Create a MooseApp from a Parser and CommandLine, both of which should have parsed. 80 : */ 81 : static std::unique_ptr<MooseApp> create(std::unique_ptr<Parser> parser, 82 : std::unique_ptr<CommandLine> command_line); 83 : 84 : /** 85 : * Create a MooseApp given a set of parameters. 86 : * 87 : * The Parser must be set in the _parser param and the CommandLine must be set 88 : * in the _command_line param, both of which must have been parsed. 89 : * 90 : * @param app_type Type of the application being constructed 91 : * @param name Name for the object 92 : * @param parameters Parameters this object should have 93 : * @return The created object 94 : */ 95 : ///@{ 96 : std::unique_ptr<MooseApp> create(const std::string & app_type, 97 : const std::string & name, 98 : InputParameters parameters, 99 : MPI_Comm COMM_WORLD_IN); 100 : std::shared_ptr<MooseApp> createShared(const std::string & app_type, 101 : const std::string & name, 102 : InputParameters parameters, 103 : MPI_Comm COMM_WORLD_IN); 104 : ///@} 105 : 106 : /** 107 : * Deprecated helper function for creating a MooseApp for Apps haven't adapted to the new Parser 108 : * and Builder changes. This function needed to be removed after the new Parser and Builder merged 109 : */ 110 : static std::shared_ptr<MooseApp> createAppShared(const std::string & default_app_type, 111 : int argc, 112 : char ** argv, 113 : MPI_Comm comm_word = MPI_COMM_WORLD); 114 : 115 : /** 116 : * Register a new object 117 : * @param name Name of the object to register 118 : */ 119 : template <typename T> 120 : void reg(const std::string & name); 121 : 122 : /** 123 : * Get valid parameters for the object 124 : * @param name Name of the object whose parameter we are requesting 125 : * @return Parameters of the object 126 : */ 127 : InputParameters getValidParams(const std::string & name); 128 : 129 : /** 130 : * @return The parameters for the application named \p name 131 : * 132 : * This is needed because we poorly decided to not pass references 133 : * of the InputParameters in all derived MooseApp objects. This enables 134 : * the MooseApp to get the copy of the parameters that it was actually 135 : * built with using this factory. 136 : */ 137 : const InputParameters & getAppParams(const InputParameters & params) const; 138 : 139 : /** 140 : * Class that is used as a parameter to clearAppParams() that allows only 141 : * MooseApp to call clearAppParams(). 142 : */ 143 : class ClearAppParamsKey 144 : { 145 : friend class MooseApp; 146 : #ifdef MOOSE_UNIT_TEST 147 : FRIEND_TEST(::AppFactoryTest, manageAppParams); 148 : #endif 149 62880 : ClearAppParamsKey() {} 150 : ClearAppParamsKey(const ClearAppParamsKey &) {} 151 : }; 152 : 153 : /** 154 : * Clears the stored parameters for the given application parameteres 155 : * 156 : * See getAppParams() for why this is needed. 157 : */ 158 : void clearAppParams(const InputParameters & params, const ClearAppParamsKey); 159 : 160 : /** 161 : * Returns a reference to the map from names to AppFactoryBuildInfo pointers 162 : */ 163 31375 : const auto & registeredObjects() const { return _name_to_build_info; } 164 : 165 : /** 166 : * Returns a Boolean indicating whether an application type has been registered 167 : */ 168 117138 : bool isRegistered(const std::string & app_name) const 169 : { 170 117138 : return _name_to_build_info.count(app_name); 171 : } 172 : 173 : /** 174 : * @returns the amount of times the AppFactory created the named App-type 175 : */ 176 : std::size_t createdAppCount(const std::string & app_type) const; 177 : 178 : /** 179 : * Returns the map of object name to a function pointer for building said object's 180 : * input parameters. 181 : */ 182 : const AppFactoryBuildInfoMap & registeredObjectBuildInfos() const { return _name_to_build_info; } 183 : 184 : ///@{ Don't allow creation through copy/move construction or assignment 185 : AppFactory(AppFactory const &) = delete; 186 : Registry & operator=(AppFactory const &) = delete; 187 : 188 : AppFactory(AppFactory &&) = delete; 189 : Registry & operator=(AppFactory &&) = delete; 190 : ///@} 191 : 192 : protected: 193 : AppFactoryBuildInfoMap _name_to_build_info; 194 : 195 : private: 196 : /** 197 : * Stores the given parameters within _input_parameters for app construction 198 : * 199 : * Also calls finalize() on the parameters 200 : */ 201 : const InputParameters & storeAppParams(InputParameters & params); 202 : 203 : /** 204 : * Get the ID for the InputParameters associated with an application, used 205 : * in storing them in _input_parameters. 206 : * 207 : * This is needed until app constructors do not copy construct parameters. 208 : * See getAppParams() for more information. 209 : * 210 : * The parameters passed in here (from the app) could be copy-constructed 211 : * parameters, but will contain a "_app_params_id" parameter that allows 212 : * us to get the actual parameters (owned by this factory). 213 : */ 214 : std::size_t getAppParamsID(const InputParameters & params) const; 215 : 216 : /** 217 : * Register an application name as a capability. 218 : */ 219 : void registerAppCapability(const std::string & app_name); 220 : 221 : /// Private constructor for singleton pattern 222 54397 : AppFactory() {} 223 : 224 : #ifdef MOOSE_UNIT_TEST 225 : FRIEND_TEST(::AppFactoryTest, manageAppParams); 226 : FRIEND_TEST(::AppFactoryTest, appCopyConstructParams); 227 : FRIEND_TEST(::AppFactoryTest, createNotRegistered); 228 : #endif 229 : 230 : /// Storage of input parameters used in applications (ID (from getAppParamsID()) -> params) 231 : std::map<std::size_t, std::unique_ptr<InputParameters>> _input_parameters; 232 : }; 233 : 234 : template <typename T> 235 : void 236 54370 : AppFactory::reg(const std::string & name) 237 : { 238 54370 : if (isRegistered(name)) 239 0 : return; 240 : 241 54370 : _name_to_build_info[name] = std::make_unique<AppFactoryBuildInfo<T>>(); 242 : 243 54370 : registerAppCapability(name); 244 : }