From f94d724a931e2ceb7123088724441b5edb19c7ba Mon Sep 17 00:00:00 2001 From: Mark Olesen Date: Sun, 11 Nov 2018 19:00:54 +0100 Subject: [PATCH] ENH: add objectRegistry::count() methods - can be useful for obtaining information about number of fields. Eg, nScalar = mesh.count(wordre); --- applications/test/objectRegistry2/Make/files | 3 + .../test/objectRegistry2/Make/options | 8 + .../objectRegistry2/Test-objectRegistry2.C | 307 ++++++++++++++++++ .../db/objectRegistry/objectRegistry.C | 7 + .../db/objectRegistry/objectRegistry.H | 58 ++++ .../objectRegistry/objectRegistryTemplates.C | 130 +++++++- 6 files changed, 501 insertions(+), 12 deletions(-) create mode 100644 applications/test/objectRegistry2/Make/files create mode 100644 applications/test/objectRegistry2/Make/options create mode 100644 applications/test/objectRegistry2/Test-objectRegistry2.C diff --git a/applications/test/objectRegistry2/Make/files b/applications/test/objectRegistry2/Make/files new file mode 100644 index 0000000000..208771853c --- /dev/null +++ b/applications/test/objectRegistry2/Make/files @@ -0,0 +1,3 @@ +Test-objectRegistry2.C + +EXE = $(FOAM_USER_APPBIN)/Test-objectRegistry2 diff --git a/applications/test/objectRegistry2/Make/options b/applications/test/objectRegistry2/Make/options new file mode 100644 index 0000000000..969020c4af --- /dev/null +++ b/applications/test/objectRegistry2/Make/options @@ -0,0 +1,8 @@ +EXE_INC = \ + -I$(LIB_SRC)/finiteVolume/lnInclude \ + -I$(LIB_SRC)/meshTools/lnInclude + +EXE_LIBS = \ + -lfiniteVolume \ + -lmeshTools \ + -lgenericPatchFields diff --git a/applications/test/objectRegistry2/Test-objectRegistry2.C b/applications/test/objectRegistry2/Test-objectRegistry2.C new file mode 100644 index 0000000000..eab159ccfc --- /dev/null +++ b/applications/test/objectRegistry2/Test-objectRegistry2.C @@ -0,0 +1,307 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2018 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 . + +Application + Test-objectRegistry2 + +Description + Print objectRegistry information, with some additional tests. + +\*---------------------------------------------------------------------------*/ + +#include "argList.H" +#include "Time.H" +#include "fvCFD.H" +#include "fvMesh.H" +#include "volFields.H" +#include "IOobjectList.H" +#include "timeSelector.H" +#include "ReadFields.H" +#include "IOstreams.H" + +using namespace Foam; + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +template +bool loadField(fvMesh& mesh, const word& fieldName) +{ + typedef GeometricField VolFieldType; + typedef GeometricField SurfaceFieldType; + + if (mesh.objectRegistry::found(fieldName)) + { + // Info<< fieldName << " already in database" << endl; + return false; + } + + IOobject fieldHeader + ( + fieldName, + mesh.time().timeName(), + mesh, + IOobject::MUST_READ, + IOobject::NO_WRITE + ); + + if (fieldHeader.typeHeaderOk(true, true, false)) + { + // Store field on mesh database + VolFieldType* ptr = new VolFieldType(fieldHeader, mesh); + mesh.objectRegistry::store(ptr); + return true; + } + else if (fieldHeader.typeHeaderOk(true, true, false)) + { + // Store field on mesh database + SurfaceFieldType* ptr = new SurfaceFieldType(fieldHeader, mesh); + mesh.objectRegistry::store(ptr); + return true; + } + + return false; +} + + +bool loadField(fvMesh& mesh, const word& fieldName) +{ + return + ( + !mesh.objectRegistry::found(fieldName) + && + ( + loadField(mesh, fieldName) + || loadField(mesh, fieldName) + || loadField(mesh, fieldName) + || loadField(mesh, fieldName) + || loadField(mesh, fieldName) + ) + ); +} + + +void loadFields(fvMesh& mesh, const IOobjectList& objects) +{ + for (const word& fieldName : objects.names()) + { + loadField(mesh, fieldName); + } +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +void printRegistry +( + Foam::Ostream& os, + const Foam::objectRegistry& obr, + Foam::label indent = 4 +); + + +void printRegistry +( + Foam::Ostream& os, + const Foam::objectRegistry& obr, + Foam::label indent +) +{ + wordList names(obr.sortedNames()); + wordList regs(obr.sortedNames()); + + std::string prefix; + for (label i=indent; i; --i) + { + prefix += ' '; + } + + os << '#' << prefix.c_str() << obr.name() + << " parent:" << obr.parent().name() << nl; + + os << ' ' << prefix.c_str() << "objects: " << flatOutput(names) << nl; + os << ' ' << prefix.c_str() << "registries: " << flatOutput(regs) << nl; + + + // Print, but skip expansion of sub-registries for now + for (const word& name : names) + { + os << (regs.found(name) ? '-' : ' ') + << prefix.c_str() << name << " => " << obr[name]->type() << nl; + } + for (label i=indent; i; --i) + { + os << '-'; // divider + } + os << '\n'; + + // Now descend into the sub-registries + for (const word& name : regs) + { + const objectRegistry& next = obr.lookupObject + ( + name, + false // non-recursive + ); + + os << prefix.c_str() + << "current:" << obr.name() << " next:" + << next.name() << " next-parent:" << next.parent().name() << nl; + + os << prefix.c_str() << name << " => " << obr[name]->type(); + + if ("dictionary" == obr[name]->type()) + { + os << " (skip dictionary)" << nl; + } + else + { + os << nl; + printRegistry(os, next, indent + 4); + } + } +} + + +template +void filterTest(const objectRegistry& obr, const wordRe& re) +{ + Info<< nl << "Filter on names:" << nl; + + Info<< "Filter = " << re << nl; + + const word& typeName = Type::typeName; + + Info<< " <" << typeName <<">(" << re << ") : " + << obr.count(re) << nl + << " (" << typeName << "::typeName, " << re << ") : " + << obr.count(typeName, re) << nl; + + Info<< " <" << typeName << ">(" << re << ") : " + << flatOutput(obr.sortedNames(re)) << nl + // << flatOutput(obr.names(re)) << nl + << " (" << typeName << "::typeName, " << re << ") : " + << flatOutput(obr.sortedNames(typeName, re)) << nl + //<< flatOutput(obr.names(typeName, re)) << nl + ; + + + wordRe reClass("vol.*Field", wordRe::REGEX); + wordRe re2(re, wordRe::REGEX_ICASE); + + Info<< "General" << nl + << " (" << re << ") : " + << flatOutput(obr.sortedNames(re)) << nl + << " (" << reClass << ", " << re2 <<" ignore-case) : " + << flatOutput(obr.sortedNames(reClass, re2)) << nl + ; + + Info<< nl; +} + + +void registryTests(const objectRegistry& obr) +{ + Info<< nl << "Registry: " << obr.name() << nl + << " names: " << flatOutput(obr.sortedNames()) << nl; + + Info<< "count" << nl + << " () : " << obr.count() << nl + << " () : " << obr.count() << nl + << " (strict) : " << obr.count(true) << nl + << " () : " << obr.count() << nl + << " (strict) : " << obr.count(true) << nl; + Info<< " () : " + << obr.count() << nl + << " (volScalarField::typeName) : " + << obr.count(volScalarField::typeName) << nl; + Info<< " () : " + << obr.count() << nl + << " (volVectorField::typeName) : " + << obr.count(volVectorField::typeName) << nl; + + Info<< nl << "Filter on names:" << nl; + + filterTest(obr, wordRe("[p-z].*", wordRe::DETECT)); + + Info<< nl; +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// Main program: + +int main(int argc, char *argv[]) +{ + argList::noBanner(); + argList::noParallel(); +// argList::addOption +// ( +// "filter", +// "wordRes", +// "filter keys with names or regexs" +// ); + + // timeSelector::addOptions(); + timeSelector::addOptions(true, true); + + #include "setRootCase.H" + +// wordRes matcher; +// if (args.readListIfPresent("filter", matcher)) +// { +// Info<<"limit names: " << matcher << nl; +// } + + #include "createTime.H" + #include "createMesh.H" + + instantList timeDirs = timeSelector::select0(runTime, args); + + forAll(timeDirs, timeI) + { + runTime.setTime(timeDirs[timeI], timeI); + + Info<< "Time: " << runTime.timeName() << endl; + + // Read objects in time directory + IOobjectList objects(mesh, runTime.timeName()); + + // Read volFields + loadFields(mesh, objects); + + printRegistry(Info, mesh); + + registryTests(mesh); + + Info<< nl; + } + + + Info<<"\nEnd\n" << endl; + + return 0; +} + + +// ************************************************************************* // diff --git a/src/OpenFOAM/db/objectRegistry/objectRegistry.C b/src/OpenFOAM/db/objectRegistry/objectRegistry.C index d2b0a1a2c6..a747de2c83 100644 --- a/src/OpenFOAM/db/objectRegistry/objectRegistry.C +++ b/src/OpenFOAM/db/objectRegistry/objectRegistry.C @@ -111,6 +111,13 @@ Foam::HashTable Foam::objectRegistry::classes() const } +Foam::label Foam::objectRegistry::count(const char* clsName) const +{ + // No nullptr check - only called with string literals + return count(static_cast(clsName)); +} + + Foam::wordList Foam::objectRegistry::names() const { return HashTable::toc(); diff --git a/src/OpenFOAM/db/objectRegistry/objectRegistry.H b/src/OpenFOAM/db/objectRegistry/objectRegistry.H index 30c03f8e31..d05f5edf0a 100644 --- a/src/OpenFOAM/db/objectRegistry/objectRegistry.H +++ b/src/OpenFOAM/db/objectRegistry/objectRegistry.H @@ -81,6 +81,25 @@ class objectRegistry // Used to terminate searching within the ancestors bool parentNotTime() const; + //- Templated implementation for count() + // The number of items with a matching class + template + static label countImpl + ( + const objectRegistry& list, + const MatchPredicate1& matchClass, + const MatchPredicate2& matchName + ); + + //- Templated implementation for count() + // The number of items with a matching class + template + static label countTypeImpl + ( + const objectRegistry& list, + const MatchPredicate& matchName + ); + //- Templated implementation for classes() template static HashTable classesImpl @@ -173,6 +192,45 @@ public: HashTable classes(const MatchPredicate& matchName) const; + // Number of items + + //- The number of objects of the given class name + // \note uses the class type() method + label count(const char* clsName) const; + + //- The number of objects of the given class name + // \note uses the class type() method + template + label count(const MatchPredicate& matchClass) const; + + //- The number of objects of the given class name + // \note uses the class type() method + template + label count + ( + const MatchPredicate1& matchClass, + const MatchPredicate2& matchName + ) const; + + //- The names of objects with a class satisfying \c isA\ + // + // \param strict use \c isType\ instead of \c isA\ + // + // \note The values of \c count\() and \c count(Type::typeName) + // may be inconsistent, since they use different mechanisms for + // testing the class type. + // \note If \a Type is \c void, no isA check is used (always true). + template + label count(const bool strict = false) const; + + //- The names of objects with a class satisfying \c isA\ + //- that also have a matching object name. + // + // \note If \a Type is \c void, no isA check is used (always true). + template + label count(const MatchPredicate& matchName) const; + + // Summary of names //- The names of all objects diff --git a/src/OpenFOAM/db/objectRegistry/objectRegistryTemplates.C b/src/OpenFOAM/db/objectRegistry/objectRegistryTemplates.C index c63ff76ace..e75a304eda 100644 --- a/src/OpenFOAM/db/objectRegistry/objectRegistryTemplates.C +++ b/src/OpenFOAM/db/objectRegistry/objectRegistryTemplates.C @@ -55,6 +55,59 @@ Foam::HashTable Foam::objectRegistry::classesImpl } +// Templated implementation for count() +template +Foam::label Foam::objectRegistry::countImpl +( + const objectRegistry& list, + const MatchPredicate1& matchClass, + const MatchPredicate2& matchName +) +{ + label count = 0; + + forAllConstIters(list, iter) + { + const regIOobject* obj = iter.object(); + + if (matchClass(obj->type()) && matchName(obj->name())) + { + ++count; + } + } + + return count; +} + + +// Templated implementation for count() +template +Foam::label Foam::objectRegistry::countTypeImpl +( + const objectRegistry& list, + const MatchPredicate& matchName +) +{ + label count = 0; + + forAllConstIters(list, iter) + { + const regIOobject* obj = iter.object(); + + if + ( + (std::is_void::value || isA(*obj)) + && matchName(obj->name()) + ) + { + ++count; + } + } + + return count; +} + + // Templated implementation for names(), sortedNames() template Foam::wordList Foam::objectRegistry::namesImpl @@ -141,6 +194,63 @@ Foam::objectRegistry::classes } +template +Foam::label Foam::objectRegistry::count +( + const MatchPredicate& matchClass +) const +{ + return countImpl(*this, matchClass, predicates::always()); +} + + +template +Foam::label Foam::objectRegistry::count +( + const MatchPredicate1& matchClass, + const MatchPredicate2& matchName +) const +{ + return countImpl(*this, matchClass, matchName); +} + + +template +Foam::label Foam::objectRegistry::count +( + const MatchPredicate& matchName +) const +{ + return countTypeImpl(*this, matchName); +} + + +template +Foam::label Foam::objectRegistry::count +( + const bool strict +) const +{ + label nObjects = 0; + + forAllConstIters(*this, iter) + { + const regIOobject* obj = iter.object(); + + if + ( + std::is_void::value + || (strict ? isType(*obj) : bool(isA(*obj))) + ) + { + ++nObjects; + } + } + + return nObjects; +} + + template Foam::wordList Foam::objectRegistry::names ( @@ -227,13 +337,11 @@ Foam::HashTable Foam::objectRegistry::lookupClass forAllConstIters(*this, iter) { - if (strict ? isType(*iter()) : bool(isA(*iter()))) + const regIOobject* obj = iter.object(); + + if (strict ? isType(*obj) : bool(isA(*obj))) { - objectsOfClass.insert - ( - iter()->name(), - dynamic_cast(iter()) - ); + objectsOfClass.insert(obj->name(), dynamic_cast(obj)); } } @@ -251,13 +359,11 @@ Foam::HashTable Foam::objectRegistry::lookupClass forAllIters(*this, iter) { - if (strict ? isType(*iter()) : bool(isA(*iter()))) + regIOobject* obj = iter.object(); + + if (strict ? isType(*obj) : bool(isA(*obj))) { - objectsOfClass.insert - ( - iter()->name(), - dynamic_cast(iter()) - ); + objectsOfClass.insert(obj->name(), dynamic_cast(obj)); } }