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