Foam::argList::argList ( int& argc, char**& argv, bool checkArgs, bool checkOpts, const bool initialise ) : args_(argc), options_(argc) { // 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 = 0; argI < argc; ++argI) { if (argv[argI][0] == '-') { const char *optionName = &argv[argI][1]; if (validParOptions.found(optionName)) { parRunControl_.runPar(argc, argv); break; } } } // Convert argv -> args_ and capture ( ... ) lists // for normal arguments and for options regroupArgv(argc, argv); // Get executable name args_[0] = fileName(argv[0]); executable_ = fileName(argv[0]).name(); // Check arguments and options, we already have argv[0] int nArgs = 1; argListStr_ = args_[0]; for (int argI = 1; argI < args_.size(); ++argI) { argListStr_ += ' '; argListStr_ += args_[argI]; if (args_[argI][0] == '-') { const char *optionName = &args_[argI][1]; if ( ( validOptions.found(optionName) && !validOptions[optionName].empty() ) || ( validParOptions.found(optionName) && !validParOptions[optionName].empty() ) ) { ++argI; if (argI >= args_.size()) { FatalError <<"Option '-" << optionName << "' requires an argument" << endl; printUsage(); FatalError.exit(); } argListStr_ += ' '; argListStr_ += args_[argI]; options_.insert(optionName, args_[argI]); } else { options_.insert(optionName, ""); } } else { if (nArgs != argI) { args_[nArgs] = args_[argI]; } ++nArgs; } } args_.setSize(nArgs); parse(checkArgs, checkOpts, initialise); }
Foam::argList::argList ( int& argc, char**& argv, bool checkArgs, bool checkOpts ) : args_(argc), options_(argc) { // 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 = 0; argI < argc; ++argI) { if (argv[argI][0] == '-') { const char *optionName = &argv[argI][1]; if (validParOptions.found(optionName)) { parRunControl_.runPar(argc, argv); break; } } } // convert argv -> args_ and capture ( ... ) lists // for normal arguments and for options regroupArgv(argc, argv); // Get executable name args_[0] = fileName(argv[0]); executable_ = fileName(argv[0]).name(); // Check arguments and options, we already have argv[0] int nArgs = 1; string argListString = args_[0]; for (int argI = 1; argI < args_.size(); ++argI) { argListString += ' '; argListString += args_[argI]; if (args_[argI][0] == '-') { const char *optionName = &args_[argI][1]; if ( ( validOptions.found(optionName) && !validOptions[optionName].empty() ) || ( validParOptions.found(optionName) && !validParOptions[optionName].empty() ) ) { ++argI; if (argI >= args_.size()) { FatalError <<"Option '-" << optionName << "' requires an argument" << endl; printUsage(); FatalError.exit(); } argListString += ' '; argListString += args_[argI]; options_.insert(optionName, args_[argI]); } else { options_.insert(optionName, ""); } } else { if (nArgs != argI) { args_[nArgs] = args_[argI]; } ++nArgs; } } args_.setSize(nArgs); // Help/documentation options: // -help print the usage // -doc display application documentation in browser // -srcDoc display source code in browser if ( options_.found("help") || options_.found("doc") || options_.found("srcDoc") ) { if (options_.found("help")) { printUsage(); } // only display one or the other if (options_.found("srcDoc")) { displayDoc(true); } else if (options_.found("doc")) { displayDoc(false); } ::exit(0); } // Print the usage message and exit if the number of arguments is incorrect if (!check(checkArgs, checkOpts)) { FatalError.exit(); } string dateString = clock::date(); string timeString = clock::clockTime(); // Print the banner once only for parallel runs if (Pstream::master() && bannerEnabled) { IOobject::writeBanner(Info, true) << "Build : " << Foam::FOAMbuild << nl << "Exec : " << argListString.c_str() << nl << "Date : " << dateString.c_str() << nl << "Time : " << timeString.c_str() << nl << "Host : " << hostName() << nl << "PID : " << pid() << endl; } jobInfo.add("startDate", dateString); jobInfo.add("startTime", timeString); jobInfo.add("userName", userName()); jobInfo.add("foamVersion", word(FOAMversion)); jobInfo.add("code", executable_); jobInfo.add("argList", argListString); jobInfo.add("currentDir", cwd()); jobInfo.add("PPID", ppid()); jobInfo.add("PGID", pgid()); // add build information - only use the first word { std::string build(Foam::FOAMbuild); std::string::size_type found = build.find(' '); if (found != std::string::npos) { build.resize(found); } jobInfo.add("foamBuild", build); } // Case is a single processor run unless it is running parallel int nProcs = 1; // Roots if running distributed fileNameList roots; // If this actually is a parallel run if (parRunControl_.parRun()) { // For the master if (Pstream::master()) { // establish rootPath_/globalCase_/case_ for master getRootCase(); // See if running distributed (different roots for different procs) label dictNProcs = -1; fileName source; if (options_.found("roots")) { source = "-roots"; IStringStream is(options_["roots"]); roots = readList<fileName>(is); if (roots.size() != 1) { dictNProcs = roots.size()+1; } } else { source = rootPath_/globalCase_/"system/decomposeParDict"; IFstream decompDictStream(source); if (!decompDictStream.good()) { FatalError << "Cannot read " << decompDictStream.name() << exit(FatalError); } dictionary decompDict(decompDictStream); dictNProcs = readLabel ( decompDict.lookup("numberOfSubdomains") ); if (decompDict.lookupOrDefault("distributed", false)) { decompDict.lookup("roots") >> roots; } } // convenience: // when a single root is specified, use it for all processes if (roots.size() == 1) { const fileName rootName(roots[0]); roots.setSize(Pstream::nProcs()-1, rootName); // adjust dictNProcs for command-line '-roots' option if (dictNProcs < 0) { dictNProcs = roots.size()+1; } } // Check number of processors. // nProcs => number of actual procs // dictNProcs => number of procs specified in decompositionDict // nProcDirs => number of processor directories // (n/a when running distributed) // // - normal running : nProcs = dictNProcs = nProcDirs // - decomposition to more processors : nProcs = dictNProcs // - decomposition to fewer processors : nProcs = nProcDirs if (dictNProcs > Pstream::nProcs()) { FatalError << source << " specifies " << dictNProcs << " processors but job was started with " << Pstream::nProcs() << " processors." << exit(FatalError); } // distributed data if (roots.size()) { if (roots.size() != Pstream::nProcs()-1) { FatalError << "number of entries in roots " << roots.size() << " is not equal to the number of slaves " << Pstream::nProcs()-1 << exit(FatalError); } forAll(roots, i) { roots[i].expand(); } // Distribute the master's argument list (with new root) bool hadCaseOpt = options_.found("case"); for ( int slave = Pstream::firstSlave(); slave <= Pstream::lastSlave(); slave++ ) { options_.set("case", roots[slave-1]/globalCase_); OPstream toSlave(Pstream::scheduled, slave); toSlave << args_ << options_; } options_.erase("case"); // restore [-case dir] if (hadCaseOpt) { options_.set("case", rootPath_/globalCase_); } } else { // Possibly going to fewer processors. // Check if all procDirs are there. if (dictNProcs < Pstream::nProcs()) { label nProcDirs = 0; while ( isDir ( rootPath_/globalCase_/"processor" + name(++nProcDirs) ) ) {} if (nProcDirs != Pstream::nProcs()) { FatalError << "number of processor directories = " << nProcDirs << " is not equal to the number of processors = " << Pstream::nProcs() << exit(FatalError); } } // Distribute the master's argument list (unaltered) for ( int slave = Pstream::firstSlave(); slave <= Pstream::lastSlave(); slave++ ) { OPstream toSlave(Pstream::scheduled, slave); toSlave << args_ << options_; } } }