https://mooseframework.inl.gov
Classes | Public Types | Public Member Functions | Private Member Functions | Private Attributes | List of all members
CommandLine Class Reference

This class wraps provides and tracks access to command line parameters. More...

#include <CommandLine.h>

Classes

struct  CommandLineParam
 Stores information pertaining to a command line InputParameter. More...
 
struct  Entry
 Stores name/value pairs for each command line argument. More...
 

Public Types

using ArgumentType = InputParameters::CommandLineMetadata::ArgumentType
 

Public Member Functions

 CommandLine ()
 
 CommandLine (int argc, char *argv[])
 
 CommandLine (const std::vector< std::string > &args)
 
virtual ~CommandLine ()
 
void addArguments (int argc, char *argv[])
 Adds arguments from raw argc and argv. More...
 
void addArgument (const std::string &arg)
 Adds a single argument. More...
 
void addArguments (const std::vector< std::string > &args)
 Adds arguments from a vector. More...
 
bool hasArgument (const std::string &arg) const
 
void removeArgument (const std::string &arg)
 Removes an argument that must exist. More...
 
void parse ()
 Performs the parsing, which is the combining of arguments into [name, value] pairs. More...
 
bool hasParsed () const
 
std::unique_ptr< CommandLineinitSubAppCommandLine (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 subapp_name. More...
 
std::vector< std::string > buildHitParams ()
 
const std::vector< std::string > & getArguments ()
 
void populateCommandLineParams (InputParameters &params)
 Populates the command line input parameters from params. More...
 
auto begin () const
 
auto end () const
 
const std::list< Entry > & getEntries () const
 
std::string getExecutableName () const
 
std::string getExecutableNameBase () const
 
void printUsage () const
 Print the usage info for this command line. More...
 
std::vector< std::string > unusedHitParams (const Parallel::Communicator &comm) const
 Returns the HIT command line arguments that are not used. More...
 
std::list< Entry >::const_iterator findCommandLineParam (const std::string &name) const
 
std::string formatEntry (const Entry &entry) const
 
template<typename T >
void setCommandLineParam (std::list< CommandLine::Entry >::iterator entry_it, const CommandLineParam &param, const std::string &cli_switch, T &value)
 

Private Member Functions

std::list< Entry > & getEntries ()
 
template<typename T >
void setCommandLineParam (std::list< Entry >::iterator entry_it, const CommandLineParam &param, const std::string &cli_switch, T &value)
 Sets an InputParameters command line option at value. More...
 
std::list< Entry >::iterator findCommandLineParam (const std::string &name)
 

Private Attributes

std::vector< std::string > _argv
 Storage for the raw argv. More...
 
std::list< Entry_entries
 The parsed command line entries (arguments split into name value pairs) This is a list because it is necessary to combine Entry objects later on. More...
 
std::map< std::string, CommandLineParam_command_line_params
 The command line parameters, added by populateCommandLineParams() More...
 
bool _has_parsed = false
 Whether or not the Parser has parsed yet. More...
 
bool _command_line_params_populated = false
 Whether or not command line parameters have been populated. More...
 
bool _hit_params_built = false
 Whether or not the HIT parameters have been built (set as used) More...
 

Detailed Description

This class wraps provides and tracks access to command line parameters.

Definition at line 29 of file CommandLine.h.

Member Typedef Documentation

◆ ArgumentType

Definition at line 32 of file CommandLine.h.

Constructor & Destructor Documentation

◆ CommandLine() [1/3]

CommandLine::CommandLine ( )

Definition at line 27 of file CommandLine.C.

27 {}

◆ CommandLine() [2/3]

CommandLine::CommandLine ( int  argc,
char *  argv[] 
)

Definition at line 28 of file CommandLine.C.

28 { addArguments(argc, argv); }
void addArguments(int argc, char *argv[])
Adds arguments from raw argc and argv.
Definition: CommandLine.C:32

◆ CommandLine() [3/3]

CommandLine::CommandLine ( const std::vector< std::string > &  args)

Definition at line 29 of file CommandLine.C.

29 { addArguments(args); }
void addArguments(int argc, char *argv[])
Adds arguments from raw argc and argv.
Definition: CommandLine.C:32

◆ ~CommandLine()

CommandLine::~CommandLine ( )
virtual

Definition at line 199 of file CommandLine.C.

199 {}

Member Function Documentation

◆ addArgument()

void CommandLine::addArgument ( const std::string &  arg)

Adds a single argument.

Definition at line 39 of file CommandLine.C.

Referenced by addArguments().

40 {
41  mooseAssert(!hasParsed(), "Has already parsed");
42  _argv.push_back(arg);
43 }
std::vector< std::string > _argv
Storage for the raw argv.
Definition: CommandLine.h:229
bool hasParsed() const
Definition: CommandLine.h:105

◆ addArguments() [1/2]

void CommandLine::addArguments ( int  argc,
char *  argv[] 
)

Adds arguments from raw argc and argv.

Definition at line 32 of file CommandLine.C.

Referenced by CommandLine().

33 {
34  for (int i = 0; i < argc; i++)
35  addArgument(argv[i]);
36 }
void addArgument(const std::string &arg)
Adds a single argument.
Definition: CommandLine.C:39

◆ addArguments() [2/2]

void CommandLine::addArguments ( const std::vector< std::string > &  args)

Adds arguments from a vector.

Definition at line 46 of file CommandLine.C.

47 {
48  for (const auto & arg : args)
49  addArgument(arg);
50 }
void addArgument(const std::string &arg)
Adds a single argument.
Definition: CommandLine.C:39

◆ begin()

auto CommandLine::begin ( ) const
inline
Returns
An iterator to the beginning of the options

Definition at line 151 of file CommandLine.h.

Referenced by initSubAppCommandLine(), and parse().

151 { return _entries.begin(); }
std::list< Entry > _entries
The parsed command line entries (arguments split into name value pairs) This is a list because it is ...
Definition: CommandLine.h:233

◆ buildHitParams()

std::vector< std::string > CommandLine::buildHitParams ( )
Returns
The parsed HIT command line parameters per the command line arguments.

This will also mark all found HIT parameters as used.

Definition at line 256 of file CommandLine.C.

257 {
258  mooseAssert(!_hit_params_built, "Already built");
259  _hit_params_built = true;
260 
261  std::vector<std::string> params;
262 
263  // Collect all hit parameters that aren't for subapps
264  for (auto & entry : getEntries())
265  if (entry.hit_param && !entry.subapp_name)
266  {
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");
270 
271  const std::string name_and_equals = entry.name + *entry.value_separator;
272  std::string arg = name_and_equals;
273  // In the case of empty values, we want them to be empty to hit
274  if (entry.value->empty())
275  arg += "''";
276  else
277  arg += *entry.value;
278 
279  // We could have issues with bash eating strings, so the first try
280  // gives us a chance to wrap the value in quotes
281  try
282  {
283  hit::check("CLI_ARG", arg);
284  }
285  catch (hit::Error & err)
286  {
287  // bash might have eaten quotes around a hit string value or vector
288  // so try quoting after the "=" and reparse
289  arg = name_and_equals + "'" + *entry.value + "'";
290  try
291  {
292  hit::check("CLI_ARG", arg);
293  }
294  // At this point, we've failed to fix it
295  catch (hit::Error & err)
296  {
297  mooseError("Failed to parse HIT in command line argument '", arg, "'\n\n", err.what());
298  }
299  }
300 
301  // Append to the total output
302  params.push_back(arg);
303  // Consider this parameter used
304  entry.used = true;
305  }
306 
307  return params;
308 }
OStreamProxy err
bool _hit_params_built
Whether or not the HIT parameters have been built (set as used)
Definition: CommandLine.h:243
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:311
const std::list< Entry > & getEntries() const
Definition: CommandLine.C:186

◆ end()

auto CommandLine::end ( ) const
inline
Returns
An iterator to the end of the options

Definition at line 155 of file CommandLine.h.

Referenced by initSubAppCommandLine(), and parse().

155 { return _entries.end(); }
std::list< Entry > _entries
The parsed command line entries (arguments split into name value pairs) This is a list because it is ...
Definition: CommandLine.h:233

◆ findCommandLineParam() [1/2]

std::list< CommandLine::Entry >::const_iterator CommandLine::findCommandLineParam ( const std::string &  name) const
Returns
The entry iterator for the command line arguments for the command line input parameter with name name, if any.

Definition at line 480 of file CommandLine.C.

Referenced by initSubAppCommandLine(), and populateCommandLineParams().

481 {
482  const auto find_param = _command_line_params.find(name);
483  if (find_param == _command_line_params.end())
484  mooseError("CommandLine::findCommandLineParam(): The parameter '",
485  name,
486  "' is not a command line parameter");
487 
488  // Search for the last thing that matches a switch from this param
489  const auto & param = find_param->second;
490  for (auto rit = _entries.rbegin(); rit != _entries.rend(); ++rit)
491  for (const auto & search_switch : param.metadata.switches)
492  if (rit->name == search_switch)
493  return --(rit.base());
494 
495  return getEntries().end();
496 }
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:311
std::list< Entry > _entries
The parsed command line entries (arguments split into name value pairs) This is a list because it is ...
Definition: CommandLine.h:233
std::map< std::string, CommandLineParam > _command_line_params
The command line parameters, added by populateCommandLineParams()
Definition: CommandLine.h:236
const std::list< Entry > & getEntries() const
Definition: CommandLine.C:186

◆ findCommandLineParam() [2/2]

std::list< CommandLine::Entry >::iterator CommandLine::findCommandLineParam ( const std::string &  name)
private
Returns
The entry iterator for the command line arguments for the command line input parameter with name name, if any.

Definition at line 499 of file CommandLine.C.

500 {
501  const auto it = std::as_const(*this).findCommandLineParam(name);
502  // Easy way to go from a const iterator -> non-const iterator
503  return _entries.erase(it, it);
504 }
std::list< Entry > _entries
The parsed command line entries (arguments split into name value pairs) This is a list because it is ...
Definition: CommandLine.h:233

◆ formatEntry()

std::string CommandLine::formatEntry ( const Entry entry) const
Returns
A formatted representation of the given command line entry

Definition at line 507 of file CommandLine.C.

508 {
509  std::stringstream oss;
510  oss << entry.name;
511  if (entry.value)
512  {
513  const auto q = (*entry.value).find(" ") != std::string::npos ? "'" : "";
514  oss << *entry.value_separator << q << *entry.value << q;
515  }
516  return oss.str();
517 }
KOKKOS_INLINE_FUNCTION const T * find(const T &target, const T *const begin, const T *const end)
Find a value in an array.
Definition: KokkosUtils.h:40

◆ getArguments()

const std::vector<std::string>& CommandLine::getArguments ( )
inline
Returns
The raw argv arguments as a vector

Definition at line 138 of file CommandLine.h.

Referenced by Moose::createMooseApp(), and Moose::PetscSupport::petscSetupOutput().

138 { return _argv; }
std::vector< std::string > _argv
Storage for the raw argv.
Definition: CommandLine.h:229

◆ getEntries() [1/2]

const std::list< CommandLine::Entry > & CommandLine::getEntries ( ) const
Returns
The combined argument entries

Definition at line 186 of file CommandLine.C.

Referenced by buildHitParams(), findCommandLineParam(), initSubAppCommandLine(), and unusedHitParams().

187 {
188  mooseAssert(hasParsed(), "Has not parsed");
189  return _entries;
190 }
std::list< Entry > _entries
The parsed command line entries (arguments split into name value pairs) This is a list because it is ...
Definition: CommandLine.h:233
bool hasParsed() const
Definition: CommandLine.h:105

◆ getEntries() [2/2]

std::list< CommandLine::Entry > & CommandLine::getEntries ( )
private
Returns
The combined argument entries

Definition at line 193 of file CommandLine.C.

194 {
195  mooseAssert(hasParsed(), "Has not parsed");
196  return _entries;
197 }
std::list< Entry > _entries
The parsed command line entries (arguments split into name value pairs) This is a list because it is ...
Definition: CommandLine.h:233
bool hasParsed() const
Definition: CommandLine.h:105

◆ getExecutableName()

std::string CommandLine::getExecutableName ( ) const
Returns
The executable name.

Definition at line 401 of file CommandLine.C.

Referenced by getExecutableNameBase(), and printUsage().

402 {
403  mooseAssert(_entries.size() > 0, "Does not have any entries");
404 
405  // Grab the first item out of argv
406  const auto & command = _entries.begin()->name;
407  return command.substr(command.find_last_of("/\\") + 1);
408 }
std::list< Entry > _entries
The parsed command line entries (arguments split into name value pairs) This is a list because it is ...
Definition: CommandLine.h:233

◆ getExecutableNameBase()

std::string CommandLine::getExecutableNameBase ( ) const
Returns
The exectuable name base (the name without the -[opt,oprof,devel,dbg])

Definition at line 411 of file CommandLine.C.

412 {
413  auto name = getExecutableName();
414  name = name.substr(0, name.find_last_of("-"));
415  if (name.find_first_of("/") != std::string::npos)
416  name = name.substr(name.find_first_of("/") + 1, std::string::npos);
417  return name;
418 }
std::string name(const ElemQuality q)
std::string getExecutableName() const
Definition: CommandLine.C:401

◆ hasArgument()

bool CommandLine::hasArgument ( const std::string &  arg) const
Returns
Whether or not the raw argument arg is contained

Definition at line 53 of file CommandLine.C.

54 {
55  return std::find(_argv.begin(), _argv.end(), arg) != _argv.end();
56 }
KOKKOS_INLINE_FUNCTION const T * find(const T &target, const T *const begin, const T *const end)
Find a value in an array.
Definition: KokkosUtils.h:40
std::vector< std::string > _argv
Storage for the raw argv.
Definition: CommandLine.h:229

◆ hasParsed()

bool CommandLine::hasParsed ( ) const
inline
Returns
Whether or not the arguments have been parsed

Definition at line 105 of file CommandLine.h.

Referenced by addArgument(), getEntries(), parse(), and removeArgument().

105 { return _has_parsed; }
bool _has_parsed
Whether or not the Parser has parsed yet.
Definition: CommandLine.h:239

◆ initSubAppCommandLine()

std::unique_ptr< CommandLine > 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 subapp_name.

The arguments input_cli_args are the additional arguments to apply to the subapp, such as those that have been specified in the MultiApp params (cli_args param).

This will apply all global parameters from this parent application and all HIT CLI parameters that have the same.

The optional exclude_params is a set of InputParameters names (e.g. "recover", "test_checkpoint_half_transient") whose corresponding command-line entries will NOT be propagated to the sub-app, even if they are marked global. Entries are matched by the parameter name as registered in MooseApp::validParams().

Definition at line 202 of file CommandLine.C.

206 {
207  mooseAssert(MooseUtils::beginsWith(subapp_name, multiapp_name),
208  "Name for the subapp should begin with the multiapp");
209 
210  std::vector<std::string> subapp_args;
211 
212  // Start with the arguments from the input file; we want these to take the
213  // lowest priority so we put them first. Also trim extra whitespace
214  for (const auto & arg : input_cli_args)
215  subapp_args.push_back(MooseUtils::removeExtraWhitespace(arg));
216 
217  // Resolve the excluded parameter names to their Entry pointers so we can
218  // efficiently skip them in the propagation loop below. We skip entries for
219  // which findCommandLineParam returns end() (param registered but not present).
220  std::set<const Entry *> skip_entries;
221  for (const auto & param_name : exclude_params)
222  {
223  auto it = findCommandLineParam(param_name);
224  if (it != getEntries().end())
225  skip_entries.insert(&*it);
226  }
227 
228  // Pull out all of the arguments that are relevant to this multiapp from the parent
229  // Note that the 0th argument of the main app, i.e., the name used to invoke the program,
230  // is neither a global entry nor a subapp entry and, as such, won't be passed on
231  for (auto & entry : as_range(getEntries().begin(), getEntries().end()))
232  if (entry.global || (entry.subapp_name && (*entry.subapp_name == multiapp_name ||
233  *entry.subapp_name == subapp_name)))
234  {
235  // Skip entries that the caller has asked to suppress from propagation
236  if (skip_entries.count(&entry))
237  continue;
238 
239  if (entry.hit_param)
240  {
241  // Append : to the beginning if this is global and should be passed to all
242  const std::string prefix = entry.global ? ":" : "";
243  // Apply the param, but without the subapp name
244  subapp_args.push_back(prefix + entry.name + *entry.value_separator + *entry.value);
245  // Mark this entry as used as a child has consumed it
246  entry.used = true;
247  }
248  else
249  subapp_args.insert(subapp_args.end(), entry.raw_args.begin(), entry.raw_args.end());
250  }
251 
252  return std::make_unique<CommandLine>(subapp_args);
253 }
bool beginsWith(const std::string &value, const std::string &begin_value)
Definition: MooseUtils.C:955
std::list< Entry >::const_iterator findCommandLineParam(const std::string &name) const
Definition: CommandLine.C:480
std::string removeExtraWhitespace(const std::string &input)
Definition: MooseUtils.C:225
auto end() const
Definition: CommandLine.h:155
auto begin() const
Definition: CommandLine.h:151
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
const std::list< Entry > & getEntries() const
Definition: CommandLine.C:186

◆ parse()

void CommandLine::parse ( )

Performs the parsing, which is the combining of arguments into [name, value] pairs.

Must be called before extracing anything from the CommandLine.

Definition at line 69 of file CommandLine.C.

Referenced by AppFactory::createAppShared(), and Moose::createMooseApp().

70 {
71  mooseAssert(!hasParsed(), "Has already parsed");
72  mooseAssert(_entries.empty(), "Should be empty");
73 
74  // Whether or not we have a entry that accepts values
75  bool has_value_accepting_entry = false;
76 
77  // Helper for adding an entry
78  auto add_entry = [this](const auto & name) -> Entry &
79  {
80  auto & entry = _entries.emplace_back();
81  entry.name = name;
82  return entry;
83  };
84 
85  // Work through each argument
86  for (const auto i : index_range(_argv))
87  {
88  const auto & arg = _argv[i];
89  const auto begins_with_dash = MooseUtils::beginsWith(arg, "-");
90  std::string subapp_prefix, subapp_name, hit_path, hit_value;
91 
92  // MultiApp syntax with a non-hit option
93  if (!begins_with_dash && std::regex_search(arg, std::regex("^(([^\\s\n\t[\\]\\/=#&:]+):)[-]")))
94  {
95  mooseError("The MultiApp command line argument '",
96  arg,
97  "' sets a command line option.\nMultiApp command line arguments can only be "
98  "used for setting HIT parameters.");
99  }
100  // Match HIT CLI syntax (including for multiapps with the prefix)
101  // For subapp hit cli syntax (i.e, <subname>:<value)), we will store the
102  // subapp names to be stripped away in initSubAppCommandLine() as they
103  // are passed down
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))
108  {
109  auto & entry = add_entry(hit_path);
110  if (subapp_prefix.size())
111  {
112  if (subapp_name.empty()) // :param=value; means apply to all
113  entry.global = true;
114  else
115  entry.subapp_name = subapp_name;
116  }
117  entry.value = MooseUtils::removeExtraWhitespace(hit_value);
118  entry.value_separator = "=";
119  entry.raw_args.push_back(arg);
120  entry.hit_param = true;
121  has_value_accepting_entry = false;
122  }
123  // Has an = sign in it, so we have a name=value (non-HIT)
124  else if (const auto find_equals = arg.find("="); find_equals != std::string::npos)
125  {
126  const auto begin = arg.substr(0, find_equals);
127  const auto end = arg.substr(find_equals + 1);
128  auto & entry = add_entry(begin);
129  entry.value = MooseUtils::removeExtraWhitespace(end);
130  entry.value_separator = "=";
131  entry.raw_args.push_back(arg);
132  has_value_accepting_entry = false;
133  }
134  // Begins with dash(es) and a character, so a new argument. We pass on
135  // everything else that starts with a dash as a value, so the error
136  // will be associated with the value before it
137  else if (std::regex_search(arg, std::regex("^\\-+[a-zA-Z]")))
138  {
139  auto & entry = add_entry(arg);
140  entry.raw_args.push_back(arg);
141  has_value_accepting_entry = true;
142  }
143  // Should be tagging on a value to the previous argument
144  else
145  {
146  // First one is the executable
147  if (i == 0)
148  {
149  auto & entry = add_entry(arg);
150  entry.raw_args.push_back(arg);
151  continue;
152  }
153 
154  // Throw an error if this a value and we don't have anything to apply it to
155  if (!has_value_accepting_entry)
156  {
157  std::stringstream err;
158  err << "The command line argument '" << arg
159  << "' is not applied to an option and is not a HIT parameter.";
160  // Maybe they meant to apply it to the previous thing
161  // Example: "-i foo.i bar.i" would suggest "-i 'foo.i bar.i'"
162  if (i > 0 && _entries.back().value)
163  {
164  err << "\n\nDid you mean to combine this argument with the previous argument, such "
165  "as:\n\n "
166  << _entries.back().name << *_entries.back().value_separator << "'"
167  << *_entries.back().value << " " << arg << "'\n";
168  }
169  mooseError(err.str());
170  }
171 
172  auto & entry = _entries.back();
173  if (entry.value)
174  *entry.value += " " + MooseUtils::removeExtraWhitespace(arg);
175  else
176  entry.value = MooseUtils::removeExtraWhitespace(arg);
177  entry.value_separator = " ";
178  entry.raw_args.push_back(arg);
179  }
180  }
181 
182  _has_parsed = true;
183 }
bool _has_parsed
Whether or not the Parser has parsed yet.
Definition: CommandLine.h:239
std::string name(const ElemQuality q)
OStreamProxy err
bool beginsWith(const std::string &value, const std::string &begin_value)
Definition: MooseUtils.C:955
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:311
std::string removeExtraWhitespace(const std::string &input)
Definition: MooseUtils.C:225
auto end() const
Definition: CommandLine.h:155
std::list< Entry > _entries
The parsed command line entries (arguments split into name value pairs) This is a list because it is ...
Definition: CommandLine.h:233
auto begin() const
Definition: CommandLine.h:151
std::vector< std::string > _argv
Storage for the raw argv.
Definition: CommandLine.h:229
bool hasParsed() const
Definition: CommandLine.h:105
auto index_range(const T &sizable)

◆ populateCommandLineParams()

void CommandLine::populateCommandLineParams ( InputParameters params)

Populates the command line input parameters from params.

Will throw errors when conversions fail and may combine entires in _entries if some are found that can be combined.

Definition at line 311 of file CommandLine.C.

Referenced by AppFactory::createAppShared(), and Moose::createMooseApp().

312 {
313  mooseAssert(!_command_line_params_populated, "Already populated");
314 
315  // Set the metadata for each command line parameter
316  // We set this separately so that it can be used later to print usage
317  std::map<std::string, std::string> switch_param_map;
318  for (const auto & name_value_pair : params)
319  {
320  const auto & name = name_value_pair.first;
321  if (const auto metadata = params.queryCommandLineMetadata(name))
322  {
323  auto it_inserted_pair = _command_line_params.emplace(name, CommandLineParam());
324  auto & option = it_inserted_pair.first->second;
325 
326  option.description = params.getDocString(name);
327  option.metadata = *metadata;
328 
329  // Make sure that one switch isn't specified for multiple parameters
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)
333  mooseError("The command line options '",
334  it_inserted_pair.first->second,
335  "' and '",
336  name,
337  "' both declare the command line switch '",
338  cli_switch,
339  "'");
340  }
341  }
342 
343  // Set each paramter that we have a value for
344  for (const auto & [name, param] : _command_line_params)
345  {
346  auto entry_it = findCommandLineParam(name);
347  if (entry_it != _entries.end())
348  {
349  auto & entry = *entry_it;
350  mooseAssert(!entry.subapp_name, "Should not be for a subapp");
351 
352  bool found = false;
353 #define trySetParameter(type) \
354  if (!found && params.have_parameter<type>(name)) \
355  { \
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); \
359  found = true; \
360  }
361 
362  trySetParameter(std::string);
363  trySetParameter(std::vector<std::string>);
364  trySetParameter(Real);
365  trySetParameter(unsigned int);
366  trySetParameter(int);
367  trySetParameter(bool);
368  trySetParameter(MooseEnum);
369 #undef trySetParameter
370 
371  mooseAssert(found, "Should have been found");
372 
373  // If we found this parameter, that means we set it and we should mark in the
374  // InputParameters that it is set so that isParamSetByUser() returns true for this param
375  params.commandLineParamSet(name, {});
376 
377  // If this parameter is global, mark its entry as global
378  if (param.metadata.global)
379  entry.global = true;
380 
381  // If the arg is of the form "--key=value", PETSc will recognize it as an unused
382  // argument. That is, setting "--key" as a known command line argument is not
383  // sufficient for PETSc to consider "--key=value" as known. Thus, we explicitly
384  // add "--key=value" args as known when we come across them.
385  if (entry.value_separator && *entry.value_separator == "=")
386  {
387  mooseAssert(entry.raw_args.size() == 1, "Should have one value");
388  libMesh::add_command_line_name(entry.raw_args[0]);
389  }
390  }
391  // If we didn't find it and it is required, we need to error
392  else if (param.metadata.required)
393  mooseError(
394  "Missing required command-line parameter: ", name, "\nDoc string: ", param.description);
395  }
396 
398 }
std::string name(const ElemQuality q)
std::list< Entry >::const_iterator findCommandLineParam(const std::string &name) const
Definition: CommandLine.C:480
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:311
std::list< Entry > _entries
The parsed command line entries (arguments split into name value pairs) This is a list because it is ...
Definition: CommandLine.h:233
bool _command_line_params_populated
Whether or not command line parameters have been populated.
Definition: CommandLine.h:241
std::map< std::string, CommandLineParam > _command_line_params
The command line parameters, added by populateCommandLineParams()
Definition: CommandLine.h:236
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Definition: MooseEnum.h:54
void add_command_line_name(const std::string &name)

◆ printUsage()

void CommandLine::printUsage ( ) const

Print the usage info for this command line.

Definition at line 421 of file CommandLine.C.

422 {
423  Moose::out << "Usage: " << getExecutableName() << " [<options>]\n\n";
424 
425  std::size_t max_len = 0;
426  for (const auto & name_option_pair : _command_line_params)
427  max_len = std::max(max_len, name_option_pair.second.metadata.syntax.size());
428 
429  const auto output_options = [this, &max_len](const bool global)
430  {
431  Moose::out << (global ? "Global " : "") << "Options:\n" << std::left;
432  for (const auto & name_option_pair : _command_line_params)
433  {
434  const auto & option = name_option_pair.second;
435  if (option.metadata.syntax.empty() || option.metadata.global != global)
436  continue;
437 
438  Moose::out << " " << std::setw(max_len + 2) << option.metadata.syntax << option.description
439  << "\n";
440  }
441  Moose::out << "\n";
442  };
443 
444  output_options(false);
445  output_options(true);
446 
447  Moose::out << "Solver Options:\n"
448  << " See PETSc manual for details" << std::endl;
449 
450  // If we get here, we are not running a simulation and should silence petsc's unused options
451  // warning
452  Moose::PetscSupport::setSinglePetscOption("-options_left", "0");
453 }
std::string getExecutableName() const
Definition: CommandLine.C:401
auto max(const L &left, const R &right)
std::map< std::string, CommandLineParam > _command_line_params
The command line parameters, added by populateCommandLineParams()
Definition: CommandLine.h:236
void setSinglePetscOption(const std::string &name, const std::string &value="", FEProblemBase *const problem=nullptr)
A wrapper function for dealing with different versions of PetscOptionsSetValue.

◆ removeArgument()

void CommandLine::removeArgument ( const std::string &  arg)

Removes an argument that must exist.

Definition at line 59 of file CommandLine.C.

60 {
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");
65  _argv.erase(it);
66 }
KOKKOS_INLINE_FUNCTION const T * find(const T &target, const T *const begin, const T *const end)
Find a value in an array.
Definition: KokkosUtils.h:40
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:311
std::vector< std::string > _argv
Storage for the raw argv.
Definition: CommandLine.h:229
bool hasParsed() const
Definition: CommandLine.h:105

◆ setCommandLineParam() [1/2]

template<typename T >
void CommandLine::setCommandLineParam ( std::list< Entry >::iterator  entry_it,
const CommandLineParam param,
const std::string &  cli_switch,
T &  value 
)
private

Sets an InputParameters command line option at value.

Will report an error if string -> value conversions fail or if the parameter requires a value and one was not found.

Parameters
entry_itIterator to the Entry object that we're extracting from
paramThe internal metadata for the command line parameter
cli_switchThe command line switch for the parameter (-t, –timing, etc)
valueThe value that we want to fill into

◆ setCommandLineParam() [2/2]

template<typename T >
void CommandLine::setCommandLineParam ( std::list< CommandLine::Entry >::iterator  entry_it,
const CommandLineParam param,
const std::string &  cli_switch,
T &  value 
)

Definition at line 248 of file CommandLine.h.

252 {
253  auto & entry = *entry_it;
254  const auto required = param.metadata.argument_type == ArgumentType::REQUIRED;
255 
256  // Mark this entry as used
257  entry.used = true;
258 
259  // Option doesn't have any arguments (boolean)
260  if constexpr (std::is_same_v<bool, T>)
261  {
262  mooseAssert(param.metadata.argument_type == ArgumentType::NONE, "Incorrect argument type");
263 
264  if (entry.value)
265  mooseError("The command line option '",
266  cli_switch,
267  "' is a boolean and does not support a value but the value '",
268  *entry.value,
269  "' was provided.\nDoc string: ",
270  param.description);
271  value = true;
272  }
273  // Option has arguments
274  else
275  {
276  mooseAssert(param.metadata.argument_type != ArgumentType::NONE, "Incorrect argument type");
277 
278  // Helper for setting a value depending on its type and also throwing a useful
279  // error when the conversion fails
280  const auto set_value = [&cli_switch](const std::string & from, auto & value)
281  {
282  using type = typename std::remove_reference<decltype(value)>::type;
283 
284  // Keep track of and change the throw on error characteristics so that
285  // we can catch parsing errors for the argument
286  const auto throw_on_error_orig = Moose::_throw_on_error;
287  Moose::_throw_on_error = true;
288 
289  try
290  {
291  if constexpr (std::is_same_v<type, std::string> || std::is_same_v<type, MooseEnum>)
292  value = from;
293  else
294  value = MooseUtils::convert<type>(from, true);
295  }
296  catch (std::exception & e)
297  {
298  Moose::_throw_on_error = throw_on_error_orig;
299  mooseError("While parsing command line option '",
300  cli_switch,
301  "' with value '",
302  from,
303  "':\n\n",
304  e.what());
305  }
306 
307  Moose::_throw_on_error = throw_on_error_orig;
308  };
309 
310  // If a value doesn't exist, check the next argument to see if it
311  // would work. This is needed for when we have argument values that
312  // have = signs that get split. For example:
313  // "--required-capabilities 'petsc>=3.11'" would get split into:
314  // - "--required-capabilities" with no value
315  // - "petsc>" with value "3.11"
316  // which we want to re-combine into
317  // - "--required-capabilities" with value "petsc>=3.11"
318  if (!entry.value)
319  {
320  auto next_entry_it = std::next(entry_it);
321  if (next_entry_it != _entries.end())
322  {
323  const auto & next_entry = *next_entry_it;
324  if (!next_entry.used && // isn't already used
325  (required || !next_entry.hit_param) && // if required, get the last value. if not, get
326  // it if it's not a hit param
327  !MooseUtils::beginsWith(next_entry.name, "-") && // doesn't start with a -
328  next_entry.value_separator && // has a separator
329  *next_entry.value_separator == "=" && // that separator is =
330  next_entry.value) // and has a value after the =
331  {
332  const auto & next_entry = *next_entry_it;
333  // Merge with the next Entry object and remove said next object
334  entry.value = next_entry.name + *next_entry.value_separator + *next_entry.value;
335  entry.value_separator = " ";
336  entry.raw_args.insert(
337  entry.raw_args.end(), next_entry.raw_args.begin(), next_entry.raw_args.end());
338  _entries.erase(next_entry_it);
339  }
340  }
341  }
342 
343  // If we have a value, set the parameter to it
344  if (entry.value)
345  {
346  // For vector<string>, we need to unpack the values
347  if constexpr (std::is_same_v<T, std::vector<std::string>>)
348  {
349  std::vector<std::string> split_values;
350  MooseUtils::tokenize(*entry.value, split_values, 1, " ");
351  value.resize(split_values.size());
352  for (const auto i : index_range(split_values))
353  set_value(split_values[i], value[i]);
354  }
355  // For everything else, we can set them directly
356  else
357  set_value(*entry.value, value);
358  }
359  // No value, but one is required
360  else if (param.metadata.argument_type == ArgumentType::REQUIRED)
361  mooseError("The command line option '",
362  cli_switch,
363  "' requires a value and one was not provided.\nDoc string: ",
364  param.description);
365  }
366 }
void tokenize(const std::string &str, std::vector< T > &elements, unsigned int min_len=1, const std::string &delims="/")
This function will split the passed in string on a set of delimiters appending the substrings to the ...
bool beginsWith(const std::string &value, const std::string &begin_value)
Definition: MooseUtils.C:955
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:311
std::list< Entry > _entries
The parsed command line entries (arguments split into name value pairs) This is a list because it is ...
Definition: CommandLine.h:233
Real value(unsigned n, unsigned alpha, unsigned beta, Real x)
bool _throw_on_error
Variable to turn on exceptions during mooseError(), should only be used within MOOSE unit tests or wh...
Definition: Moose.C:844
auto index_range(const T &sizable)

◆ unusedHitParams()

std::vector< std::string > CommandLine::unusedHitParams ( const Parallel::Communicator comm) const

Returns the HIT command line arguments that are not used.

The HIT command line arguments are considered used when they are accumulated in buildHitParams().

The commmunicator is needed because we need to sync this in parallel due to the fact that sub apps could only be created on a subset of processors.

Definition at line 456 of file CommandLine.C.

457 {
458  libmesh_parallel_only(comm);
459 
460  std::vector<const Entry *> hit_params;
461  std::vector<std::size_t> use_count;
462  for (const auto & entry : getEntries())
463  if (entry.hit_param)
464  {
465  hit_params.push_back(&entry);
466  use_count.push_back(entry.used ? 1 : 0);
467  }
468 
469  mooseAssert(comm.verify(use_count.size()), "Inconsistent HIT params across procs");
470  comm.sum(use_count);
471 
472  std::vector<std::string> unused;
473  for (const auto i : index_range(use_count))
474  if (use_count[i] == 0)
475  unused.push_back(hit_params[i]->raw_args[0]);
476  return unused;
477 }
const std::list< Entry > & getEntries() const
Definition: CommandLine.C:186
timpi_pure bool verify(const T &r) const
auto index_range(const T &sizable)

Member Data Documentation

◆ _argv

std::vector<std::string> CommandLine::_argv
private

Storage for the raw argv.

Definition at line 229 of file CommandLine.h.

Referenced by addArgument(), getArguments(), hasArgument(), parse(), and removeArgument().

◆ _command_line_params

std::map<std::string, CommandLineParam> CommandLine::_command_line_params
private

The command line parameters, added by populateCommandLineParams()

Definition at line 236 of file CommandLine.h.

Referenced by findCommandLineParam(), populateCommandLineParams(), and printUsage().

◆ _command_line_params_populated

bool CommandLine::_command_line_params_populated = false
private

Whether or not command line parameters have been populated.

Definition at line 241 of file CommandLine.h.

Referenced by populateCommandLineParams().

◆ _entries

std::list<Entry> CommandLine::_entries
private

The parsed command line entries (arguments split into name value pairs) This is a list because it is necessary to combine Entry objects later on.

Definition at line 233 of file CommandLine.h.

Referenced by begin(), end(), findCommandLineParam(), getEntries(), getExecutableName(), parse(), populateCommandLineParams(), and setCommandLineParam().

◆ _has_parsed

bool CommandLine::_has_parsed = false
private

Whether or not the Parser has parsed yet.

Definition at line 239 of file CommandLine.h.

Referenced by hasParsed(), and parse().

◆ _hit_params_built

bool CommandLine::_hit_params_built = false
private

Whether or not the HIT parameters have been built (set as used)

Definition at line 243 of file CommandLine.h.

Referenced by buildHitParams().


The documentation for this class was generated from the following files: