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