ENH: support command-line specification of MPI threads (#2791)

- MPI_THREAD_MULTIPLE is usually undesirable for performance reasons,
  but in some cases may be necessary if a linked library expects it.
  Provide a '-mpi-threads' option to explicitly request it.

ENH: consolidate some looping logic within argList
This commit is contained in:
Mark Olesen 2023-06-15 11:23:31 +02:00
parent b2217d5e6b
commit 4412566c58
14 changed files with 366 additions and 233 deletions

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2017-2021 OpenCFD Ltd.
Copyright (C) 2017-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -124,6 +124,9 @@ int main(int argc, char *argv[])
argList::addDryRunOption("Just for testing");
argList::addVerboseOption("Increase verbosity");
// Check -verbose before initialisation
UPstream::debug = argList::verbose(argc, argv);
#include "setRootCase.H"
Pout<< "command-line ("

View File

@ -42,6 +42,7 @@ Description
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
void printInfo(const label comm)
{
@ -65,20 +66,10 @@ int main(int argc, char *argv[])
{
argList::noBanner();
argList::noCheckProcessorDirectories();
argList::addBoolOption("verbose", "Set debug level");
// Capture manually. We need values before proper startup
int nVerbose = 0;
for (int argi = 1; argi < argc; ++argi)
{
if (strcmp(argv[argi], "-verbose") == 0)
{
++nVerbose;
}
}
UPstream::debug = nVerbose;
argList::addVerboseOption("Set UPstream::debug level");
// Check -verbose before initialisation
UPstream::debug = argList::verbose(argc, argv);
#include "setRootCase.H"

View File

@ -44,6 +44,8 @@ Description
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
void rankInfo(const label comm)
{
const int ranki = UPstream::myProcNo(comm);
@ -63,7 +65,7 @@ int main(int argc, char *argv[])
{
argList::noBanner();
argList::noCheckProcessorDirectories();
argList::addBoolOption("verbose", "Set debug level");
argList::addVerboseOption("Set UPstream::debug level");
argList::addBoolOption("info", "information");
argList::addBoolOption("print-tree", "Report tree(s) as graph");
argList::addBoolOption("comm-split", "Test simple comm split");
@ -71,17 +73,8 @@ int main(int argc, char *argv[])
argList::addBoolOption("host-comm", "Test Pstream host-comm");
argList::addBoolOption("host-broadcast", "Test host-base broadcasts");
// Capture manually. We need values before proper startup
int nVerbose = 0;
for (int argi = 1; argi < argc; ++argi)
{
if (strcmp(argv[argi], "-verbose") == 0)
{
++nVerbose;
}
}
UPstream::debug = nVerbose;
// Check -verbose before initialisation
UPstream::debug = argList::verbose(argc, argv);
#include "setRootCase.H"

View File

@ -44,6 +44,7 @@ Description
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
bool startMPI()
{
@ -121,19 +122,10 @@ int main(int argc, char *argv[])
{
argList::noBanner();
argList::noCheckProcessorDirectories();
argList::addBoolOption("verbose", "Set debug level");
argList::addVerboseOption("Set UPstream::debug level");
// Need to capture manually, since we need values before proper startup
int nVerbose = 0;
for (int argi = 1; argi < argc; ++argi)
{
if (strcmp(argv[argi], "-verbose") == 0)
{
++nVerbose;
}
}
UPstream::debug = nVerbose;
// Check -verbose before initialisation
UPstream::debug = argList::verbose(argc, argv);
startMPI();

View File

@ -43,24 +43,15 @@ using namespace Foam;
int main(int argc, char *argv[])
{
argList::noFunctionObjects();
argList::addBoolOption("verbose", "Set debug level");
argList::addVerboseOption("Set UPstream::debug level");
argList::addBoolOption("comm-graph", "Test simple graph communicator");
argList::addNote
(
"Create graph of OpenFOAM mesh connections"
);
// Capture manually. We need values before proper startup
int nVerbose = 0;
for (int argi = 1; argi < argc; ++argi)
{
if (strcmp(argv[argi], "-verbose") == 0)
{
++nVerbose;
}
}
UPstream::debug = nVerbose;
// Check -verbose before initialisation
UPstream::debug = argList::verbose(argc, argv);
#include "setRootCase.H"

View File

@ -264,7 +264,7 @@ int main(int argc, char *argv[])
// enable noConstant by switching
if (!args.found("noConstant"))
{
args.setOption("constant", "");
args.setOption("constant");
}
else
{

View File

@ -402,7 +402,6 @@ int main(int argc, char *argv[])
timeSelector::addOptions();
argList::addOptionCompat("dry-run", {"test", 1806});
argList::addDryRunOption
(
"Test only do not change any files"
@ -425,7 +424,7 @@ int main(int argc, char *argv[])
instantList timeDirs = timeSelector::select0(runTime, args);
const bool dryrun = args.found("dry-run");
const bool dryrun = args.dryRun();
if (dryrun)
{
Info<< "-dry-run option: no changes made" << nl << endl;

View File

@ -166,10 +166,13 @@ void Foam::Time::readDict()
}
controlDict_.watchIndices().clear();
// The new handler, create with some verbosity
// Reporting verbosity corresponding to detail level
const bool verbose = (::Foam::infoDetailLevel > 0);
// The new handler
refPtr<fileOperation> newHandler
(
fileOperation::New(fileHandlerName, true)
fileOperation::New(fileHandlerName, verbose)
);
// Install the new handler
@ -206,6 +209,9 @@ void Foam::Time::readDict()
IStringStream dummyIs("");
// Reporting verbosity corresponding to detail level
const bool verbose = (::Foam::infoDetailLevel > 0);
forAllConstIters(objs, iter)
{
const List<simpleRegIOobject*>& objects = *iter;
@ -214,7 +220,7 @@ void Foam::Time::readDict()
{
obj->readData(dummyIs);
if (Foam::infoDetailLevel > 0)
if (verbose)
{
Info<< " ";
obj->writeData(Info);

View File

@ -54,6 +54,7 @@ License
bool Foam::argList::argsMandatory_ = true;
bool Foam::argList::checkProcessorDirectories_ = true;
bool Foam::argList::parallelThreads_ = false;
Foam::SLList<Foam::string> Foam::argList::validArgs;
Foam::HashSet<Foam::string> Foam::argList::advancedOptions;
@ -122,6 +123,14 @@ Foam::argList::initValidTables::initValidTables()
argList::addBoolOption("parallel", "Run in parallel");
validParOptions.set("parallel", "");
argList::addBoolOption
(
"mpi-threads",
"Request use of MPI threads",
true // advanced option
);
argList::addOption
(
"roots",
@ -401,7 +410,7 @@ void Foam::argList::addOption
void Foam::argList::setAdvanced(const word& optName, bool advanced)
{
if (advanced && validOptions.found(optName))
if (advanced && validOptions.contains(optName))
{
advancedOptions.set(optName);
}
@ -504,7 +513,13 @@ void Foam::argList::addDryRunOption
bool advanced
)
{
argList::addBoolOption("dry-run", usage, advanced);
const word optName("dry-run", false);
argList::addBoolOption(optName, usage, advanced);
if (!advanced)
{
advancedOptions.erase(optName); // Avoid 'stickiness'
}
}
@ -514,13 +529,24 @@ void Foam::argList::addVerboseOption
bool advanced
)
{
const word optName("verbose", false);
if (usage.empty())
{
argList::addBoolOption("verbose", "Additional verbosity", advanced);
argList::addBoolOption
(
optName,
"Additional verbosity (can be used multiple times)",
advanced
);
}
else
{
argList::addBoolOption("verbose", usage, advanced);
argList::addBoolOption(optName, usage, advanced);
}
if (!advanced)
{
advancedOptions.erase(optName); // Avoid 'stickiness'
}
}
@ -569,10 +595,17 @@ void Foam::argList::noParallel()
removeOption("decomposeParDict");
removeOption("hostRoots");
removeOption("world");
removeOption("mpi-threads");
validParOptions.clear();
}
void Foam::argList::parallelThreads_on()
{
parallelThreads_ = true;
}
void Foam::argList::noCheckProcessorDirectories()
{
checkProcessorDirectories_ = false;
@ -581,11 +614,18 @@ void Foam::argList::noCheckProcessorDirectories()
bool Foam::argList::postProcess(int argc, char *argv[])
{
for (int i=1; i<argc; ++i)
for (int argi = 1; argi < argc; ++argi)
{
if (argv[i] == '-' + postProcessOptionName)
const char *optName = argv[argi];
if (optName[0] == '-')
{
return true;
++optName; // Looks like an option, skip leading '-'
if (optName == postProcessOptionName)
{
return true;
}
}
}
@ -593,6 +633,20 @@ bool Foam::argList::postProcess(int argc, char *argv[])
}
int Foam::argList::verbose(int argc, char *argv[])
{
int num = 0;
for (int argi = 1; argi < argc; ++argi)
{
if (strcmp(argv[argi], "-verbose") == 0)
{
++num;
}
}
return num;
}
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
Foam::word Foam::argList::envExecutable()
@ -694,6 +748,8 @@ int Foam::argList::optionIgnore(const word& optName)
}
}
// TBD: could ignore -verbose, -dry-run etc if they are not active...
return 0; // Do not skip
}
@ -711,15 +767,19 @@ bool Foam::argList::regroupArgv(int& argc, char**& argv)
args_[0] = fileName(argv[0]);
for (int argi = 1; argi < argc; ++argi)
{
if (strcmp(argv[argi], "(") == 0)
const char *optName = argv[argi];
if (optName[0] == '(' && optName[1] == '\0')
{
// Begin list
++depth;
group += '(';
}
else if (strcmp(argv[argi], ")") == 0)
else if (optName[0] == ')' && optName[1] == '\0')
{
if (depth)
{
// End list
--depth;
group += ')';
if (!depth)
@ -730,6 +790,7 @@ bool Foam::argList::regroupArgv(int& argc, char**& argv)
}
else
{
// A stray ')' - likely never happens
args_[nArgs++] = argv[argi];
}
}
@ -740,12 +801,11 @@ bool Foam::argList::regroupArgv(int& argc, char**& argv)
group += argv[argi];
group += '"';
}
else if (argv[argi][0] == '-')
else if (optName[0] == '-')
{
// Appears to be an option
const char *optName = &argv[argi][1];
++optName; // Looks like an option, skip leading '-'
if (validOptions.found(optName))
if (validOptions.contains(optName))
{
// Known option name
args_[nArgs++] = argv[argi];
@ -848,59 +908,117 @@ Foam::argList::argList
bool initialise
)
:
runControl_(),
args_(argc),
options_(argc),
libs_()
{
// Check for -fileHandler, which requires an argument.
word handlerType;
for (int argi = argc-2; argi > 0; --argi)
{
if (argv[argi][0] == '-')
{
const char *optName = &argv[argi][1];
// Pre-scan for some options needed for initial setup:
// -fileHandler (takes an argument)
// -mpi-threads (bool option)
//
// Also handle -dry-run and -verbose counting
// (it is left to the application to decide what to do with them).
// Detect any parallel run options
if (strcmp(optName, "fileHandler") == 0)
{
handlerType = argv[argi+1];
break;
}
}
}
if (handlerType.empty())
word fileHandlerName;
if (parallelThreads_)
{
handlerType = Foam::getEnv("FOAM_FILEHANDLER");
if (handlerType.empty())
{
handlerType = fileOperation::defaultFileHandler;
}
// Default -mpi-threads configured statically from application
runControl_.threads(true);
}
// Detect any parallel options
const bool needsThread = fileOperations::fileOperationInitialise::New
(
handlerType,
argc,
argv
)().needsThreading();
// Check if this run is a parallel run by searching for any parallel option
// If found call runPar which might filter argv
for (int argi = 1; argi < argc; ++argi)
{
if (argv[argi][0] == '-')
{
const char *optName = &argv[argi][1];
const char *optName = argv[argi];
if (validParOptions.found(optName))
if (optName[0] == '-')
{
++optName; // Looks like an option, skip leading '-'
bool emitErrorMessage = false;
if (strcmp(optName, "dry-run") == 0)
{
runControl_.runPar(argc, argv, needsThread);
break;
runControl_.incrDryRun();
}
else if (strcmp(optName, "verbose") == 0)
{
runControl_.incrVerbose();
}
else if (strcmp(optName, "mpi-threads") == 0)
{
runControl_.threads(true);
}
else if (strcmp(optName, "fileHandler") == 0)
{
// Requires a parameter
if (argi < argc-1)
{
++argi;
fileHandlerName = argv[argi];
}
else
{
emitErrorMessage = true;
}
}
else if (validParOptions.contains(optName))
{
// Contains a parallel run option
runControl_.parRun(true);
}
if (emitErrorMessage)
{
// Missing argument: emit message but not exit or
// FatalError since Pstream etc are not yet initialised
Info<< nl
<< "Error: option '-" << optName
<< "' requires an argument" << nl << nl;
//NO: UPstream::exit(1); // works for serial and parallel
}
}
}
// No -fileHandler specifed, get from environment or use default
if (fileHandlerName.empty())
{
fileHandlerName = Foam::getEnv("FOAM_FILEHANDLER");
if (fileHandlerName.empty())
{
fileHandlerName = fileOperation::defaultFileHandler;
}
}
// Parse out any additional fileHandler-specific options
// (may alter argv list). Recover its threading requirements
{
auto fileOperationInit = fileOperations::fileOperationInitialise::New
(
fileHandlerName,
argc,
argv
);
if (fileOperationInit && fileOperationInit->needsThreading())
{
runControl_.threads(true);
}
}
// Parallel job options detected?
// - start parallel run (possibly filters argv as a side-effect)
if (runControl_.parRun())
{
runControl_.runPar(argc, argv);
}
// ------------------------------------------------------------------------
// Convert argv -> args_ and capture ( ... ) lists
regroupArgv(argc, argv);
commandLine_ += args_[0];
@ -908,9 +1026,6 @@ 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)
@ -918,9 +1033,11 @@ Foam::argList::argList
commandLine_ += ' ';
commandLine_ += args_[argi];
if (args_[argi][0] == '-')
const char *optName = args_[argi].data();
if (optName[0] == '-')
{
const char *optName = &args_[argi][1];
++optName; // Looks like an option, skip leading '-'
if (!*optName)
{
@ -949,7 +1066,7 @@ Foam::argList::argList
if (wantArg)
{
// Known option and expects a parameter
// Option expects a parameter
// - get it or emit a FatalError.
++argi;
@ -1019,18 +1136,11 @@ Foam::argList::argList
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;
}
}
// // Special increment handling for some known flags
// if (wantArg.good())
// {
// ...
// }
}
}
else
@ -1043,10 +1153,6 @@ 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);
@ -1093,42 +1199,42 @@ void Foam::argList::parse
bool quickExit = false;
// Display either application or source documentation, not both
if (options_.found("doc"))
if (options_.contains("doc"))
{
displayDoc(false);
quickExit = true;
}
else if (options_.found("doc-source"))
else if (options_.contains("doc-source"))
{
displayDoc(true);
quickExit = true;
}
// Display either short or full help, not both
if (options_.found("help-full"))
if (options_.contains("help-full"))
{
printUsage(true);
quickExit = true;
}
else if (options_.found("help-notes"))
else if (options_.contains("help-notes"))
{
printNotes();
Info<< nl;
quickExit = true;
}
else if (options_.found("help"))
else if (options_.contains("help"))
{
printUsage(false);
quickExit = true;
}
else if (options_.found("help-man"))
else if (options_.contains("help-man"))
{
printMan();
quickExit = true;
}
// Allow independent display of compatibility information
if (options_.found("help-compat"))
if (options_.contains("help-compat"))
{
printCompat();
quickExit = true;
@ -1221,19 +1327,19 @@ void Foam::argList::parse
// 5. '-fileHandler' commmand-line option
{
word handlerType
word fileHandlerName
(
options_.lookup("fileHandler", Foam::getEnv("FOAM_FILEHANDLER"))
);
if (handlerType.empty())
if (fileHandlerName.empty())
{
handlerType = fileOperation::defaultFileHandler;
fileHandlerName = fileOperation::defaultFileHandler;
}
(void) fileOperation::fileHandler
(
fileOperation::New(handlerType, bannerEnabled())
fileOperation::New(fileHandlerName, bannerEnabled())
);
}
@ -1346,7 +1452,7 @@ void Foam::argList::parse
dictNProcs = roots.size()+1;
}
}
else if (options_.found("hostRoots"))
else if (options_.contains("hostRoots"))
{
source = "-hostRoots";
runControl_.distributed(true);
@ -1546,7 +1652,7 @@ void Foam::argList::parse
}
// Distribute the master's argument list (with new root)
const bool hadCaseOpt = options_.found("case");
const bool hadCaseOpt = options_.contains("case");
for (const int subproci : Pstream::subProcs())
{
options_.set("case", roots[subproci-1]/globalCase_);
@ -1841,15 +1947,15 @@ Foam::argList::~argList()
bool Foam::argList::allowFunctionObjects() const
{
if (validOptions.found("withFunctionObjects"))
if (validOptions.contains("withFunctionObjects"))
{
// '-withFunctionObjects' is available and explicitly enabled
return options_.found("withFunctionObjects");
return options_.contains("withFunctionObjects");
}
else if (validOptions.found("noFunctionObjects"))
else if (validOptions.contains("noFunctionObjects"))
{
// '-noFunctionObjects' is available and not explicitly disabled
return !options_.found("noFunctionObjects");
return !options_.contains("noFunctionObjects");
}
// Disallow functions if there is no way to enable/disable them
@ -1859,7 +1965,7 @@ bool Foam::argList::allowFunctionObjects() const
bool Foam::argList::allowLibs() const
{
return !options_.found("no-libs");
return !options_.contains("no-libs");
}
@ -1867,32 +1973,29 @@ bool Foam::argList::allowLibs() const
Foam::label Foam::argList::count(const UList<word>& optionNames) const
{
label n = 0;
label num = 0;
for (const word& optName : optionNames)
{
if (options_.found(optName))
if (options_.contains(optName))
{
++n;
++num;
}
}
return n;
return num;
}
Foam::label Foam::argList::count
(
std::initializer_list<word> optionNames
) const
Foam::label Foam::argList::count(std::initializer_list<word> optionNames) const
{
label n = 0;
label num = 0;
for (const word& optName : optionNames)
{
if (options_.found(optName))
if (options_.contains(optName))
{
++n;
++num;
}
}
return n;
return num;
}
@ -1912,7 +2015,9 @@ bool Foam::argList::setOption(const word& optName, const string& param)
return false;
}
if (options_.found(optName) ? (options_[optName] != param) : true)
const auto optIter = options_.cfind(optName);
if (!optIter.good() || (optIter.val() != param))
{
options_.set(optName, param);
return true;
@ -1930,7 +2035,6 @@ bool Foam::argList::unsetOption(const word& optName)
optName == "case"
|| optName == "parallel"
|| optName == "roots"
|| optName == "hostRoots"
)
{
FatalErrorInFunction
@ -2040,8 +2144,8 @@ bool Foam::argList::check(bool checkArgs, bool checkOpts) const
const word& optName = iter.key();
if
(
!validOptions.found(optName)
&& !validParOptions.found(optName)
!validOptions.contains(optName)
&& !validParOptions.contains(optName)
)
{
FatalError

View File

@ -124,12 +124,15 @@ class argList
{
// Private Data
//- Track if command arguments are mandatory/optional
//- Command arguments are mandatory (default) or optional
static bool argsMandatory_;
//- Track enabled/disabled checking of processor directories state
//- Check presence of processor directories (default: on)
static bool checkProcessorDirectories_;
//- MPI threads are desired for the application (default: off)
static bool parallelThreads_;
//- Switch on/off parallel mode, dry-run etc.
// Construct first so destructor is done last.
ParRunControl runControl_;
@ -645,11 +648,11 @@ public:
//- Remove the parallel options
static void noParallel();
//- Remove checking of processor directories
//- Disable checking of processor directories
static void noCheckProcessorDirectories();
//- Return true if the post-processing option is specified
static bool postProcess(int argc, char *argv[]);
//- MPI threads are desired for the application
static void parallelThreads_on();
//- Set option directly (use with caution)
// An option with an empty param is a bool option.
@ -664,6 +667,15 @@ public:
bool unsetOption(const word& optName);
// Helpers
//- True if the post-processing option is found in the \c argv list
static bool postProcess(int argc, char *argv[]);
//- The number of times -verbose is found in the \c argv list
static int verbose(int argc, char *argv[]);
// Print
//- Print option compatibility

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2018-2021 OpenCFD Ltd.
Copyright (C) 2018-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -102,7 +102,7 @@ static void printManOption(const word& optName)
argList::optionUsage.lookup(optName, string::null)
);
if (argList::validParOptions.found(optName))
if (argList::validParOptions.contains(optName))
{
Info<< "\\fB[Parallel option]\\fR" << nl;
}
@ -314,7 +314,7 @@ void Foam::argList::printMan() const
for (const word& optName : validOptions.sortedToc())
{
// Normal (non-advanced) options
if (!advancedOptions.found(optName))
if (!advancedOptions.contains(optName))
{
printManOption(optName);
}
@ -333,7 +333,7 @@ void Foam::argList::printMan() const
for (const word& optName : validOptions.sortedToc())
{
// Advanced options
if (advancedOptions.found(optName))
if (advancedOptions.contains(optName))
{
printManOption(optName);
}
@ -418,7 +418,7 @@ void Foam::argList::printUsage(bool full) const
for (const word& optName : validOptions.sortedToc())
{
// Suppress advanced options for regular -help.
if (full || !advancedOptions.found(optName))
if (full || !advancedOptions.contains(optName))
{
printOption(optName);
}

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2013 OpenFOAM Foundation
Copyright (C) 2017-2021 OpenCFD Ltd.
Copyright (C) 2017-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -37,7 +37,7 @@ inline void Foam::argList::readList(ITstream& is, List<T>& list)
{
// Single token - treat like List with one entry
list.resize(1);
is >> list.first();
is >> list.front();
}
else
{
@ -177,7 +177,7 @@ Foam::argList::options() noexcept
inline bool Foam::argList::found(const word& optName) const
{
return options_.found(optName);
return options_.contains(optName);
}
@ -309,7 +309,7 @@ inline T Foam::argList::getOrDefault
const T& deflt
) const
{
if (found(optName))
if (options_.contains(optName))
{
return get<T>(optName);
}
@ -325,7 +325,7 @@ inline bool Foam::argList::readIfPresent
T& val
) const
{
if (found(optName))
if (options_.contains(optName))
{
val = get<T>(optName);
return true;
@ -376,7 +376,7 @@ inline Foam::List<T> Foam::argList::getList
{
List<T> list;
if (mandatory || found(optName))
if (mandatory || options_.contains(optName))
{
ITstream is(options_[optName]);
@ -396,7 +396,7 @@ inline bool Foam::argList::readListIfPresent
List<T>& list
) const
{
if (found(optName))
if (options_.contains(optName))
{
ITstream is(options_[optName]);

View File

@ -37,10 +37,10 @@ Note
\*---------------------------------------------------------------------------*/
#ifndef argListRunControl_H
#define argListRunControl_H
#ifndef Foam_argListRunControl_H
#define Foam_argListRunControl_H
#include "Pstream.H"
#include "UPstream.H"
#include "IOstreams.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -54,21 +54,38 @@ namespace Foam
class ParRunControl
{
int dryRun_;
int verbose_;
bool parallel_;
bool distributed_;
// Private Data
//- The dry-run level
int dryRun_;
//- The verbosity level
int verbose_;
//- True if this is (or will be) a parallel run
bool parallel_;
//- Uses distributed roots
bool distributed_;
//- MPI threads are desired
bool needsThread_;
public:
//- Default construct
ParRunControl()
:
dryRun_(0),
verbose_(0),
parallel_(false),
distributed_(false)
{}
// Constructors
//- Default construct
ParRunControl() noexcept
:
dryRun_(0),
verbose_(0),
parallel_(false),
distributed_(false),
needsThread_(false)
{}
//- Destructor. Shutdown (finalize) MPI as required
~ParRunControl()
@ -81,27 +98,56 @@ public:
}
// Parallel Control
// Member Functions - General Control
//- Initialize Pstream for a parallel run
void runPar(int& argc, char**& argv, bool needsThread)
//- Return the dry-run level (default: 0)
int dryRun() const noexcept { return dryRun_; }
//- Increase the dry-run level
void incrDryRun(int level = 1) noexcept { dryRun_ += level; }
//- Change dry-run level, returns old value
int dryRun(const int level) noexcept
{
if (!UPstream::init(argc, argv, needsThread))
{
Info<< "Failed to start parallel run" << endl;
UPstream::exit(1);
}
parallel_ = true;
int old(dryRun_);
dryRun_ = level;
return old;
}
//- Return the verbosity level (default: 0)
int verbose() const noexcept { return verbose_; }
//- Increase the verbosity level
void incrVerbose(int level = 1) noexcept { verbose_ += level; }
//- Change verbosity level, returns old value
int verbose(const int level) noexcept
{
int old(verbose_);
verbose_ = level;
return old;
}
//- True if this is a parallel run
// Member Functions - Parallel Control
//- True if this is (or will be) a parallel run
bool parRun() const noexcept
{
return parallel_;
}
//- True if this is a parallel run and uses distributed roots.
//- Set as parallel run on/off, return the previous value.
// Use with \b extreme caution if runPar() has already been
// called.
bool parRun(const bool on) noexcept
{
bool old(parallel_);
parallel_ = on;
return old;
}
//- True if a parallel run and uses distributed roots.
bool distributed() const noexcept
{
return (parallel_ && distributed_);
@ -113,35 +159,27 @@ public:
distributed_ = (parallel_ && on);
}
// General Control
//- Non-zero if set as 'dry-run'
int dryRun() const noexcept
//- True if MPI threads are desired (default: false)
bool threads() const noexcept
{
return dryRun_;
return needsThread_;
}
//- Change 'dry-run', return old value
int dryRun(const int level) noexcept
//- Set preference for use of MPI threads
void threads(bool on) noexcept
{
int old(dryRun_);
dryRun_ = level;
return old;
needsThread_ = on;
}
//- Non-zero if set as 'verbose'
int verbose() const noexcept
//- Initialize UPstream for a parallel run
void runPar(int& argc, char**& argv)
{
return verbose_;
}
//- Change 'verbose', return old value
int verbose(const int level) noexcept
{
int old(verbose_);
verbose_ = level;
return old;
if (!UPstream::init(argc, argv, needsThread_))
{
Info<< "Failed to start parallel run" << endl;
UPstream::exit(1);
}
parallel_ = true;
}
};

View File

@ -282,13 +282,17 @@ bool Foam::UPstream::init(int& argc, char**& argv, const bool needsThread)
if (UPstream::debug)
{
Pout<< "UPstream::init :"
<< " thread-support : wanted:" << needsThread
<< " thread-support : requested:" << needsThread
<< " obtained:"
<< (
provided_thread_support == MPI_THREAD_MULTIPLE
? "MPI_THREAD_MULTIPLE"
: "MPI_THREAD_SINGLE"
)
<< (
(provided_thread_support == MPI_THREAD_SINGLE)
? "SINGLE"
: (provided_thread_support == MPI_THREAD_SERIALIZED)
? "SERIALIZED"
: (provided_thread_support == MPI_THREAD_MULTIPLE)
? "MULTIPLE"
: "other"
)
<< " procs:" << numprocs
<< " rank:" << myRank
<< " world:" << world << endl;