diff --git a/src/OpenFOAM/db/IOobjectList/IOobjectList.C b/src/OpenFOAM/db/IOobjectList/IOobjectList.C
index 95f84c49c1a19b27964f2c50c5189977b6fbe5e4..9b6824f85698c2cd6b916a77283e84f4438775de 100644
--- a/src/OpenFOAM/db/IOobjectList/IOobjectList.C
+++ b/src/OpenFOAM/db/IOobjectList/IOobjectList.C
@@ -33,7 +33,8 @@ License
 
 bool Foam::IOobjectList::checkNames(wordList& masterNames, const bool syncPar)
 {
-    // Sort for consistent order on all processors
+    // Sort for consistent order on all processors.
+    // Even do this for serial runs, for consistent behaviour
     Foam::sort(masterNames);
 
     if (syncPar && Pstream::parRun())
@@ -273,6 +274,13 @@ Foam::HashTable<Foam::wordHashSet> Foam::IOobjectList::classes() const
 }
 
 
+Foam::label Foam::IOobjectList::count(const char* clsName) const
+{
+    // No nullptr check - only called with string literals
+    return count(static_cast<word>(clsName));
+}
+
+
 Foam::wordList Foam::IOobjectList::names() const
 {
     return HashPtrTable<IOobject>::toc();
@@ -348,6 +356,41 @@ Foam::wordList Foam::IOobjectList::sortedNames
 }
 
 
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+Foam::label Foam::IOobjectList::prune_0()
+{
+    return
+        HashPtrTable<IOobject>::filterKeys
+        (
+            [](const word& k){ return k.endsWith("_0"); },
+            true  // prune
+        );
+}
+
+
+Foam::wordList Foam::IOobjectList::allNames() const
+{
+    wordList objNames(HashPtrTable<IOobject>::toc());
+
+    syncNames(objNames);
+    return objNames;
+}
+
+
+bool Foam::IOobjectList::checkNames(const bool syncPar) const
+{
+    if (syncPar && Pstream::parRun())
+    {
+        wordList objNames(HashPtrTable<IOobject>::toc());
+
+        return checkNames(objNames, syncPar);
+    }
+
+    return true;
+}
+
+
 // * * * * * * * * * * * * * * * Member Operators  * * * * * * * * * * * * * //
 
 void Foam::IOobjectList::operator=(IOobjectList&& list)
diff --git a/src/OpenFOAM/db/IOobjectList/IOobjectList.H b/src/OpenFOAM/db/IOobjectList/IOobjectList.H
index 3496e47d20c3b27c95d2f746c225b1d122da47d8..b4882c5d9175b4b8822b03399795669457d1db71 100644
--- a/src/OpenFOAM/db/IOobjectList/IOobjectList.H
+++ b/src/OpenFOAM/db/IOobjectList/IOobjectList.H
@@ -76,6 +76,24 @@ class IOobjectList
             const MatchPredicate& matchName
         );
 
+        //- Templated implementation for count()
+        //  The number of items with a matching class
+        template<class MatchPredicate1, class MatchPredicate2>
+        static label countImpl
+        (
+            const IOobjectList& list,
+            const MatchPredicate1& matchClass,
+            const MatchPredicate2& matchName
+        );
+
+        //- Templated implementation for count()
+        template<class Type, class MatchPredicate>
+        static label countTypeImpl
+        (
+            const IOobjectList& list,
+            const MatchPredicate& matchName
+        );
+
         //- Templated implementation for names(), sortedNames()
         template<class MatchPredicate1, class MatchPredicate2>
         static wordList namesImpl
@@ -87,6 +105,15 @@ class IOobjectList
             const bool syncPar
         );
 
+        //- Templated implementation for names(), sortedNames()
+        template<class Type, class MatchPredicate>
+        static wordList namesTypeImpl
+        (
+            const IOobjectList& list,
+            const MatchPredicate& matchName,
+            const bool doSort
+        );
+
         //- Templated implementation for lookup()
         template<class MatchPredicate>
         static IOobjectList lookupImpl
@@ -104,6 +131,14 @@ class IOobjectList
             const MatchPredicate2& matchName
         );
 
+        //- Templated implementation for lookupClass()
+        template<class Type, class MatchPredicate>
+        static IOobjectList lookupClassTypeImpl
+        (
+            const IOobjectList& list,
+            const MatchPredicate& matchName
+        );
+
 
 public:
 
@@ -181,17 +216,38 @@ public:
 
     // Lookup multiple items
 
-        //- The list of all IOobjects that have a matching object name.
+        //- The list of IOobjects that have a matching object name.
         template<class MatchPredicate>
         IOobjectList lookup(const MatchPredicate& matchName) const;
 
-        //- The list of all IOobjects with the given headerClassName
+        //- The list of IOobjects with the given headerClassName
         IOobjectList lookupClass(const char* clsName) const;
 
-        //- The list of all IOobjects with matching headerClassName
+        //- The list of IOobjects with matching headerClassName
         template<class MatchPredicate>
         IOobjectList lookupClass(const MatchPredicate& matchClass) const;
 
+        //- The list of IOobjects with matching headerClassName
+        //- that also have a matching object name.
+        template<class MatchPredicate1, class MatchPredicate2>
+        IOobjectList lookupClass
+        (
+            const MatchPredicate1& matchClass,
+            const MatchPredicate2& matchName
+        ) const;
+
+        //- The list of IOobjects with headerClassName == Type::typeName
+        //
+        //  \note If \a Type is \c void, no headerClassName check is used
+        //      (always true).
+        template<class Type>
+        IOobjectList lookupClass() const;
+
+        //- The list of IOobjects with headerClassName == Type::typeName
+        //- that also have a matching object name.
+        template<class Type, class MatchPredicate>
+        IOobjectList lookupClass(const MatchPredicate& matchName) const;
+
 
     // Summary of classes
 
@@ -273,6 +329,41 @@ public:
         HashTable<wordHashSet> classes(const MatchPredicate& matchName) const;
 
 
+    // Number of items
+
+        //- The number of objects of the given headerClassName
+        //  \note uses the class type() method
+        label count(const char* clsName) const;
+
+        //- The number of objects of the given headerClassName
+        template<class MatchPredicate>
+        label count
+        (
+            const MatchPredicate& matchClass
+        ) const;
+
+        //- The number of objects of the given headerClassName
+        //- that also have a matching object name.
+        template<class MatchPredicate1, class MatchPredicate2>
+        label count
+        (
+            const MatchPredicate1& matchClass,
+            const MatchPredicate2& matchName
+        ) const;
+
+        //- The number of objects with headerClassName == Type::typeName
+        template<class Type>
+        label count() const;
+
+        //- The number of objects with headerClassName == Type::typeName
+        //- that also have a matching object name.
+        //
+        //  \note If \a Type is \c void, no headerClassName check is used
+        //      (always true).
+        template<class Type, class MatchPredicate>
+        label count(const MatchPredicate& matchName) const;
+
+
     // Summary of names
 
         //- The names of the IOobjects
@@ -353,6 +444,47 @@ public:
         ) const;
 
 
+    // Edit
+
+        //- Filter to retain or prune given classes
+        //  \return The number of items changed (removed)
+        template<class UnaryPredicate>
+        label filterClasses
+        (
+            const UnaryPredicate& pred,
+            const bool pruning = false
+        );
+
+        //- Filter to retain or prune given object names
+        //  \return The number of items changed (removed)
+        template<class UnaryPredicate>
+        label filterObjects
+        (
+            const UnaryPredicate& pred,
+            const bool pruning = false
+        );
+
+        //- Remove objects with names ending with "_0" (restart fields)
+        //  \return The number of items changed (removed)
+        label prune_0();
+
+
+    // Parallel
+
+        //- The sorted names of all objects (synchronised across processors)
+        wordList allNames() const;
+
+        //- The sorted names of all objects (synchronised across processors)
+        //- with headerClassName == Type::typeName
+        template<class Type>
+        wordList allNames() const;
+
+        //- Verify that object names are synchronised across processors
+        //  Triggers FatalError if the names are not consistent on all
+        //  processors.
+        bool checkNames(const bool syncPar = true) const;
+
+
     // Member Operators
 
         //- No copy assignment
diff --git a/src/OpenFOAM/db/IOobjectList/IOobjectListTemplates.C b/src/OpenFOAM/db/IOobjectList/IOobjectListTemplates.C
index 2dd17f84060fd6562e29d7e1fa1df58e4a95a248..c08833c124a326d20d2939cd48dd5c16fcebd32c 100644
--- a/src/OpenFOAM/db/IOobjectList/IOobjectListTemplates.C
+++ b/src/OpenFOAM/db/IOobjectList/IOobjectListTemplates.C
@@ -55,6 +55,55 @@ Foam::HashTable<Foam::wordHashSet> Foam::IOobjectList::classesImpl
 }
 
 
+// Templated implementation for count()
+template<class MatchPredicate1, class MatchPredicate2>
+Foam::label Foam::IOobjectList::countImpl
+(
+    const IOobjectList& list,
+    const MatchPredicate1& matchClass,
+    const MatchPredicate2& matchName
+)
+{
+    label count = 0;
+
+    forAllConstIters(list, iter)
+    {
+        const IOobject* io = iter.object();
+
+        if (matchClass(io->headerClassName()) && matchName(io->name()))
+        {
+            ++count;
+        }
+    }
+
+    return count;
+}
+
+
+// Templated implementation for count()
+template<class Type, class MatchPredicate>
+Foam::label Foam::IOobjectList::countTypeImpl
+(
+    const IOobjectList& list,
+    const MatchPredicate& matchName
+)
+{
+    label count = 0;
+
+    forAllConstIters(list, iter)
+    {
+        const IOobject* io = iter.object();
+
+        if (io->isHeaderClassName<Type>() && matchName(io->name()))
+        {
+            ++count;
+        }
+    }
+
+    return count;
+}
+
+
 // Templated implementation for names(), sortedNames()
 template<class MatchPredicate1, class MatchPredicate2>
 Foam::wordList Foam::IOobjectList::namesImpl
@@ -94,6 +143,41 @@ Foam::wordList Foam::IOobjectList::namesImpl
 }
 
 
+// Templated implementation for names(), sortedNames()
+template<class Type, class MatchPredicate>
+Foam::wordList Foam::IOobjectList::namesTypeImpl
+(
+    const IOobjectList& list,
+    const MatchPredicate& matchName,
+    const bool doSort
+)
+{
+    wordList objNames(list.size());
+
+    label count = 0;
+    forAllConstIters(list, iter)
+    {
+        const word& key = iter.key();
+        const IOobject* io = iter.object();
+
+        if (io->isHeaderClassName<Type>() && matchName(key))
+        {
+            objNames[count] = key;
+            ++count;
+        }
+    }
+
+    objNames.resize(count);
+
+    if (doSort)
+    {
+        Foam::sort(objNames);
+    }
+
+    return objNames;
+}
+
+
 // Templated implementation for lookup()
 template<class MatchPredicate>
 Foam::IOobjectList Foam::IOobjectList::lookupImpl
@@ -155,6 +239,36 @@ Foam::IOobjectList Foam::IOobjectList::lookupClassImpl
 }
 
 
+// Templated implementation for lookupClass()
+template<class Type, class MatchPredicate>
+Foam::IOobjectList Foam::IOobjectList::lookupClassTypeImpl
+(
+    const IOobjectList& list,
+    const MatchPredicate& matchName
+)
+{
+    IOobjectList results(list.size());
+
+    forAllConstIters(list, iter)
+    {
+        const word& key = iter.key();
+        const IOobject* io = iter.object();
+
+        if (io->isHeaderClassName<Type>() && matchName(key))
+        {
+            if (IOobject::debug)
+            {
+                InfoInFunction << "Found " << key << endl;
+            }
+
+            results.set(key, new IOobject(*io));
+        }
+    }
+
+    return results;
+}
+
+
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
 template<class MatchPredicate>
@@ -177,6 +291,34 @@ Foam::IOobjectList Foam::IOobjectList::lookupClass
 }
 
 
+template<class MatchPredicate1, class MatchPredicate2>
+Foam::IOobjectList Foam::IOobjectList::lookupClass
+(
+    const MatchPredicate1& matchClass,
+    const MatchPredicate2& matchName
+) const
+{
+    return lookupClassImpl(*this, matchClass, matchName);
+}
+
+
+template<class Type>
+Foam::IOobjectList Foam::IOobjectList::lookupClass() const
+{
+    return lookupClassTypeImpl<Type>(*this, predicates::always());
+}
+
+
+template<class Type, class MatchPredicate>
+Foam::IOobjectList Foam::IOobjectList::lookupClass
+(
+    const MatchPredicate& matchName
+) const
+{
+    return lookupClassImpl<Type>(*this, matchName);
+}
+
+
 template<class MatchPredicate>
 Foam::HashTable<Foam::wordHashSet>
 Foam::IOobjectList::classes
@@ -200,6 +342,46 @@ Foam::wordList Foam::IOobjectList::names
 }
 
 
+template<class MatchPredicate>
+Foam::label Foam::IOobjectList::count
+(
+    const MatchPredicate& matchClass
+) const
+{
+    return countImpl(*this, matchClass, predicates::always());
+}
+
+
+template<class MatchPredicate1, class MatchPredicate2>
+Foam::label Foam::IOobjectList::count
+(
+    const MatchPredicate1& matchClass,
+    const MatchPredicate2& matchName
+) const
+{
+    return countImpl(*this, matchClass, matchName);
+}
+
+
+template<class Type>
+Foam::label Foam::IOobjectList::count() const
+{
+    return countTypeImpl<Type>(*this, predicates::always());
+}
+
+
+template<class Type, class MatchPredicate>
+Foam::label Foam::IOobjectList::count
+(
+    const MatchPredicate& matchName
+) const
+{
+    return countTypeImpl<Type>(*this, matchName);
+}
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
 template<class MatchPredicate>
 Foam::wordList Foam::IOobjectList::names
 (
@@ -238,4 +420,59 @@ Foam::wordList Foam::IOobjectList::sortedNames
 }
 
 
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+template<class UnaryPredicate>
+Foam::label Foam::IOobjectList::filterClasses
+(
+    const UnaryPredicate& pred,
+    const bool pruning
+)
+{
+//    return HashPtrTable<IOobject>::filterValues
+//    (
+//        [&](const IOobject* io){ return pred(io->headerClassName()); },
+//        pruning
+//    );
+
+    label changed = 0;
+
+    for (iterator iter = begin(); iter != end(); ++iter)
+    {
+        // Matches? either prune (pruning) or keep (!pruning)
+        if
+        (
+            (pred(iter.object()->headerClassName()) ? pruning : !pruning)
+         && erase(iter)
+        )
+        {
+            ++changed;
+        }
+    }
+
+    return changed;
+}
+
+
+template<class UnaryPredicate>
+Foam::label Foam::IOobjectList::filterObjects
+(
+    const UnaryPredicate& pred,
+    const bool pruning
+)
+{
+    return HashPtrTable<IOobject>::filterKeys(pred, pruning);
+}
+
+
+template<class Type>
+Foam::wordList Foam::IOobjectList::allNames() const
+{
+    wordList objNames(namesTypeImpl<Type>(*this, predicates::always(), false));
+
+    syncNames(objNames);
+    return objNames;
+}
+
+
 // ************************************************************************* //