From ba95b89e5fa756301ee219d215b52eab9a0e1fe2 Mon Sep 17 00:00:00 2001
From: mattijs <mattijs>
Date: Thu, 30 Sep 2021 13:37:08 +0100
Subject: [PATCH] ENH: add Function1 caching selector

---
 .../functions/Function1/Function1/Function1.H |  29 ++++-
 .../Function1/Function1/Function1New.C        | 100 ++++++++++++++++++
 2 files changed, 128 insertions(+), 1 deletion(-)

diff --git a/src/OpenFOAM/primitives/functions/Function1/Function1/Function1.H b/src/OpenFOAM/primitives/functions/Function1/Function1/Function1.H
index 41d4f5e06e5..dacf265cd90 100644
--- a/src/OpenFOAM/primitives/functions/Function1/Function1/Function1.H
+++ b/src/OpenFOAM/primitives/functions/Function1/Function1/Function1.H
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2017 OpenFOAM Foundation
-    Copyright (C) 2018-2020 OpenCFD Ltd.
+    Copyright (C) 2018-2021 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -76,6 +76,7 @@ SourceFiles
 
 #include "function1Base.H"
 #include "Field.H"
+#include "HashPtrTable.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
@@ -191,6 +192,32 @@ public:
         );
 
 
+    // Caching Selectors - accept wildcards in dictionary
+
+        //- Selector with external storage of Function1.
+        //- This also allows wildcard matches in a dictionary
+        static refPtr<Function1<Type>> New
+        (
+            HashPtrTable<Function1<Type>>& cache,
+            const word& entryName,
+            const dictionary& dict,
+            enum keyType::option matchOpt = keyType::LITERAL,
+            const bool mandatory = true
+        );
+
+        /// //- Selector with external storage of Function1.
+        /// //- This also allows wildcard matches in a dictionary.
+        /// //  If the default value is used, stores an entry as "default"
+        /// static refPtr<Function1<Type>> NewOrDefault
+        /// (
+        ///     HashPtrTable<Function1<Type>>& cache,
+        ///     const word& entryName,
+        ///     const dictionary& dict,
+        ///     const Type& deflt,
+        ///     enum keyType::option matchOpt = keyType::LITERAL
+        /// );
+
+
     //- Destructor
     virtual ~Function1() = default;
 
diff --git a/src/OpenFOAM/primitives/functions/Function1/Function1/Function1New.C b/src/OpenFOAM/primitives/functions/Function1/Function1/Function1New.C
index 3e8727606aa..0cefa9e2ac3 100644
--- a/src/OpenFOAM/primitives/functions/Function1/Function1/Function1New.C
+++ b/src/OpenFOAM/primitives/functions/Function1/Function1/Function1New.C
@@ -209,4 +209,104 @@ Foam::Function1<Type>::NewIfPresent
 }
 
 
+template<class Type>
+Foam::refPtr<Foam::Function1<Type>>
+Foam::Function1<Type>::New
+(
+    HashPtrTable<Function1<Type>>& cache,
+
+    const word& entryName,
+    const dictionary& dict,
+    enum keyType::option matchOpt,
+    const bool mandatory
+)
+{
+    // Use the dictionary to find the keyword (allowing wildcards).
+    // Alternative would be to have
+    // a HashTable where the key type uses a wildcard match
+
+
+    refPtr<Function1<Type>> fref;  // return value
+
+    // Try for direct cache hit
+    fref.cref(cache.get(entryName));
+
+    if (fref)
+    {
+        return fref;
+    }
+
+
+    // Lookup from dictionary
+    const entry* eptr = dict.findEntry(entryName, matchOpt);
+
+    if (eptr)
+    {
+        // Use keyword (potentially a wildcard) instead of entry name
+        const auto& kw = eptr->keyword();
+
+        // Try for a cache hit
+        fref.cref(cache.get(kw));
+
+        if (!fref)
+        {
+            // Create new entry
+            auto fauto
+            (
+                Function1<Type>::New
+                (
+                    kw,
+                    eptr,  // Already resolved
+                    dict,
+                    word::null,
+                    mandatory
+                )
+            );
+
+            if (fauto)
+            {
+                // Cache the newly created function
+                fref.cref(fauto.get());
+                cache.set(kw, fauto);
+            }
+        }
+    }
+
+    if (mandatory && !fref)
+    {
+        FatalIOErrorInFunction(dict)
+            << "No match for " << entryName << nl
+            << exit(FatalIOError);
+    }
+
+    return fref;
+}
+
+
+/// template<class Type>
+/// Foam::refPtr<Foam::Function1<Type>>
+/// Foam::Function1<Type>::NewOrDefault
+/// (
+///     HashPtrTable<Function1<Type>>& cache,
+///
+///     const word& entryName,
+///     const dictionary& dict,
+///     const Type& deflt,
+///     enum keyType::option matchOpt
+/// )
+/// {
+///     auto fref
+///     (
+///         Function1<Type>::New(entryName, dict, cache, matchOpt, false)
+///     );
+///
+///     if (!fref)
+///     {
+///         fref.reset(new Function1Types::Constant<Type>("default", deflt));
+///     }
+///
+///     return fref;
+/// }
+
+
 // ************************************************************************* //
-- 
GitLab