Commit 9761e9d8 authored by Mark OLESEN's avatar Mark OLESEN
Browse files

ENH: added classes() method to objectRegistry/IOobjectList

- provides a summary hash of classes used and their associated object names.

  The HashTable representation allows us to leverage various HashTable
  methods. This hashed summary view can be useful when querying
  particular aspects, but is most useful when reducing the objects in
  consideration to a particular subset. For example,

      const wordHashSet interestingTypes
      {
          volScalarField::typeName,
          volVectorField::typeName
      };

      IOobjectList objects(runTime, runTime.timeName());
      HashTable<wordHashSet> classes = objects.classes();

      classes.retain(interestingTypes);

      // Or do just the opposite:
      classes.erase(unsupportedTypes);

  Can also use the underlying HashTable filter methods

STYLE: use templated internals to avoid findString() when matching subsets
parent cf889306
Test-IOobjectList.C
EXE = $(FOAM_USER_APPBIN)/Test-IOobjectList
EXE_INC = -I$(LIB_SRC)/finiteVolume/lnInclude
EXE_LIBS = -lfiniteVolume
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2017 OpenCFD Ltd.
\\/ 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/>.
Description
Basic tests of IOobjectList
\*---------------------------------------------------------------------------*/
#include "argList.H"
#include "Time.H"
#include "volFields.H"
#include "timeSelector.H"
#include "IOobjectList.H"
#include "hashedWordList.H"
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:
int main(int argc, char *argv[])
{
argList::noParallel();
argList::addOption("re", "wordReList");
// timeSelector::addOptions();
timeSelector::addOptions(true, true);
#include "setRootCase.H"
#include "createTime.H"
wordReList matcher;
if (args.optionFound("re"))
{
matcher = args.optionReadList<wordRe>("re");
Info<<"limit names: " << matcher << nl;
}
const hashedWordList subsetTypes
{
volScalarField::typeName,
volScalarField::Internal::typeName,
volVectorField::typeName,
};
instantList timeDirs = timeSelector::select0(runTime, args);
forAll(timeDirs, timeI)
{
runTime.setTime(timeDirs[timeI], timeI);
// Objects at this time
IOobjectList objects(runTime, runTime.timeName());
HashTable<wordHashSet> classes =
(
matcher.size()
? objects.classes(matcher)
: objects.classes()
);
Info<< "Time: " << runTime.timeName() << nl;
Info<<"Name: " << flatOutput(objects.sortedNames()) << nl
<<"Objects: " << objects << nl
<<"Classes: " << classes << nl;
classes.filterKeys(subsetTypes);
Info<<"only retain: " << flatOutput(subsetTypes) << nl;
Info<<"Pruned: " << classes << nl;
classes = objects.classes();
classes.erase(subsetTypes);
Info<<"remove: " << flatOutput(subsetTypes) << nl;
Info<<"Pruned: " << classes << nl;
}
Info<< "\nEnd\n" << endl;
return 0;
}
// ************************************************************************* //
......@@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd.
\\/ M anipulation | Copyright (C) 2016-2017 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
......@@ -27,7 +27,99 @@ License
#include "Time.H"
#include "OSspecific.H"
#include "IOList.H"
#include "stringListOps.H"
#include "predicates.H"
// * * * * * * * * * * * * * * Static Functions * * * * * * * * * * * * * //
namespace Foam
{
// Templated implementation for lookup() - file-scope
template<class UnaryMatchPredicate>
static IOobjectList lookupImpl
(
const IOobjectList& list,
const UnaryMatchPredicate& matcher
)
{
IOobjectList results(list.size());
forAllConstIters(list, iter)
{
if (matcher(iter.key()))
{
if (IOobject::debug)
{
InfoInFunction << "Found " << iter.key() << endl;
}
results.insert
(
iter.key(),
new IOobject(*(iter.object()))
);
}
}
return results;
}
// Templated implementation for classes() - file-scope
template<class UnaryMatchPredicate>
static HashTable<wordHashSet> classesImpl
(
const IOobjectList& list,
const UnaryMatchPredicate& matcher
)
{
HashTable<wordHashSet> summary(2*list.size());
// Summary (key,val) = (class-name, object-names)
forAllConstIters(list, iter)
{
if (matcher(iter.key()))
{
// Create entry (if needed) and insert
summary(iter.object()->headerClassName()).insert(iter.key());
}
}
return summary;
}
// Templated implementation for names(), sortedNames() - file-scope
template<class UnaryMatchPredicate>
static wordList namesImpl
(
const IOobjectList& list,
const word& clsName,
const UnaryMatchPredicate& matcher,
const bool doSort
)
{
wordList objNames(list.size());
label count = 0;
forAllConstIters(list, iter)
{
if (iter()->headerClassName() == clsName && matcher(iter.key()))
{
objNames[count++] = iter.key();
}
}
objNames.setSize(count);
if (doSort)
{
Foam::sort(objNames);
}
return objNames;
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
......@@ -62,14 +154,14 @@ Foam::IOobjectList::IOobjectList
}
// Create a list of file names in this directory
fileNameList ObjectNames =
fileNameList objNames =
readDir(db.path(newInstance, db.dbDir()/local), fileName::FILE);
forAll(ObjectNames, i)
forAll(objNames, i)
{
IOobject* objectPtr = new IOobject
(
ObjectNames[i],
objNames[i],
newInstance,
local,
db,
......@@ -81,7 +173,7 @@ Foam::IOobjectList::IOobjectList
// Use object with local scope
if (objectPtr->typeHeaderOk<IOList<label>>(false))
{
insert(ObjectNames[i], objectPtr);
insert(objectPtr->name(), objectPtr);
}
else
{
......@@ -119,7 +211,7 @@ bool Foam::IOobjectList::remove(IOobject& io)
Foam::IOobject* Foam::IOobjectList::lookup(const word& name) const
{
HashPtrTable<IOobject>::const_iterator iter = find(name);
const_iterator iter = find(name);
if (iter.found())
{
......@@ -144,38 +236,23 @@ Foam::IOobject* Foam::IOobjectList::lookup(const word& name) const
Foam::IOobjectList Foam::IOobjectList::lookup(const wordRe& matcher) const
{
IOobjectList results(size());
forAllConstIters(*this, iter)
{
if (matcher.match(iter.key()))
{
if (IOobject::debug)
{
InfoInFunction << "Found " << iter.key() << endl;
}
return lookupImpl(*this, matcher);
}
results.insert
(
iter.key(),
new IOobject(*(iter.object()))
);
}
}
return results;
Foam::IOobjectList Foam::IOobjectList::lookup(const wordRes& matcher) const
{
return lookupImpl(*this, matcher);
}
Foam::IOobjectList Foam::IOobjectList::lookup(const wordReList& matcher) const
Foam::IOobjectList Foam::IOobjectList::lookupClass(const word& clsName) const
{
wordRes mat(matcher);
IOobjectList results(size());
forAllConstIters(*this, iter)
{
if (mat.match(iter.key()))
if (iter()->headerClassName() == clsName)
{
if (IOobject::debug)
{
......@@ -194,28 +271,23 @@ Foam::IOobjectList Foam::IOobjectList::lookup(const wordReList& matcher) const
}
Foam::IOobjectList Foam::IOobjectList::lookupClass(const word& clsName) const
Foam::HashTable<Foam::wordHashSet> Foam::IOobjectList::classes() const
{
IOobjectList results(size());
return classesImpl(*this, predicates::always());
}
forAllConstIters(*this, iter)
{
if (iter()->headerClassName() == clsName)
{
if (IOobject::debug)
{
InfoInFunction << "Found " << iter.key() << endl;
}
results.insert
(
iter.key(),
new IOobject(*(iter.object()))
);
}
}
Foam::HashTable<Foam::wordHashSet>
Foam::IOobjectList::classes(const wordRe& matcher) const
{
return classesImpl(*this, matcher);
}
return results;
Foam::HashTable<Foam::wordHashSet>
Foam::IOobjectList::classes(const wordRes& matcher) const
{
return classesImpl(*this, matcher);
}
......@@ -236,20 +308,7 @@ Foam::wordList Foam::IOobjectList::names
const word& clsName
) const
{
wordList objNames(size());
label count = 0;
forAllConstIters(*this, iter)
{
if (iter()->headerClassName() == clsName)
{
objNames[count++] = iter.key();
}
}
objNames.setSize(count);
return objNames;
return namesImpl(*this, clsName, predicates::always(), false);
}
......@@ -259,21 +318,17 @@ Foam::wordList Foam::IOobjectList::names
const wordRe& matcher
) const
{
wordList objNames = names(clsName);
return wordList(objNames, findStrings(matcher, objNames));
return namesImpl(*this, clsName, matcher, false);
}
Foam::wordList Foam::IOobjectList::names
(
const word& clsName,
const wordReList& matcher
const wordRes& matcher
) const
{
wordList objNames = names(clsName);
return wordList(objNames, findStrings(matcher, objNames));
return namesImpl(*this, clsName, matcher, false);
}
......@@ -282,10 +337,7 @@ Foam::wordList Foam::IOobjectList::sortedNames
const word& clsName
) const
{
wordList sortedLst = names(clsName);
sort(sortedLst);
return sortedLst;
return namesImpl(*this, clsName, predicates::always(), true);
}
......@@ -295,23 +347,35 @@ Foam::wordList Foam::IOobjectList::sortedNames
const wordRe& matcher
) const
{
wordList sortedLst = names(clsName, matcher);
sort(sortedLst);
return sortedLst;
return namesImpl(*this, clsName, matcher, true);
}
Foam::wordList Foam::IOobjectList::sortedNames
(
const word& clsName,
const wordReList& matcher
const wordRes& matcher
) const
{
wordList sortedLst = names(clsName, matcher);
sort(sortedLst);
return namesImpl(*this, clsName, matcher, true);
}
// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
Foam::Ostream& Foam::operator<<(Ostream& os, const IOobjectList& list)
{
os << nl << list.size() << nl << token::BEGIN_LIST << nl;
forAllConstIters(list, it)
{
os << it.key() << token::SPACE << it.object()->headerClassName() << nl;
}
os << token::END_LIST;
os.check(FUNCTION_NAME);
return sortedLst;
return os;
}
......
......@@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd.
\\/ M anipulation | Copyright (C) 2016-2017 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
......@@ -36,14 +36,20 @@ SourceFiles
#define IOobjectList_H
#include "HashPtrTable.H"
#include "HashSet.H"
#include "IOobject.H"
#include "wordReList.H"
#include "wordRes.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// Forward declaration of friend functions and operators
class IOobjectList;
Ostream& operator<<(Ostream& os, const IOobjectList& list);
/*---------------------------------------------------------------------------*\
Class IOobjectList Declaration
\*---------------------------------------------------------------------------*/
......@@ -86,12 +92,17 @@ public:
// Member functions
// Basic methods
//- Add an IOobject to the list
bool add(IOobject& io);
//- Remove an IOobject from the list
bool remove(IOobject& io);
// Lookup
//- Lookup a given name and return IOobject ptr if found else nullptr
IOobject* lookup(const word& name) const;
......@@ -99,12 +110,94 @@ public:
IOobjectList lookup(const wordRe& matcher) const;
//- The list of all IOobjects with matching names
IOobjectList lookup(const wordReList& matcher) const;
IOobjectList lookup(const wordRes& matcher) const;
//- The list of all IOobjects with the given class name
IOobjectList lookupClass(const word& clsName) const;
// Summary of classes
//- A summary hash of classes used and their associated object names.
// The HashTable representation allows us to leverage various
// HashTable methods.
// This hashed summary view can be useful when querying particular
// aspects. For example,
//
// \code
// IOobjectList objects(runTime, runTime.timeName());
// HashTable<wordHashSet> classes = objects.classes();
//
// // How many volScalarField?
// word checkType = volScalarField::typeName;
//
// Info<< checkType << "="
// << (classes.found(checkType) ? classes[checkType].size() : 0)
// << nl;
// \endcode
// Using the two-parameter HashTable::lookup method lets us avoid
// the \c '?' ternary, but still looks fairly ugly:
// \code
// Info<< checkType << "="
// << classes.lookup(checkType, wordHashSet()).size() << nl;
// \endcode
//
// If we have non-const access to the hash table, and don't mind
// incidentally creating empty entries,
// we can use the HashTable::operator() directly:
// \code
// Info<< checkType << "=" << classes(checkType).size() << nl;
// \endcode
//
// Of course, for a single query it would have been easier
// and simpler to have used a direct query of the names:
// \code
// Info<< checkType << "=" << objects.names(checkType).size() << nl;
// \endcode
//
// The summary hash, however, becomes most useful when reducing
// the objects in consideration to a particular subset. For example,
// \code
// const wordHashSet interestingTypes
// {
// volScalarField::typeName,
// volVectorField::typeName
// };
//
// classes.retain(interestingTypes);
// \endcode
// Or do just the opposite:
// \code
// classes.erase(unsupportedTypes);
// \endcode
// This also works with a hashedWordList, since it provides the
// expected '()' operator. But in this case the more general
// HashTable::filterKeys is required:
// \code
// const hashedWordList interestingTypes
// {
// volScalarField::typeName,
// volVectorField::typeName
// };
//
// classes.filterKeys(interestingTypes);
// \endcode
//
// Of course, there are many other ways to use and manipulate the
// summary information.
HashTable<wordHashSet> classes() const;
//- A summary hash of classes used and their associated object names
// restricted to objects with names that satisfy the input matcher
HashTable<wordHashSet> classes(const wordRe& matcher) const;
//- A summary hash of classes used and their associated object names
// restricted to objects with names that satisfy the input matcher
HashTable<wordHashSet> classes(const wordRes& matcher) const;
// Summary of names
//- A list of names of the IOobjects
wordList names() const;
......@@ -117,9 +210,11 @@ public:
//- The names of IOobjects with the given class name that also
// have a name satisfying the input matcher
wordList names(const word& clsName, const wordReList& matcher) const;
wordList names(const word& clsName, const wordRes& matcher) const;
// Summary of names (sorted)
//- A sorted list of names of the IOobjects
wordList sortedNames() const;
......@@ -132,11 +227,12 @@ public:
//- The sorted names of IOobjects with the given class name that also
// have a name satisfying the input matcher
wordList sortedNames
(
const word& clsName,
const wordReList& matcher
) const;
wordList sortedNames(const word& clsName, const wordRes& matcher) const;
// Ostream Operator
friend Ostream& operator<<(Ostream& os, const IOobjectList& list);
};