20 #include "libmesh/libmesh.h" 21 #include "libmesh/simple_range.h" 22 #include "libmesh/parallel_algebra.h" 23 #include "libmesh/parallel_sync.h" 34 for (
int i = 0; i < argc; i++)
41 mooseAssert(!
hasParsed(),
"Has already parsed");
48 for (
const auto & arg : args)
61 mooseAssert(!
hasParsed(),
"Has already parsed");
62 auto it = std::find(
_argv.begin(),
_argv.end(), arg);
63 if (it ==
_argv.end())
64 mooseError(
"CommandLine::removeArgument(): The argument '", arg,
"' does not exist");
71 mooseAssert(!
hasParsed(),
"Has already parsed");
72 mooseAssert(
_entries.empty(),
"Should be empty");
75 bool has_value_accepting_entry =
false;
78 auto add_entry = [
this](
const auto &
name) ->
Entry &
80 auto & entry =
_entries.emplace_back();
88 const auto & arg =
_argv[i];
90 std::string subapp_prefix, subapp_name, hit_path, hit_value;
93 if (!begins_with_dash && std::regex_search(arg, std::regex(
"^(([^\\s\n\t[\\]\\/=#&:]+):)[-]")))
95 mooseError(
"The MultiApp command line argument '",
97 "' sets a command line option.\nMultiApp command line arguments can only be " 98 "used for setting HIT parameters.");
104 else if (!begins_with_dash &&
105 pcrecpp::RE(
"(([^\\s\n\t[\\]\\/=#&:]+)?:)?((?:[^\\s\n\t[\\]=#&]+\\/" 106 ")?(?:[^\\s\n\t=#$'\"]+))=([^#]+)?")
107 .FullMatch(arg, &subapp_prefix, &subapp_name, &hit_path, &hit_value))
109 auto & entry = add_entry(hit_path);
110 if (subapp_prefix.size())
112 if (subapp_name.empty())
115 entry.subapp_name = subapp_name;
118 entry.value_separator =
"=";
119 entry.raw_args.push_back(arg);
120 entry.hit_param =
true;
121 has_value_accepting_entry =
false;
124 else if (
const auto find_equals = arg.find(
"="); find_equals != std::string::npos)
126 const auto begin = arg.substr(0, find_equals);
127 const auto end = arg.substr(find_equals + 1);
128 auto & entry = add_entry(
begin);
130 entry.value_separator =
"=";
131 entry.raw_args.push_back(arg);
132 has_value_accepting_entry =
false;
137 else if (std::regex_search(arg, std::regex(
"^\\-+[a-zA-Z]")))
139 auto & entry = add_entry(arg);
140 entry.raw_args.push_back(arg);
141 has_value_accepting_entry =
true;
149 auto & entry = add_entry(arg);
150 entry.raw_args.push_back(arg);
155 if (!has_value_accepting_entry)
157 std::stringstream
err;
158 err <<
"The command line argument '" << arg
159 <<
"' is not applied to an option and is not a HIT parameter.";
164 err <<
"\n\nDid you mean to combine this argument with the previous argument, such " 167 << *
_entries.back().value <<
" " << arg <<
"'\n";
177 entry.value_separator =
" ";
178 entry.raw_args.push_back(arg);
185 const std::list<CommandLine::Entry> &
188 mooseAssert(
hasParsed(),
"Has not parsed");
192 std::list<CommandLine::Entry> &
195 mooseAssert(
hasParsed(),
"Has not parsed");
201 std::unique_ptr<CommandLine>
203 const std::string & subapp_name,
204 const std::vector<std::string> & input_cli_args)
207 "Name for the subapp should begin with the multiapp");
209 std::vector<std::string> subapp_args;
213 for (
const auto & arg : input_cli_args)
220 if (entry.global || (entry.subapp_name && (*entry.subapp_name == multiapp_name ||
221 *entry.subapp_name == subapp_name)))
226 const std::string prefix = entry.global ?
":" :
"";
228 subapp_args.push_back(prefix + entry.name + *entry.value_separator + *entry.value);
233 subapp_args.insert(subapp_args.end(), entry.raw_args.begin(), entry.raw_args.end());
236 return std::make_unique<CommandLine>(subapp_args);
244 std::vector<std::string> params;
248 if (entry.hit_param && !entry.subapp_name)
250 mooseAssert(entry.value,
"Should have a value");
251 mooseAssert(entry.value_separator,
"Should have value separator");
252 mooseAssert(*entry.value_separator ==
"=",
"Should be an equals");
254 const std::string name_and_equals = entry.name + *entry.value_separator;
255 std::string arg = name_and_equals;
257 if (entry.value->empty())
268 catch (hit::ParseError &
err)
272 arg = name_and_equals +
"'" + *entry.value +
"'";
278 catch (hit::ParseError &
err)
280 mooseError(
"Failed to parse HIT in command line argument '", arg,
"'\n\n",
err.what());
285 params.push_back(arg);
300 std::map<std::string, std::string> switch_param_map;
301 for (
const auto & name_value_pair : params)
303 const auto &
name = name_value_pair.first;
304 if (
const auto metadata = params.queryCommandLineMetadata(
name))
307 auto & option = it_inserted_pair.first->second;
309 option.description = params.getDocString(
name);
310 option.metadata = *metadata;
313 for (
const auto & cli_switch : option.metadata.switches)
314 if (
const auto it_inserted_pair = switch_param_map.emplace(cli_switch,
name);
315 !it_inserted_pair.second)
317 it_inserted_pair.first->second,
320 "' both declare the command line switch '",
332 auto & entry = *entry_it;
333 mooseAssert(!entry.subapp_name,
"Should not be for a subapp");
336 #define trySetParameter(type) \ 337 if (!found && params.have_parameter<type>(name)) \ 339 static_assert(InputParameters::isValidCommandLineType<type>::value, "Not a supported value"); \ 340 auto & value = params.set<type>(name); \ 341 setCommandLineParam(entry_it, param, entry.name, value); \ 345 trySetParameter(std::string);
346 trySetParameter(std::vector<std::string>);
347 trySetParameter(
Real);
348 trySetParameter(
unsigned int);
349 trySetParameter(
int);
350 trySetParameter(
bool);
352 #undef trySetParameter 354 mooseAssert(found,
"Should have been found");
358 params.commandLineParamSet(
name, {});
361 if (param.metadata.global)
368 if (entry.value_separator && *entry.value_separator ==
"=")
370 mooseAssert(entry.raw_args.size() == 1,
"Should have one value");
375 else if (param.metadata.required)
377 "Missing required command-line parameter: ",
name,
"\nDoc string: ", param.description);
386 mooseAssert(
_entries.size() > 0,
"Does not have any entries");
389 const auto & command =
_entries.begin()->name;
390 return command.substr(command.find_last_of(
"/\\") + 1);
398 if (
name.find_first_of(
"/") != std::string::npos)
399 name =
name.substr(
name.find_first_of(
"/") + 1, std::string::npos);
408 std::size_t max_len = 0;
410 max_len =
std::max(max_len, name_option_pair.second.metadata.syntax.size());
412 const auto output_options = [
this, &max_len](
const bool global)
414 Moose::out << (global ?
"Global " :
"") <<
"Options:\n" << std::left;
417 const auto & option = name_option_pair.second;
418 if (option.metadata.syntax.empty() || option.metadata.global != global)
421 Moose::out <<
" " << std::setw(max_len + 2) << option.metadata.syntax << option.description
427 output_options(
false);
428 output_options(
true);
430 Moose::out <<
"Solver Options:\n" 431 <<
" See PETSc manual for details" << std::endl;
438 std::vector<std::string>
441 libmesh_parallel_only(comm);
443 std::vector<const Entry *> hit_params;
444 std::vector<std::size_t> use_count;
448 hit_params.push_back(&entry);
449 use_count.push_back(entry.used ? 1 : 0);
452 mooseAssert(comm.
verify(use_count.size()),
"Inconsistent HIT params across procs");
455 std::vector<std::string> unused;
457 if (use_count[i] == 0)
458 unused.push_back(hit_params[i]->raw_args[0]);
462 std::list<CommandLine::Entry>::const_iterator
467 mooseError(
"CommandLine::findCommandLineParam(): The parameter '",
469 "' is not a command line parameter");
472 const auto & param = find_param->second;
474 for (
const auto & search_switch : param.metadata.switches)
475 if (rit->name == search_switch)
476 return --(rit.base());
481 std::list<CommandLine::Entry>::iterator
484 const auto it = std::as_const(*this).findCommandLineParam(
name);
492 std::stringstream oss;
496 const auto q = (*entry.
value).find(
" ") != std::string::npos ?
"'" :
"";
bool _has_parsed
Whether or not the Parser has parsed yet.
std::string name(const ElemQuality q)
std::string getExecutableName() const
std::optional< std::string > value_separator
The string that separates the value, if a value exists (space or =)
bool beginsWith(const std::string &value, const std::string &begin_value)
std::list< Entry >::const_iterator findCommandLineParam(const std::string &name) const
std::string formatEntry(const Entry &entry) const
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Stores name/value pairs for each command line argument.
void printUsage() const
Print the usage info for this command line.
std::string name
The name, i.e, ["-foo=bar"] -> "-foo" or ["--foo", "bar"] -> "--foo".
auto max(const L &left, const R &right)
void addArgument(const std::string &arg)
Adds a single argument.
std::list< Entry > _entries
The parsed command line entries (arguments split into name value pairs) This is a list because it is ...
bool _command_line_params_populated
Whether or not command line parameters have been populated.
void populateCommandLineParams(InputParameters ¶ms)
Populates the command line input parameters from params.
Stores information pertaining to a command line InputParameter.
std::map< std::string, CommandLineParam > _command_line_params
The command line parameters, added by populateCommandLineParams()
std::vector< std::string > _argv
Storage for the raw argv.
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
const std::list< Entry > & getEntries() const
bool hasArgument(const std::string &arg) const
void setSinglePetscOption(const std::string &name, const std::string &value="", FEProblemBase *const problem=nullptr)
A wrapper function for dealing with different versions of PetscOptionsSetValue.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
void add_command_line_name(const std::string &name)
timpi_pure bool verify(const T &r) const
void removeArgument(const std::string &arg)
Removes an argument that must exist.
void parse()
Performs the parsing, which is the combining of arguments into [name, value] pairs.
std::unique_ptr< CommandLine > initSubAppCommandLine(const std::string &multiapp_name, const std::string &subapp_name, const std::vector< std::string > &input_cli_args)
Initializes a new CommandLine for a subapp with a MultiApp named multiapp_name and a subapp named sub...
std::string removeExtraWhitespace(const std::string &str)
Removes additional whitespace from a string.
std::vector< std::string > unusedHitParams(const Parallel::Communicator &comm) const
Returns the HIT command line arguments that are not used.
std::string stringJoin(const std::vector< std::string > &values, const std::string &separator=" ")
Concatenates value into a single string separated by separator.
std::optional< std::string > value
The value, i.e. ["-foo=bar"] -> "bar" or ["-foo"] -> empty, if any.
auto index_range(const T &sizable)
std::string getExecutableNameBase() const
void addArguments(int argc, char *argv[])
Adds arguments from raw argc and argv.
Result check(std::string requirements, const Registry &capabilities)
Checks if a set of requirements is satisified by the given capability registry.
std::string buildHitParams()