mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: add -verbose support into argList
- similar to -dry-run handling, can be interrogated from argList,
which makes it simpler to add into utilities.
- support multiple uses of -dry-run and -verbose to increase the
level. For example, could have
someApplication -verbose -verbose
and inside of the application:
if (args.verbose() > 2) ...
BUG: error with empty distributed roots specification (fixes #2196)
- previously used the size of distributed roots to transmit if the
case was running in distributed mode, but this behaves rather poorly
with bad input. Specifically, the following questionable setup:
distributed true;
roots ( /*none*/ );
Now transmit the ParRunControl distributed() value instead,
and also emit a gentle warning for the user:
WARNING: running distributed but did not specify roots!
This commit is contained in:
@ -28,6 +28,7 @@ License
|
||||
|
||||
#include "argList.H"
|
||||
#include "OSspecific.H"
|
||||
#include "Switch.H"
|
||||
#include "clock.H"
|
||||
#include "dictionary.H"
|
||||
#include "IOobject.H"
|
||||
@ -110,7 +111,7 @@ Foam::argList::initValidTables::initValidTables()
|
||||
(
|
||||
"opt-switch",
|
||||
"name=val",
|
||||
"Specify the value of a registered optimisation switch (int/bool)."
|
||||
"Specify the value of a registered optimisation switch."
|
||||
" Default is 1 if the value is omitted."
|
||||
" (Can be used multiple times)",
|
||||
true // advanced option
|
||||
@ -326,7 +327,7 @@ void Foam::argList::addBoolOption
|
||||
bool advanced
|
||||
)
|
||||
{
|
||||
addOption(optName, "", usage, advanced);
|
||||
argList::addOption(optName, "", usage, advanced);
|
||||
}
|
||||
|
||||
|
||||
@ -455,7 +456,17 @@ void Foam::argList::addDryRunOption
|
||||
bool advanced
|
||||
)
|
||||
{
|
||||
addOption("dry-run", "", usage, advanced);
|
||||
argList::addBoolOption("dry-run", usage, advanced);
|
||||
}
|
||||
|
||||
|
||||
void Foam::argList::addVerboseOption
|
||||
(
|
||||
const string& usage,
|
||||
bool advanced
|
||||
)
|
||||
{
|
||||
argList::addBoolOption("verbose", usage, advanced);
|
||||
}
|
||||
|
||||
|
||||
@ -469,7 +480,7 @@ void Foam::argList::noFunctionObjects(bool addWithOption)
|
||||
|
||||
if (addWithOption)
|
||||
{
|
||||
addBoolOption
|
||||
argList::addBoolOption
|
||||
(
|
||||
"withFunctionObjects",
|
||||
"Execute functionObjects",
|
||||
@ -487,7 +498,7 @@ void Foam::argList::noJobInfo()
|
||||
|
||||
void Foam::argList::noLibs()
|
||||
{
|
||||
addBoolOption
|
||||
argList::addBoolOption
|
||||
(
|
||||
"no-libs",
|
||||
"Disable use of the controlDict libs entry",
|
||||
@ -768,11 +779,6 @@ void Foam::argList::setCasePaths()
|
||||
|
||||
// Executable name, unless already present in the environment
|
||||
setEnv("FOAM_EXECUTABLE", executable_, false);
|
||||
|
||||
if (validOptions.found("dry-run") && options_.found("dry-run"))
|
||||
{
|
||||
runControl_.dryRun(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -847,6 +853,9 @@ Foam::argList::argList
|
||||
// Set executable name immediately - useful when emitting errors.
|
||||
executable_ = fileName(args_[0]).name();
|
||||
|
||||
// Count -dry-run and -verbose switches
|
||||
int numDryRun = 0, numVerbose = 0;
|
||||
|
||||
// Check arguments and options, argv[0] was already handled
|
||||
int nArgs = 1;
|
||||
for (int argi = 1; argi < args_.size(); ++argi)
|
||||
@ -862,15 +871,31 @@ Foam::argList::argList
|
||||
{
|
||||
Warning
|
||||
<< "Ignoring lone '-' on the command-line" << endl;
|
||||
continue;
|
||||
}
|
||||
else if
|
||||
|
||||
// Option known and expects an argument?
|
||||
// - use Switch for a tri-state
|
||||
// True : known option, expects a parameter
|
||||
// False : known option, no parameter
|
||||
// bad() : unknown option
|
||||
|
||||
Switch wantArg(Switch::INVALID);
|
||||
auto optIter = validOptions.cfind(optName);
|
||||
if
|
||||
(
|
||||
validOptions.lookup(optName, "").size()
|
||||
|| validParOptions.lookup(optName, "").size()
|
||||
optIter.found()
|
||||
|| (optIter = validParOptions.cfind(optName)).found()
|
||||
)
|
||||
{
|
||||
// If the option is known to require an argument,
|
||||
// get it or emit a FatalError.
|
||||
wantArg = !optIter.val().empty();
|
||||
}
|
||||
|
||||
|
||||
if (wantArg)
|
||||
{
|
||||
// Known option and expects a parameter
|
||||
// - get it or emit a FatalError.
|
||||
|
||||
++argi;
|
||||
if (argi >= args_.size())
|
||||
@ -883,12 +908,16 @@ Foam::argList::argList
|
||||
<< "See '" << executable_ << " -help' for usage"
|
||||
<< nl << nl;
|
||||
|
||||
Pstream::exit(1); // works for serial and parallel
|
||||
Pstream::exit(1); // works for serial and parallel
|
||||
}
|
||||
|
||||
commandLine_ += ' ';
|
||||
commandLine_ += args_[argi];
|
||||
|
||||
//
|
||||
// Special handling of these options
|
||||
//
|
||||
|
||||
if (strcmp(optName, "lib") == 0)
|
||||
{
|
||||
// The '-lib' option:
|
||||
@ -921,7 +950,7 @@ Foam::argList::argList
|
||||
}
|
||||
else
|
||||
{
|
||||
// Regular option:
|
||||
// Regular option (with a parameter):
|
||||
// Duplicates handled by using the last -option specified
|
||||
options_.set(optName, args_[argi]);
|
||||
}
|
||||
@ -932,6 +961,19 @@ Foam::argList::argList
|
||||
// registered as existing.
|
||||
|
||||
options_.insert(optName, "");
|
||||
|
||||
// Special increment handling for some known flags
|
||||
if (wantArg.good())
|
||||
{
|
||||
if (strcmp(optName, "dry-run") == 0)
|
||||
{
|
||||
++numDryRun;
|
||||
}
|
||||
else if (strcmp(optName, "verbose") == 0)
|
||||
{
|
||||
++numVerbose;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -944,6 +986,10 @@ Foam::argList::argList
|
||||
}
|
||||
}
|
||||
|
||||
// Commit number of -dry-run and -verbose flag occurrences
|
||||
runControl_.dryRun(numDryRun);
|
||||
runControl_.verbose(numVerbose);
|
||||
|
||||
args_.resize(nArgs);
|
||||
|
||||
parse(checkArgs, checkOpts, initialise);
|
||||
@ -1043,7 +1089,7 @@ void Foam::argList::parse
|
||||
foamVersion::printBuildInfo(Info.stdStream(), false);
|
||||
FatalError.write(Info, false);
|
||||
|
||||
Pstream::exit(1); // works for serial and parallel
|
||||
Pstream::exit(1); // works for serial and parallel
|
||||
}
|
||||
|
||||
if (initialise)
|
||||
@ -1227,7 +1273,13 @@ void Foam::argList::parse
|
||||
{
|
||||
source = "-roots";
|
||||
runControl_.distributed(true);
|
||||
if (roots.size() != 1)
|
||||
if (roots.empty())
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "The -roots option must contain values"
|
||||
<< exit(FatalError);
|
||||
}
|
||||
if (roots.size() > 1)
|
||||
{
|
||||
dictNProcs = roots.size()+1;
|
||||
}
|
||||
@ -1235,17 +1287,27 @@ void Foam::argList::parse
|
||||
else if (options_.found("hostRoots"))
|
||||
{
|
||||
source = "-hostRoots";
|
||||
roots.resize(Pstream::nProcs()-1, fileName::null);
|
||||
runControl_.distributed(true);
|
||||
|
||||
ITstream is(this->lookup("hostRoots"));
|
||||
|
||||
List<Tuple2<wordRe, fileName>> hostRoots(is);
|
||||
checkITstream(is, "hostRoots");
|
||||
|
||||
if (hostRoots.empty())
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "The -hostRoots option must contain values"
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
// Match machine names to roots
|
||||
roots.resize(Pstream::nProcs()-1, fileName::null);
|
||||
for (const auto& hostRoot : hostRoots)
|
||||
{
|
||||
labelList matched
|
||||
(
|
||||
findStrings(hostRoot.first(), hostMachine)
|
||||
findMatchingStrings(hostRoot.first(), hostMachine)
|
||||
);
|
||||
for (const label matchi : matched)
|
||||
{
|
||||
@ -1275,7 +1337,7 @@ void Foam::argList::parse
|
||||
}
|
||||
}
|
||||
|
||||
if (roots.size() != 1)
|
||||
if (roots.size() > 1)
|
||||
{
|
||||
dictNProcs = roots.size()+1;
|
||||
}
|
||||
@ -1312,6 +1374,13 @@ void Foam::argList::parse
|
||||
nDomainsMandatory = true;
|
||||
runControl_.distributed(true);
|
||||
decompDict.readEntry("roots", roots);
|
||||
|
||||
if (roots.empty())
|
||||
{
|
||||
DetailInfo
|
||||
<< "WARNING: running distributed"
|
||||
<< " but did not specify roots!" << nl;
|
||||
}
|
||||
}
|
||||
|
||||
// Get numberOfSubdomains if it exists.
|
||||
@ -1330,7 +1399,7 @@ void Foam::argList::parse
|
||||
{
|
||||
// Optional if using default location
|
||||
DetailInfo
|
||||
<< "Warning: running without decomposeParDict "
|
||||
<< "WARNING: running without decomposeParDict "
|
||||
<< this->relativePath(source) << nl;
|
||||
}
|
||||
else
|
||||
@ -1415,8 +1484,13 @@ void Foam::argList::parse
|
||||
{
|
||||
options_.set("case", roots[subproci-1]/globalCase_);
|
||||
|
||||
OPstream toSubproc(Pstream::commsTypes::scheduled, subproci);
|
||||
toSubproc << args_ << options_ << roots.size();
|
||||
OPstream toProc(Pstream::commsTypes::scheduled, subproci);
|
||||
toProc
|
||||
<< args_ << options_
|
||||
<< runControl_.distributed()
|
||||
<< label(runControl_.dryRun())
|
||||
<< label(runControl_.verbose());
|
||||
|
||||
}
|
||||
options_.erase("case");
|
||||
|
||||
@ -1463,24 +1537,34 @@ void Foam::argList::parse
|
||||
// Distribute the master's argument list (unaltered)
|
||||
for (const int subproci : Pstream::subProcs())
|
||||
{
|
||||
OPstream toSubproc(Pstream::commsTypes::scheduled, subproci);
|
||||
toSubproc << args_ << options_ << roots.size();
|
||||
OPstream toProc(Pstream::commsTypes::scheduled, subproci);
|
||||
toProc
|
||||
<< args_ << options_
|
||||
<< runControl_.distributed()
|
||||
<< label(runControl_.dryRun())
|
||||
<< label(runControl_.verbose());
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Collect the master's argument list
|
||||
label nroots;
|
||||
bool isDistributed;
|
||||
label numDryRun, numVerbose;
|
||||
|
||||
IPstream fromMaster
|
||||
(
|
||||
Pstream::commsTypes::scheduled,
|
||||
Pstream::masterNo()
|
||||
);
|
||||
fromMaster >> args_ >> options_ >> nroots;
|
||||
fromMaster
|
||||
>> args_ >> options_
|
||||
>> isDistributed
|
||||
>> numDryRun >> numVerbose;
|
||||
|
||||
runControl_.distributed(nroots);
|
||||
runControl_.distributed(isDistributed);
|
||||
runControl_.dryRun(numDryRun);
|
||||
runControl_.verbose(numVerbose);
|
||||
|
||||
// Establish rootPath_/globalCase_/case_ for sub-process
|
||||
setCasePaths();
|
||||
|
||||
@ -366,16 +366,23 @@ public:
|
||||
//- Return the run control (parallel, dry-run etc)
|
||||
inline const ParRunControl& runControl() const noexcept;
|
||||
|
||||
//- Return the dryRun flag
|
||||
inline bool dryRun() const noexcept;
|
||||
|
||||
//- Modify the dryRun flag
|
||||
inline bool dryRun(const bool on) noexcept;
|
||||
|
||||
//- Return distributed flag
|
||||
//- (i.e. are rootPaths different on different machines)
|
||||
inline bool distributed() const noexcept;
|
||||
|
||||
//- Return the dry-run flag
|
||||
inline int dryRun() const noexcept;
|
||||
|
||||
//- Modify the dry-run flag
|
||||
inline int dryRun(const int level) noexcept;
|
||||
|
||||
//- Return the verbose flag
|
||||
inline int verbose() const noexcept;
|
||||
|
||||
//- Modify the verbose flag
|
||||
inline int verbose(const int level) noexcept;
|
||||
|
||||
|
||||
//- Mutable access to the loaded dynamic libraries
|
||||
inline dlLibraryTable& libs() const noexcept;
|
||||
|
||||
@ -603,10 +610,17 @@ public:
|
||||
// Queries the Foam::infoDetailLevel flag.
|
||||
static bool bannerEnabled();
|
||||
|
||||
//- Add a 'dry-run' bool option to validOptions with usage information
|
||||
//- Enable a 'dry-run' bool option, with usage information
|
||||
static void addDryRunOption
|
||||
(
|
||||
const string& usage, //! usage information (mandatory)
|
||||
const string& usage, //! usage information (expected)
|
||||
bool advanced = false
|
||||
);
|
||||
|
||||
//- Enable a 'verbose' bool option, with usage information
|
||||
static void addVerboseOption
|
||||
(
|
||||
const string& usage, //! usage information (expected)
|
||||
bool advanced = false
|
||||
);
|
||||
|
||||
|
||||
@ -107,21 +107,33 @@ Foam::argList::runControl() const noexcept
|
||||
}
|
||||
|
||||
|
||||
inline bool Foam::argList::dryRun() const noexcept
|
||||
inline bool Foam::argList::distributed() const noexcept
|
||||
{
|
||||
return runControl_.distributed();
|
||||
}
|
||||
|
||||
|
||||
inline int Foam::argList::dryRun() const noexcept
|
||||
{
|
||||
return runControl_.dryRun();
|
||||
}
|
||||
|
||||
|
||||
inline bool Foam::argList::dryRun(const bool on) noexcept
|
||||
inline int Foam::argList::dryRun(const int level) noexcept
|
||||
{
|
||||
return runControl_.dryRun(on);
|
||||
return runControl_.dryRun(level);
|
||||
}
|
||||
|
||||
|
||||
inline bool Foam::argList::distributed() const noexcept
|
||||
inline int Foam::argList::verbose() const noexcept
|
||||
{
|
||||
return runControl_.distributed();
|
||||
return runControl_.verbose();
|
||||
}
|
||||
|
||||
|
||||
inline int Foam::argList::verbose(const int level) noexcept
|
||||
{
|
||||
return runControl_.verbose(level);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -54,7 +54,8 @@ namespace Foam
|
||||
|
||||
class ParRunControl
|
||||
{
|
||||
bool dryRun_;
|
||||
int dryRun_;
|
||||
int verbose_;
|
||||
bool parallel_;
|
||||
bool distributed_;
|
||||
|
||||
@ -63,7 +64,8 @@ public:
|
||||
//- Default construct
|
||||
ParRunControl()
|
||||
:
|
||||
dryRun_(false),
|
||||
dryRun_(0),
|
||||
verbose_(0),
|
||||
parallel_(false),
|
||||
distributed_(false)
|
||||
{}
|
||||
@ -79,49 +81,68 @@ public:
|
||||
}
|
||||
|
||||
|
||||
//- Initialize Pstream for a parallel run
|
||||
void runPar(int& argc, char**& argv, bool needsThread)
|
||||
{
|
||||
if (!UPstream::init(argc, argv, needsThread))
|
||||
// Parallel Control
|
||||
|
||||
//- Initialize Pstream for a parallel run
|
||||
void runPar(int& argc, char**& argv, bool needsThread)
|
||||
{
|
||||
Info<< "Failed to start parallel run" << endl;
|
||||
UPstream::exit(1);
|
||||
if (!UPstream::init(argc, argv, needsThread))
|
||||
{
|
||||
Info<< "Failed to start parallel run" << endl;
|
||||
UPstream::exit(1);
|
||||
}
|
||||
parallel_ = true;
|
||||
}
|
||||
parallel_ = true;
|
||||
}
|
||||
|
||||
|
||||
//- True if set as 'dry-run'
|
||||
bool dryRun() const noexcept
|
||||
{
|
||||
return dryRun_;
|
||||
}
|
||||
//- True if this is a parallel run
|
||||
bool parRun() const noexcept
|
||||
{
|
||||
return parallel_;
|
||||
}
|
||||
|
||||
//- Set as 'dry-run', return old value
|
||||
bool dryRun(bool on) noexcept
|
||||
{
|
||||
bool old(dryRun_);
|
||||
dryRun_ = on;
|
||||
return old;
|
||||
}
|
||||
//- True if this is a parallel run and uses distributed roots.
|
||||
bool distributed() const noexcept
|
||||
{
|
||||
return (parallel_ && distributed_);
|
||||
}
|
||||
|
||||
//- True if this is a parallel run
|
||||
bool parRun() const noexcept
|
||||
{
|
||||
return parallel_;
|
||||
}
|
||||
//- Set use of distributed roots, but only if actually parallel
|
||||
void distributed(bool on) noexcept
|
||||
{
|
||||
distributed_ = (parallel_ && on);
|
||||
}
|
||||
|
||||
//- True if this is a parallel run and uses distributed roots.
|
||||
bool distributed() const noexcept
|
||||
{
|
||||
return (parallel_ && distributed_);
|
||||
}
|
||||
|
||||
//- Set use of distributed roots, but only if actually parallel
|
||||
void distributed(bool on) noexcept
|
||||
{
|
||||
distributed_ = (parallel_ && on);
|
||||
}
|
||||
// General Control
|
||||
|
||||
//- Non-zero if set as 'dry-run'
|
||||
int dryRun() const noexcept
|
||||
{
|
||||
return dryRun_;
|
||||
}
|
||||
|
||||
//- Change 'dry-run', return old value
|
||||
int dryRun(const int level) noexcept
|
||||
{
|
||||
int old(dryRun_);
|
||||
dryRun_ = level;
|
||||
return old;
|
||||
}
|
||||
|
||||
//- Non-zero if set as 'verbose'
|
||||
int verbose() const noexcept
|
||||
{
|
||||
return verbose_;
|
||||
}
|
||||
|
||||
//- Change 'verbose', return old value
|
||||
int verbose(const int level) noexcept
|
||||
{
|
||||
int old(verbose_);
|
||||
verbose_ = level;
|
||||
return old;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user