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 "AppFactory.h" 11 : #include "CommandLine.h" 12 : #include "InputParameters.h" 13 : #include "MooseApp.h" 14 : #include "Parser.h" 15 : #include "MooseMain.h" 16 : #include "Capabilities.h" 17 : #include "MooseStringUtils.h" 18 : 19 : AppFactory & 20 412395 : AppFactory::instance() 21 : { 22 : // We need a naked new here (_not_ a smart pointer or object instance) due to what seems like a 23 : // bug in clang's static object destruction when using dynamic library loading. 24 : static AppFactory * instance = nullptr; 25 412395 : if (!instance) 26 54389 : instance = new AppFactory; 27 412395 : return *instance; 28 : } 29 : 30 8 : AppFactory::~AppFactory() {} 31 : 32 : const std::string AppFactory::main_app_name = "main"; 33 : 34 : InputParameters 35 66972 : AppFactory::getValidParams(const std::string & name) 36 : { 37 66972 : if (const auto it = _name_to_build_info.find(name); it != _name_to_build_info.end()) 38 66972 : return it->second->buildParameters(); 39 : 40 0 : mooseError(std::string("A '") + name + "' is not a registered object\n\n"); 41 : } 42 : 43 : const InputParameters & 44 66997 : AppFactory::getAppParams(const InputParameters & params) const 45 : { 46 66997 : const auto id = getAppParamsID(params); 47 66997 : if (const auto it = _input_parameters.find(id); it != _input_parameters.end()) 48 66997 : return *it->second; 49 0 : mooseError("AppFactory::getAppParams(): Parameters for application with ID ", id, " not found"); 50 : } 51 : 52 : void 53 62880 : AppFactory::clearAppParams(const InputParameters & params, const ClearAppParamsKey) 54 : { 55 62880 : const auto id = getAppParamsID(params); 56 62880 : if (const auto it = _input_parameters.find(id); it != _input_parameters.end()) 57 62878 : _input_parameters.erase(it); 58 : else 59 2 : mooseError( 60 : "AppFactory::clearAppParams(): Parameters for application with ID ", id, " not found"); 61 62878 : } 62 : 63 : std::unique_ptr<MooseApp> 64 40 : AppFactory::create(const std::string & app_type, 65 : const std::vector<std::string> & cli_args /* = {} */) 66 : { 67 40 : auto parser = std::make_unique<Parser>(std::vector<std::string>()); 68 40 : parser->parse(); 69 40 : parser->setAppType(app_type); 70 : 71 120 : auto command_line = std::make_unique<CommandLine>(std::vector<std::string>{"unused"}); 72 40 : command_line->addArguments(cli_args); 73 40 : command_line->parse(); 74 : 75 80 : return AppFactory::create(std::move(parser), std::move(command_line)); 76 160 : } 77 : 78 : std::unique_ptr<MooseApp> 79 54871 : AppFactory::create(std::unique_ptr<Parser> parser, std::unique_ptr<CommandLine> command_line) 80 : { 81 : mooseAssert(parser, "Not set"); 82 : mooseAssert(parser->getAppType().size(), "App type not set"); 83 : mooseAssert(parser->queryRoot(), "Has not parsed"); 84 : mooseAssert(command_line, "Not set"); 85 : mooseAssert(command_line->hasParsed(), "Has not parsed"); 86 : 87 54871 : const std::string app_type = parser->getAppType(); 88 : 89 54871 : auto app_params = AppFactory::instance().getValidParams(parser->getAppType()); 90 109742 : app_params.set<std::shared_ptr<Parser>>("_parser") = std::move(parser); 91 109742 : app_params.set<std::shared_ptr<CommandLine>>("_command_line") = std::move(command_line); 92 : 93 109739 : return AppFactory::instance().create(app_type, main_app_name, app_params, MPI_COMM_WORLD); 94 54868 : } 95 : 96 : std::shared_ptr<MooseApp> 97 2 : AppFactory::createAppShared(const std::string & default_app_type, 98 : int argc, 99 : char ** argv, 100 : MPI_Comm comm_world_in) 101 : { 102 2 : mooseDeprecated("Please update your main.C to adapt new main function in MOOSE framework, " 103 : "see'test/src/main.C in MOOSE as an example of moose::main()'. "); 104 : 105 : // Populate the -i and --app parameters early 106 2 : auto command_line_params = emptyInputParameters(); 107 2 : MooseApp::addInputParam(command_line_params); 108 2 : MooseApp::addAppParam(command_line_params); 109 : { 110 2 : CommandLine pre_command_line(argc, argv); 111 2 : pre_command_line.parse(); 112 2 : pre_command_line.populateCommandLineParams(command_line_params); 113 2 : } 114 2 : const auto & input_filenames = command_line_params.get<std::vector<std::string>>("input_file"); 115 2 : std::string app_type = command_line_params.get<std::string>("app_to_run"); 116 : 117 2 : auto command_line = std::make_unique<CommandLine>(argc, argv); 118 2 : command_line->parse(); 119 : 120 2 : auto parser = std::make_unique<Parser>(input_filenames); 121 2 : parser->setCommandLineParams(command_line->buildHitParams()); 122 2 : parser->parse(); 123 : 124 2 : if (app_type.empty()) 125 2 : app_type = default_app_type; 126 : else 127 0 : mooseDeprecated("Please use [Application] block to specify application type, '--app <AppName>' " 128 : "is deprecated and will be removed in a future release."); 129 : 130 2 : parser->setAppType(app_type); 131 : 132 2 : auto app_params = AppFactory::instance().getValidParams(app_type); 133 4 : app_params.set<std::shared_ptr<Parser>>("_parser") = std::move(parser); 134 4 : app_params.set<std::shared_ptr<CommandLine>>("_command_line") = std::move(command_line); 135 : 136 8 : return AppFactory::instance().create(app_type, "main", app_params, comm_world_in); 137 2 : } 138 : 139 : std::unique_ptr<MooseApp> 140 66997 : AppFactory::create(const std::string & app_type, 141 : const std::string & name, 142 : InputParameters parameters, 143 : MPI_Comm comm_world_in) 144 : { 145 : // Error if the application type is not located 146 66997 : const auto it = _name_to_build_info.find(app_type); 147 66997 : if (it == _name_to_build_info.end()) 148 6 : mooseError("AppFactory::Create(): Application '" + app_type + "' was not registered"); 149 66995 : auto & build_info = it->second; 150 : 151 66995 : auto comm = std::make_shared<Parallel::Communicator>(comm_world_in); 152 : 153 : // Take the app_type and add it to the parameters so that it can be retrieved in the Application 154 66995 : parameters.set<std::string>(MooseBase::type_param) = app_type; 155 66995 : parameters.set<std::string>(MooseBase::name_param) = name; 156 66995 : parameters.set<std::string>(MooseBase::unique_name_param) = "Application/" + name; 157 133990 : parameters.set<std::shared_ptr<Parallel::Communicator>>("_comm") = comm; 158 66995 : parameters.set<std::string>("_app_name") = name; 159 : 160 66995 : auto parser = parameters.get<std::shared_ptr<Parser>>("_parser"); 161 : mooseAssert(parser, "Parser not valid"); 162 : mooseAssert(parser->queryRoot(), "Parser has not parsed"); 163 : 164 66995 : auto command_line = parameters.get<std::shared_ptr<CommandLine>>("_command_line"); 165 : mooseAssert(command_line, "Command line not valid"); 166 : mooseAssert(command_line->hasParsed(), "Command line has not parsed"); 167 66995 : command_line->populateCommandLineParams(parameters); 168 : 169 : // Historically we decided to non-const copy construct all application parameters. In 170 : // order to get around that while apps are fixed (by taking a const reference instead), 171 : // we store the app params here and the MooseApp constructor will query the InputParameters 172 : // owned by ths factory instead of the ones that are passed to it (likely a const ref to a 173 : // copy of the derived app's parmeters) 174 66995 : const auto & params = storeAppParams(parameters); 175 : 176 66995 : build_info->_app_creation_count++; 177 : 178 133985 : return build_info->build(params); 179 66996 : } 180 : 181 : std::shared_ptr<MooseApp> 182 0 : AppFactory::createShared(const std::string & app_type, 183 : const std::string & name, 184 : InputParameters parameters, 185 : MPI_Comm comm_world_in) 186 : { 187 0 : return AppFactory::instance().create(app_type, name, parameters, comm_world_in); 188 : } 189 : 190 : std::size_t 191 0 : AppFactory::createdAppCount(const std::string & app_type) const 192 : { 193 : // Error if the application type is not located 194 0 : const auto it = _name_to_build_info.find(app_type); 195 0 : if (it == _name_to_build_info.end()) 196 0 : mooseError("AppFactory::createdAppCount(): '", app_type, "' is not a registered app"); 197 : 198 0 : return it->second->_app_creation_count; 199 : } 200 : 201 : const InputParameters & 202 66999 : AppFactory::storeAppParams(InputParameters & params) 203 : { 204 : const std::size_t next_id = 205 79119 : _input_parameters.size() ? (std::prev(_input_parameters.end())->first + 1) : 0; 206 66999 : params.addPrivateParam<std::size_t>("_app_params_id", next_id); 207 : const auto it_inserted_pair = 208 66999 : _input_parameters.emplace(next_id, std::make_unique<InputParameters>(params)); 209 : mooseAssert(it_inserted_pair.second, "Already exists"); 210 66999 : auto & stored_params = *it_inserted_pair.first->second; 211 66999 : stored_params.finalize(""); 212 66999 : return stored_params; 213 : } 214 : 215 : std::size_t 216 129885 : AppFactory::getAppParamsID(const InputParameters & params) const 217 : { 218 129885 : if (!params.have_parameter<std::size_t>("_app_params_id")) 219 2 : mooseError("AppFactory::getAppParamsID(): Invalid application parameters (missing " 220 : "'_app_params_id')"); 221 129883 : return params.get<std::size_t>("_app_params_id"); 222 : } 223 : 224 : void 225 54420 : AppFactory::registerAppCapability(const std::string & app_name) 226 : { 227 54420 : auto & capabilities = Moose::internal::Capabilities::getCapabilities({}); 228 108840 : capabilities.add(MooseUtils::toLower(app_name), 229 54420 : bool(true), 230 108840 : "MOOSE application " + app_name + " is available."); 231 54420 : }