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));
}
}