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);
}
Exemple #2
0
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_;
                }
            }
        }