Skip to content
Snippets Groups Projects
functionObjectList.C 16.1 KiB
Newer Older
  • Learn to ignore specific revisions
  • /*---------------------------------------------------------------------------*\
      =========                 |
      \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
       \\    /   O peration     |
    
        \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
    
         \\/     M anipulation  |
    -------------------------------------------------------------------------------
    License
        This file is part of OpenFOAM.
    
    
        OpenFOAM is free software: you can redistribute it and/or modify it
        under the terms of the GNU General Public License as published by
        the Free Software Foundation, either version 3 of the License, or
        (at your option) any later version.
    
    
        OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
        ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
        FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
        for more details.
    
        You should have received a copy of the GNU General Public License
    
        along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
    
    
    \*---------------------------------------------------------------------------*/
    
    #include "functionObjectList.H"
    #include "Time.H"
    
    #include "mapPolyMesh.H"
    
    #include "timeControlFunctionObject.H"
    
    #include "IFstream.H"
    #include "dictionaryEntry.H"
    #include "stringOps.H"
    
    #include "Tuple2.H"
    
    #include "etcFiles.H"
    
    /* * * * * * * * * * * * * * * Static Member Data  * * * * * * * * * * * * * */
    
    Foam::fileName Foam::functionObjectList::functionObjectDictPath
    (
        "caseDicts/postProcessing"
    );
    
    
    // * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * * //
    
    
    Foam::functionObject* Foam::functionObjectList::remove
    (
        const word& key,
        label& oldIndex
    )
    
    {
        functionObject* ptr = 0;
    
        // Find index of existing functionObject
        HashTable<label>::iterator fnd = indices_.find(key);
    
        if (fnd != indices_.end())
        {
    
            oldIndex = fnd();
    
    
            // Retrieve the pointer and remove it from the old list
    
            ptr = this->set(oldIndex, 0).ptr();
    
            indices_.erase(fnd);
        }
    
    void Foam::functionObjectList::listDir
    (
        const fileName& dir,
        HashSet<word>& foMap
    )
    {
        // Search specified directory for functionObject configuration files
        {
            fileNameList foFiles(readDir(dir));
            forAll(foFiles, f)
            {
                if (foFiles[f].ext().empty())
                {
                    foMap.insert(foFiles[f]);
                }
            }
        }
    
        // Recurse into sub-directories
        {
            fileNameList foDirs(readDir(dir, fileName::DIRECTORY));
            forAll(foDirs, fd)
            {
                listDir(dir/foDirs[fd], foMap);
            }
        }
    }
    
    
    
    void Foam::functionObjectList::list()
    {
        HashSet<word> foMap;
    
        fileNameList etcDirs(findEtcDirs(functionObjectDictPath));
    
        forAll(etcDirs, ed)
        {
    
        }
    
        Info<< nl
            << "Available configured functionObjects:"
            << foMap.sortedToc()
            << nl;
    }
    
    
    
    Foam::fileName Foam::functionObjectList::findDict(const word& funcName)
    {
        // First check if there is a functionObject dictionary file in the
        // case system directory
        fileName dictFile = stringOps::expand("$FOAM_CASE")/"system"/funcName;
    
        if (isFile(dictFile))
        {
            return dictFile;
        }
        else
        {
            fileNameList etcDirs(findEtcDirs(functionObjectDictPath));
    
            forAll(etcDirs, i)
            {
                dictFile = search(funcName, etcDirs[i]);
                if (!dictFile.empty())
                {
                    return dictFile;
                }
            }
        }
    
        return fileName::null;
    }
    
    
    
    bool Foam::functionObjectList::readFunctionObject
    
        const string& funcNameArgs,
    
        // Parse the optional functionObject arguments:
        //     'Q(U)' -> funcName = Q; args = (U); field = U
        //
        // Supports named arguments:
        //     'patchAverage(patch=inlet, p)' -> funcName = patchAverage;
        //         args = (patch=inlet, p); field = p
    
        List<Tuple2<word, string>> namedArgs;
        bool namedArg = false;
        word argName;
    
    
        word::size_type start = 0;
        word::size_type i = 0;
    
        for
        (
            word::const_iterator iter = funcNameArgs.begin();
            iter != funcNameArgs.end();
            ++iter
        )
        {
            char c = *iter;
    
            if (c == '(')
            {
    
                    funcName = funcNameArgs(start, i - start);
    
            else if (c == ',' || c == ')')
    
                    if (namedArg)
                    {
                        namedArgs.append
                        (
                            Tuple2<word, string>
                            (
                                argName,
                                funcNameArgs(start, i - start)
                            )
                        );
                        namedArg = false;
                    }
                    else
                    {
                        args.append
                        (
                            string::validate<word>(funcNameArgs(start, i - start))
                        );
                    }
    
                    if (argLevel == 1)
                    {
                        break;
                    }
                    --argLevel;
    
            }
            else if (c == '=')
            {
                argName = string::validate<word>(funcNameArgs(start, i - start));
                start = i+1;
                namedArg = true;
    
            }
    
            ++i;
        }
    
        // Search for the functionObject dictionary
        fileName path = findDict(funcName);
    
        if (path == fileName::null)
        {
            WarningInFunction
                << "Cannot find functionObject file " << funcName << endl;
    
        }
    
        // Read the functionObject dictionary
        IFstream fileStream(path);
        dictionary funcsDict(fileStream);
    
        dictionary* funcDictPtr = &funcsDict;
    
        if (funcsDict.found(funcName) && funcsDict.isDict(funcName))
        {
            funcDictPtr = &funcsDict.subDict(funcName);
        }
    
        dictionary& funcDict = *funcDictPtr;
    
        // Insert the 'field' and/or 'fields' entry corresponding to the optional
    
        // arguments or read the 'field' or 'fields' entry and add the required
    
        if (args.size() == 1)
        {
            funcDict.set("field", args[0]);
    
            funcDict.set("fields", args);
    
        }
        else if (args.size() > 1)
        {
            funcDict.set("fields", args);
    
            requiredFields.insert(word(funcDict.lookup("field")));
    
        }
        else if (funcDict.found("fields"))
        {
    
            requiredFields.insert(wordList(funcDict.lookup("fields")));
    
        // Insert named arguments
        forAll(namedArgs, i)
        {
            IStringStream entryStream
            (
                namedArgs[i].first() + ' ' + namedArgs[i].second() + ';'
            );
            funcDict.set(entry::New(entryStream).ptr());
        }
    
    
        // Merge this functionObject dictionary into functionsDict
        dictionary funcArgsDict;
    
        funcArgsDict.add(string::validate<word>(funcNameArgs), funcDict);
    
        functionsDict.merge(funcArgsDict);
    
        return true;
    
    // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
    
    Foam::functionObjectList::functionObjectList
    (
        const Time& t,
        const bool execution
    )
    :
    
        PtrList<functionObject>(),
        digests_(),
    
        parentDict_(t.controlDict()),
        execution_(execution),
        updated_(false)
    
    {}
    
    
    Foam::functionObjectList::functionObjectList
    (
        const Time& t,
    
        const dictionary& parentDict,
    
        PtrList<functionObject>(),
        digests_(),
    
        parentDict_(parentDict),
        execution_(execution),
        updated_(false)
    
    Foam::autoPtr<Foam::functionObjectList> Foam::functionObjectList::New
    (
        const argList& args,
        const Time& runTime,
    
        dictionary& controlDict,
        HashSet<word>& requiredFields
    
        autoPtr<functionObjectList> functionsPtr;
    
    
            dictionaryEntry("functions", controlDict, dictionary::null)
    
        dictionary& functionsDict = controlDict.subDict("functions");
    
    
        if
        (
            args.optionFound("dict")
         || args.optionFound("func")
         || args.optionFound("funcs")
        )
    
                    IOdictionary
                    (
                        IOobject
                        (
                            args["dict"],
                            runTime,
                            IOobject::MUST_READ_IF_MODIFIED
                        )
                    )
                );
            }
    
            if (args.optionFound("func"))
            {
    
                readFunctionObject(args["func"], functionsDict, requiredFields);
    
            }
    
            if (args.optionFound("funcs"))
            {
                wordList funcs(args.optionLookup("funcs")());
    
                forAll(funcs, i)
                {
    
                    readFunctionObject(funcs[i], functionsDict, requiredFields);
    
            functionsPtr.reset(new functionObjectList(runTime, controlDict));
    
            functionsPtr.reset(new functionObjectList(runTime));
    
        functionsPtr->start();
    
        return functionsPtr;
    
    // * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
    
    Foam::functionObjectList::~functionObjectList()
    {}
    
    
    // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
    
    
    void Foam::functionObjectList::clear()
    {
        PtrList<functionObject>::clear();
        digests_.clear();
        indices_.clear();
        updated_ = false;
    }
    
    
    
    Foam::label Foam::functionObjectList::findObjectID(const word& name) const
    {
        forAll(*this, objectI)
        {
            if (operator[](objectI).name() == name)
            {
                return objectI;
            }
        }
    
        return -1;
    }
    
    
    
    void Foam::functionObjectList::on()
    {
        execution_ = true;
    }
    
    
    void Foam::functionObjectList::off()
    {
    
        // For safety, also force a read() when execution is turned back on
    
        updated_ = execution_ = false;
    }
    
    
    bool Foam::functionObjectList::status() const
    {
        return execution_;
    }
    
    
    
    bool Foam::functionObjectList::start()
    {
    
        return read();
    
    bool Foam::functionObjectList::execute()
    
            if (!updated_)
    
            forAll(*this, objectI)
    
                ok = operator[](objectI).execute() && ok;
                ok = operator[](objectI).write() && ok;
    
    bool Foam::functionObjectList::end()
    {
        bool ok = true;
    
        if (execution_)
        {
            if (!updated_)
            {
                read();
            }
    
    
            forAll(*this, objectI)
    
                ok = operator[](objectI).end() && ok;
    
    bool Foam::functionObjectList::adjustTimeStep()
    {
        bool ok = true;
    
        if (execution_)
        {
            if (!updated_)
            {
                read();
            }
    
            forAll(*this, objectI)
            {
                ok = operator[](objectI).adjustTimeStep() && ok;
            }
        }
    
        return ok;
    }
    
    
    
    bool Foam::functionObjectList::read()
    {
    
        bool ok = true;
        updated_ = execution_;
    
    
        // Avoid reading/initializing if execution is off
    
        if (!execution_)
        {
    
        // Update existing and add new functionObjects
    
        const entry* entryPtr = parentDict_.lookupEntryPtr
        (
            "functions",
            false,
            false
        );
    
    
        if (entryPtr)
    
            PtrList<functionObject> newPtrs;
    
            List<SHA1Digest> newDigs;
    
            HashTable<label> newIndices;
    
            label nFunc = 0;
    
                FatalIOErrorInFunction(parentDict_)
                    << "'functions' entry is not a dictionary"
                    << exit(FatalIOError);
            }
    
    
            const dictionary& functionsDict = entryPtr->dict();
    
            const_cast<Time&>(time_).libs().open
            (
                functionsDict,
                "libs",
                functionObject::dictionaryConstructorTablePtr_
            );
    
            newPtrs.setSize(functionsDict.size());
            newDigs.setSize(functionsDict.size());
    
            forAllConstIter(dictionary, functionsDict, iter)
    
            {
                const word& key = iter().keyword();
    
                if (!iter().isDict())
    
                    if (key != "libs")
                    {
                        IOWarningInFunction(parentDict_)
                            << "Entry " << key << " is not a dictionary" << endl;
                    }
    
    
                    continue;
                }
    
                const dictionary& dict = iter().dict();
                bool enabled = dict.lookupOrDefault("enabled", true);
    
                label oldIndex;
                functionObject* objPtr = remove(key, oldIndex);
    
                if (objPtr)
                {
                    if (enabled)
    
                        // Dictionary changed for an existing functionObject
    
                        if (newDigs[nFunc] != digests_[oldIndex])
                        {
                            ok = objPtr->read(dict) && ok;
                        }
    
                        // Delete the disabled functionObject
                        delete objPtr;
    
                    FatalError.throwExceptions();
                    FatalIOError.throwExceptions();
                    try
    
                        if
                        (
                            dict.found("writeControl")
                         || dict.found("outputControl")
                        )
                        {
                            foPtr.set
                            (
                                new functionObjects::timeControl(key, time_, dict)
                            );
                        }
                        else
                        {
                            foPtr = functionObject::New(key, time_, dict);
                        }
    
                    catch (Foam::IOerror& ioErr)
                    {
                        Info<< ioErr << nl << endl;
                        ::exit(1);
                    }
                    catch (Foam::error& err)
                    {
                        WarningInFunction
                            << "Caught FatalError " << err << nl << endl;
                    }
    
                    FatalError.dontThrowExceptions();
                    FatalIOError.dontThrowExceptions();
    
                    if (foPtr.valid())
    
                // Insert active functionObjects into the list
                if (objPtr)
                {
    
                    newPtrs.set(nFunc, objPtr);
                    newIndices.insert(key, nFunc);
                    nFunc++;
    
    
            newPtrs.setSize(nFunc);
    
            newDigs.setSize(nFunc);
    
            // Updating the PtrList of functionObjects deletes any
            // existing unused functionObjects
    
            PtrList<functionObject>::transfer(newPtrs);
    
            digests_.transfer(newDigs);
    
            indices_.transfer(newIndices);
    
            PtrList<functionObject>::clear();
    
            digests_.clear();
    
            indices_.clear();
    
    void Foam::functionObjectList::updateMesh(const mapPolyMesh& mpm)
    {
        if (execution_)
        {
            forAll(*this, objectI)
            {
                operator[](objectI).updateMesh(mpm);
            }
        }
    }
    
    
    void Foam::functionObjectList::movePoints(const polyMesh& mesh)
    {
        if (execution_)
        {
            forAll(*this, objectI)
            {
                operator[](objectI).movePoints(mesh);
            }
        }
    }
    
    
    
    // ************************************************************************* //