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