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");
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,
205 const std::set<std::string> & exclude_params)
208 "Name for the subapp should begin with the multiapp");
210 std::vector<std::string> subapp_args;
214 for (
const auto & arg : input_cli_args)
220 std::set<const Entry *> skip_entries;
221 for (
const auto & param_name : exclude_params)
225 skip_entries.insert(&*it);
232 if (entry.global || (entry.subapp_name && (*entry.subapp_name == multiapp_name ||
233 *entry.subapp_name == subapp_name)))
236 if (skip_entries.count(&entry))
242 const std::string prefix = entry.global ?
":" :
"";
244 subapp_args.push_back(prefix + entry.name + *entry.value_separator + *entry.value);
249 subapp_args.insert(subapp_args.end(), entry.raw_args.begin(), entry.raw_args.end());
252 return std::make_unique<CommandLine>(subapp_args);
255 std::vector<std::string>
261 std::vector<std::string> params;
265 if (entry.hit_param && !entry.subapp_name)
267 mooseAssert(entry.value,
"Should have a value");
268 mooseAssert(entry.value_separator,
"Should have value separator");
269 mooseAssert(*entry.value_separator ==
"=",
"Should be an equals");
271 const std::string name_and_equals = entry.name + *entry.value_separator;
272 std::string arg = name_and_equals;
274 if (entry.value->empty())
283 hit::check(
"CLI_ARG", arg);
285 catch (hit::Error &
err)
289 arg = name_and_equals +
"'" + *entry.value +
"'";
292 hit::check(
"CLI_ARG", arg);
295 catch (hit::Error &
err)
297 mooseError(
"Failed to parse HIT in command line argument '", arg,
"'\n\n",
err.what());
302 params.push_back(arg);
317 std::map<std::string, std::string> switch_param_map;
318 for (
const auto & name_value_pair : params)
320 const auto &
name = name_value_pair.first;
321 if (
const auto metadata = params.queryCommandLineMetadata(
name))
324 auto & option = it_inserted_pair.first->second;
326 option.description = params.getDocString(
name);
327 option.metadata = *metadata;
330 for (
const auto & cli_switch : option.metadata.switches)
331 if (
const auto it_inserted_pair = switch_param_map.emplace(cli_switch,
name);
332 !it_inserted_pair.second)
334 it_inserted_pair.first->second,
337 "' both declare the command line switch '",
349 auto & entry = *entry_it;
350 mooseAssert(!entry.subapp_name,
"Should not be for a subapp");
353 #define trySetParameter(type) \ 354 if (!found && params.have_parameter<type>(name)) \ 356 static_assert(InputParameters::isValidCommandLineType<type>::value, "Not a supported value"); \ 357 auto & value = params.set<type>(name); \ 358 setCommandLineParam(entry_it, param, entry.name, value); \ 362 trySetParameter(std::string);
363 trySetParameter(std::vector<std::string>);
364 trySetParameter(
Real);
365 trySetParameter(
unsigned int);
366 trySetParameter(
int);
367 trySetParameter(
bool);
369 #undef trySetParameter 371 mooseAssert(found,
"Should have been found");
375 params.commandLineParamSet(
name, {});
378 if (param.metadata.global)
385 if (entry.value_separator && *entry.value_separator ==
"=")
387 mooseAssert(entry.raw_args.size() == 1,
"Should have one value");
392 else if (param.metadata.required)
394 "Missing required command-line parameter: ",
name,
"\nDoc string: ", param.description);
403 mooseAssert(
_entries.size() > 0,
"Does not have any entries");
406 const auto & command =
_entries.begin()->name;
407 return command.substr(command.find_last_of(
"/\\") + 1);
415 if (
name.find_first_of(
"/") != std::string::npos)
416 name =
name.substr(
name.find_first_of(
"/") + 1, std::string::npos);
425 std::size_t max_len = 0;
427 max_len =
std::max(max_len, name_option_pair.second.metadata.syntax.size());
429 const auto output_options = [
this, &max_len](
const bool global)
431 Moose::out << (global ?
"Global " :
"") <<
"Options:\n" << std::left;
434 const auto & option = name_option_pair.second;
435 if (option.metadata.syntax.empty() || option.metadata.global != global)
438 Moose::out <<
" " << std::setw(max_len + 2) << option.metadata.syntax << option.description
444 output_options(
false);
445 output_options(
true);
447 Moose::out <<
"Solver Options:\n" 448 <<
" See PETSc manual for details" << std::endl;
455 std::vector<std::string>
458 libmesh_parallel_only(comm);
460 std::vector<const Entry *> hit_params;
461 std::vector<std::size_t> use_count;
465 hit_params.push_back(&entry);
466 use_count.push_back(entry.used ? 1 : 0);
469 mooseAssert(comm.
verify(use_count.size()),
"Inconsistent HIT params across procs");
472 std::vector<std::string> unused;
474 if (use_count[i] == 0)
475 unused.push_back(hit_params[i]->raw_args[0]);
479 std::list<CommandLine::Entry>::const_iterator
484 mooseError(
"CommandLine::findCommandLineParam(): The parameter '",
486 "' is not a command line parameter");
489 const auto & param = find_param->second;
491 for (
const auto & search_switch : param.metadata.switches)
492 if (rit->name == search_switch)
493 return --(rit.base());
498 std::list<CommandLine::Entry>::iterator
501 const auto it = std::as_const(*this).findCommandLineParam(
name);
509 std::stringstream oss;
513 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)
bool _hit_params_built
Whether or not the HIT parameters have been built (set as used)
KOKKOS_INLINE_FUNCTION const T * find(const T &target, const T *const begin, const T *const end)
Find a value in an array.
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.
std::vector< std::string > buildHitParams()
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".
std::string removeExtraWhitespace(const std::string &input)
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
std::unique_ptr< CommandLine > initSubAppCommandLine(const std::string &multiapp_name, const std::string &subapp_name, const std::vector< std::string > &input_cli_args, const std::set< std::string > &exclude_params={})
Initializes a new CommandLine for a subapp with a MultiApp named multiapp_name and a subapp named sub...
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::vector< std::string > unusedHitParams(const Parallel::Communicator &comm) const
Returns the HIT command line arguments that are not used.
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.