From dec262a1f2f1da7a688622fbbae898d715f19d9e Mon Sep 17 00:00:00 2001
From: Mark Olesen <Mark.Olesen@esi-group.com>
Date: Wed, 1 May 2019 14:00:54 +0200
Subject: [PATCH] ENH: ensure that content changes in coded objects are noticed
 (#1293)

- for codedFunctionObject and CodedSource the main code snippets
  were not included in the SHA1 calculation, which meant that many
  changes would not be noticed and no new library would be compiled.

  We now allow tracking of the dynamicCodeContext for the coded
  objects and can append to the SHA1 hasher. This should solve the
  previous misbehaviour.
---
 .../functionEntries/codeStream/codeStream.C   |  87 +++------
 .../db/dynamicLibrary/codedBase/codedBase.C   | 182 ++++++++++--------
 .../db/dynamicLibrary/codedBase/codedBase.H   |  68 +++++--
 .../dynamicLibrary/dynamicCode/dynamicCode.C  |  66 ++++---
 .../dynamicLibrary/dynamicCode/dynamicCode.H  |  14 +-
 .../dynamicCode/dynamicCodeContext.C          | 133 +++++++------
 .../dynamicCode/dynamicCodeContext.H          |  74 +++++--
 .../codedFixedValuePointPatchField.C          |  55 +++---
 .../codedPoints0/codedPoints0MotionSolver.C   |  13 +-
 .../codedPoints0/codedPoints0MotionSolver.H   |  12 +-
 .../codedFixedValueFvPatchField.C             |  70 ++++---
 .../codedMixed/codedMixedFvPatchField.C       |  67 +++----
 .../codedFunctionObject/codedFunctionObject.C |  94 ++++++---
 .../codedFunctionObject/codedFunctionObject.H |   8 +-
 .../sources/general/codedSource/CodedSource.C |  39 ++--
 .../sources/general/codedSource/CodedSource.H |  84 ++++----
 .../general/codedSource/CodedSourceIO.C       | 125 ++++++------
 17 files changed, 659 insertions(+), 532 deletions(-)

diff --git a/src/OpenFOAM/db/dictionary/functionEntries/codeStream/codeStream.C b/src/OpenFOAM/db/dictionary/functionEntries/codeStream/codeStream.C
index c7df23c8de..10e845e0f7 100644
--- a/src/OpenFOAM/db/dictionary/functionEntries/codeStream/codeStream.C
+++ b/src/OpenFOAM/db/dictionary/functionEntries/codeStream/codeStream.C
@@ -94,27 +94,19 @@ bool Foam::functionEntries::codeStream::doingMasterOnlyReading
             topDict
         );
 
-        if (debug)
-        {
-            Pout<< "codeStream : baseIOdictionary:" << dict.name()
-                << " master-only-reading:" << d.globalObject()
-                << endl;
-        }
+        DebugPout
+            << "codeStream : baseIOdictionary:" << dict.name()
+            << " master-only-reading:" << d.globalObject() << endl;
 
         return d.globalObject();
     }
-    else
-    {
-        if (debug)
-        {
-            Pout<< "codeStream : not a baseIOdictionary:" << dict.name()
-                << " master-only-reading:" << regIOobject::masterOnlyReading
-                << endl;
-        }
 
-        // Fall back to regIOobject::masterOnlyReading
-        return regIOobject::masterOnlyReading;
-    }
+    DebugPout
+        << "codeStream : not a baseIOdictionary:" << dict.name()
+        << " master-only-reading:" << regIOobject::masterOnlyReading << endl;
+
+    // Fall back to regIOobject::masterOnlyReading
+    return regIOobject::masterOnlyReading;
 }
 
 
@@ -147,17 +139,13 @@ Foam::functionEntries::codeStream::getFunction
         lib = libs(parentDict).findLibrary(libPath);
     }
 
+    // nothing loaded
+    // avoid compilation if possible by loading an existing library
     if (!lib)
     {
         DetailInfo
             << "Using #codeStream with " << libPath << endl;
-    }
-
 
-    // nothing loaded
-    // avoid compilation if possible by loading an existing library
-    if (!lib)
-    {
         if (isA<baseIOdictionary>(topDict))
         {
             // Cached access to dl libs. Guarantees clean up upon destruction
@@ -237,26 +225,21 @@ Foam::functionEntries::codeStream::getFunction
             off_t masterSize = mySize;
             Pstream::scatter(masterSize);
 
-            if (debug)
-            {
-                Pout<< endl<< "on processor " << Pstream::myProcNo()
-                    << " have masterSize:" << masterSize
-                    << " and localSize:" << mySize
-                    << endl;
-            }
-
+            DebugPout
+                << nl << "on processor " << Pstream::myProcNo()
+                << " have masterSize:" << masterSize
+                << " and localSize:" << mySize << endl;
 
             if (mySize < masterSize)
             {
-                if (debug)
-                {
-                    Pout<< "Local file " << libPath
-                        << " not of same size (" << mySize
-                        << ") as master ("
-                        << masterSize << "). Waiting for "
-                        << regIOobject::fileModificationSkew
-                        << " seconds." << endl;
-                }
+                DebugPout
+                    << "Local file " << libPath
+                    << " not of same size (" << mySize
+                    << ") as master ("
+                    << masterSize << "). Waiting for "
+                    << regIOobject::fileModificationSkew
+                    << " seconds." << endl;
+
                 Foam::sleep(regIOobject::fileModificationSkew);
 
                 // Recheck local size
@@ -278,13 +261,10 @@ Foam::functionEntries::codeStream::getFunction
                 }
             }
 
-            if (debug)
-            {
-                Pout<< endl<< "on processor " << Pstream::myProcNo()
-                    << " after waiting: have masterSize:" << masterSize
-                    << " and localSize:" << mySize
-                    << endl;
-            }
+            DebugPout
+                << nl << "on processor " << Pstream::myProcNo()
+                << " after waiting: have masterSize:" << masterSize
+                << " and localSize:" << mySize << endl;
         }
 
         if (isA<baseIOdictionary>(topDict))
@@ -293,10 +273,8 @@ Foam::functionEntries::codeStream::getFunction
             // of Time.
             dlLibraryTable& dlLibs = libs(parentDict);
 
-            if (debug)
-            {
-                Pout<< "Opening cached dictionary:" << libPath << endl;
-            }
+            DebugPout
+                << "Opening cached dictionary:" << libPath << endl;
 
             if (!dlLibs.open(libPath, false))
             {
@@ -312,10 +290,9 @@ Foam::functionEntries::codeStream::getFunction
         else
         {
             // Uncached opening of libPath
-            if (debug)
-            {
-                Pout<< "Opening uncached dictionary:" << libPath << endl;
-            }
+            DebugPout
+                << "Opening uncached dictionary:" << libPath << endl;
+
             lib = dlOpen(libPath, true);
         }
     }
diff --git a/src/OpenFOAM/db/dynamicLibrary/codedBase/codedBase.C b/src/OpenFOAM/db/dynamicLibrary/codedBase/codedBase.C
index 031b3d8fdd..03af8cddf9 100644
--- a/src/OpenFOAM/db/dynamicLibrary/codedBase/codedBase.C
+++ b/src/OpenFOAM/db/dynamicLibrary/codedBase/codedBase.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2016-2018 OpenCFD Ltd.
+    \\  /    A nd           | Copyright (C) 2016-2019 OpenCFD Ltd.
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
                             | Copyright (C) 2011-2016 OpenFOAM Foundation
@@ -56,7 +56,6 @@ static inline void writeEntryIfPresent
     const word& key
 )
 {
-    // non-recursive like dictionary::found, but no pattern-match either
     const entry* eptr = dict.findEntry(key, keyType::LITERAL);
 
     if (eptr)
@@ -89,57 +88,58 @@ void* Foam::codedBase::loadLibrary
 (
     const fileName& libPath,
     const string& globalFuncName,
-    const dictionary& contextDict
+    const dynamicCodeContext& context
 ) const
 {
-    void* lib = 0;
+    // Avoid compilation by loading an existing library
+
+    void* lib =
+    (
+        !libPath.empty() && libs().open(libPath, false)
+      ? libs().findLibrary(libPath)
+      : nullptr
+    );
+
+    if (!lib)
+    {
+        return lib;
+    }
 
-    // avoid compilation by loading an existing library
-    if (!libPath.empty())
+    // verify the loaded version and unload if needed
+
+    // provision for manual execution of code after loading
+    if (dlSymFound(lib, globalFuncName))
     {
-        if (libs().open(libPath, false))
+        loaderFunctionType function =
+            reinterpret_cast<loaderFunctionType>
+            (
+                dlSym(lib, globalFuncName)
+            );
+
+        if (function)
+        {
+            (*function)(true);    // force load
+        }
+        else
         {
-            lib = libs().findLibrary(libPath);
+            FatalIOErrorInFunction(context.dict())
+                << "Failed looking up symbol " << globalFuncName
+                << nl << "from " << libPath << exit(FatalIOError);
+        }
+    }
+    else
+    {
+        FatalIOErrorInFunction(context.dict())
+            << "Failed looking up symbol " << globalFuncName << nl
+            << "from " << libPath << exit(FatalIOError);
 
-            // verify the loaded version and unload if needed
-            if (lib)
-            {
-                // provision for manual execution of code after loading
-                if (dlSymFound(lib, globalFuncName))
-                {
-                    loaderFunctionType function =
-                        reinterpret_cast<loaderFunctionType>
-                        (
-                            dlSym(lib, globalFuncName)
-                        );
-
-                    if (function)
-                    {
-                        (*function)(true);    // force load
-                    }
-                    else
-                    {
-                        FatalIOErrorInFunction(contextDict)
-                            << "Failed looking up symbol " << globalFuncName
-                            << nl << "from " << libPath << exit(FatalIOError);
-                    }
-                }
-                else
-                {
-                    FatalIOErrorInFunction(contextDict)
-                        << "Failed looking up symbol " << globalFuncName << nl
-                        << "from " << libPath << exit(FatalIOError);
-
-                    lib = 0;
-                    if (!libs().close(libPath, false))
-                    {
-                        FatalIOErrorInFunction(contextDict)
-                            << "Failed unloading library "
-                            << libPath
-                            << exit(FatalIOError);
-                    }
-                }
-            }
+        lib = nullptr;
+        if (!libs().close(libPath, false))
+        {
+            FatalIOErrorInFunction(context.dict())
+                << "Failed unloading library "
+                << libPath
+                << exit(FatalIOError);
         }
     }
 
@@ -151,17 +151,16 @@ void Foam::codedBase::unloadLibrary
 (
     const fileName& libPath,
     const string& globalFuncName,
-    const dictionary& contextDict
+    const dynamicCodeContext& context
 ) const
 {
-    void* lib = 0;
-
-    if (libPath.empty())
-    {
-        return;
-    }
 
-    lib = libs().findLibrary(libPath);
+    void* lib =
+    (
+        !libPath.empty() && libs().open(libPath, false)
+      ? libs().findLibrary(libPath)
+      : nullptr
+    );
 
     if (!lib)
     {
@@ -183,7 +182,7 @@ void Foam::codedBase::unloadLibrary
         }
         else
         {
-            FatalIOErrorInFunction(contextDict)
+            FatalIOErrorInFunction(context.dict())
                 << "Failed looking up symbol " << globalFuncName << nl
                 << "from " << libPath << exit(FatalIOError);
         }
@@ -191,7 +190,7 @@ void Foam::codedBase::unloadLibrary
 
     if (!libs().close(libPath, false))
     {
-        FatalIOErrorInFunction(contextDict)
+        FatalIOErrorInFunction(context.dict())
             << "Failed unloading library " << libPath
             << exit(FatalIOError);
     }
@@ -305,21 +304,30 @@ void Foam::codedBase::createLibrary
 
 // * * * * * * * * * * * * Protected Member Functions  * * * * * * * * * * * //
 
+void Foam::codedBase::setCodeContext(const dictionary& dict)
+{
+    context_.setCodeContext(dict);
+}
+
+
+void Foam::codedBase::append(const std::string& str)
+{
+    context_.append(str);
+}
+
+
 void Foam::codedBase::updateLibrary
 (
-    const word& name
+    const word& name,
+    const dynamicCodeContext& context
 ) const
 {
-    const dictionary& dict = this->codeDict();
-
     dynamicCode::checkSecurity
     (
         "codedBase::updateLibrary()",
-        dict
+        context
     );
 
-    dynamicCodeContext context(dict);
-
     // codeName: name + _<sha1>
     // codeDir : name
     dynamicCode dynCode
@@ -327,10 +335,11 @@ void Foam::codedBase::updateLibrary
         name + context.sha1().str(true),
         name
     );
+
     const fileName libPath = dynCode.libPath();
 
 
-    // the correct library was already loaded => we are done
+    // The correct library was already loaded => we are done
     if (libs().findLibrary(libPath))
     {
         return;
@@ -338,44 +347,55 @@ void Foam::codedBase::updateLibrary
 
     DetailInfo
         << "Using dynamicCode for " << this->description().c_str()
-        << " at line " << dict.startLineNumber()
-        << " in " << dict.name() << endl;
+        << " at line " << context.dict().startLineNumber()
+        << " in " << context.dict().name() << endl;
 
 
-    // remove instantiation of fvPatchField provided by library
+    // Remove instantiation of fvPatchField provided by library
     this->clearRedirect();
 
-    // may need to unload old library
+    // May need to unload old library
     unloadLibrary
     (
         oldLibPath_,
         dynamicCode::libraryBaseName(oldLibPath_),
-        context.dict()
+        context
     );
 
-    // try loading an existing library (avoid compilation when possible)
-    if (!loadLibrary(libPath, dynCode.codeName(), context.dict()))
+    // Try loading an existing library (avoid compilation when possible)
+    if (!loadLibrary(libPath, dynCode.codeName(), context))
     {
         createLibrary(dynCode, context);
 
-        loadLibrary(libPath, dynCode.codeName(), context.dict());
+        loadLibrary(libPath, dynCode.codeName(), context);
     }
 
-    // retain for future reference
+    // Retain for future reference
     oldLibPath_ = libPath;
 }
 
 
-// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
-
-Foam::codedBase::codedBase()
-{}
-
+void Foam::codedBase::updateLibrary
+(
+    const word& name,
+    const dictionary& dict
+) const
+{
+    updateLibrary(name, dynamicCodeContext(dict));
+}
 
-// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
 
-Foam::codedBase::~codedBase()
-{}
+void Foam::codedBase::updateLibrary(const word& name) const
+{
+    if (context_.valid())
+    {
+        updateLibrary(name, context_);
+    }
+    else
+    {
+        updateLibrary(name, dynamicCodeContext(this->codeDict()));
+    }
+}
 
 
 // ************************************************************************* //
diff --git a/src/OpenFOAM/db/dynamicLibrary/codedBase/codedBase.H b/src/OpenFOAM/db/dynamicLibrary/codedBase/codedBase.H
index 2d318848e9..a32c8f5e15 100644
--- a/src/OpenFOAM/db/dynamicLibrary/codedBase/codedBase.H
+++ b/src/OpenFOAM/db/dynamicLibrary/codedBase/codedBase.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2016 OpenCFD Ltd.
+    \\  /    A nd           | Copyright (C) 2016-2019 OpenCFD Ltd.
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
                             | Copyright (C) 2011-2016 OpenFOAM Foundation
@@ -28,6 +28,15 @@ Class
 
 Description
     Base class for function objects and boundary conditions using dynamic code
+    that provides methods for managing loading/unloading/updating
+    of a dynamic library. For these purposes, it uses a dynamicCodeContext
+    object to maintain information about the state.
+
+    For simple coded objects, the default state management is sufficient.
+    When there are more complicated code segements
+    (eg, functionObjects::codedFunctionObject), the state management
+    must also register these elements as well, starting with an initial
+    setCodeContext() call and followed by append() to register each element.
 
 SourceFiles
     codedBase.C
@@ -38,16 +47,16 @@ SourceFiles
 #define codedBase_H
 
 #include "dictionary.H"
+#include "dynamicCodeContext.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
 namespace Foam
 {
 
-// Forward declaration of classes
+// Forward Declarations
 class Ostream;
 class dynamicCode;
-class dynamicCodeContext;
 class dlLibraryTable;
 
 /*---------------------------------------------------------------------------*\
@@ -56,11 +65,15 @@ class dlLibraryTable;
 
 class codedBase
 {
-    // Private data
+    // Private Data
+
+        //- The code context
+        dynamicCodeContext context_;
 
         //- Previously loaded library
         mutable fileName oldLibPath_;
 
+
     // Private Member Functions
 
         //- Global loader/unloader function type
@@ -71,7 +84,7 @@ class codedBase
         (
             const fileName& libPath,
             const string& globalFuncName,
-            const dictionary& contextDict
+            const dynamicCodeContext& context
         ) const;
 
         //- Execute globalFuncName(false) and unload specified library
@@ -79,11 +92,15 @@ class codedBase
         (
             const fileName& libPath,
             const string& globalFuncName,
-            const dictionary& contextDict
+            const dynamicCodeContext& context
         ) const;
 
         //- Create library based on the dynamicCodeContext
-        void createLibrary(dynamicCode&, const dynamicCodeContext&) const;
+        void createLibrary
+        (
+            dynamicCode& dynCode,
+            const dynamicCodeContext& context
+        ) const;
 
         //- No copy construct
         codedBase(const codedBase&) = delete;
@@ -95,22 +112,45 @@ class codedBase
 protected:
 
         //- Write code-dictionary contents
-        static void writeCodeDict(Ostream&, const dictionary&);
+        static void writeCodeDict(Ostream& os, const dictionary& dict);
+
+
+    // Protected Member Functions
+
+        //- Set code context from a dictionary
+        void setCodeContext(const dictionary& dict);
 
-        //- Update library as required
+        //- Set code context from a dictionary
+        void append(const dictionary& dict);
+
+
+        //- Update library as required, using the given context
         void updateLibrary
         (
-            const word& name
+            const word& name,
+            const dynamicCodeContext& context
         ) const;
 
+        //- Update library as required, using the given code dictionary
+        //- to use for the context
+        void updateLibrary
+        (
+            const word& name,
+            const dictionary& dict
+        ) const;
+
+        //- Update library as required, using the predefined context
+        //- or use the codeDict() to generate one
+        void updateLibrary(const word& name) const;
+
         //- Get the loaded dynamic libraries
         virtual dlLibraryTable& libs() const = 0;
 
         //- Adapt the context for the current object
         virtual void prepare
         (
-            dynamicCode&,
-            const dynamicCodeContext&
+            dynamicCode& dynCode,
+            const dynamicCodeContext& context
         ) const = 0;
 
         // Return a description (type + name) for the output
@@ -132,11 +172,11 @@ public:
     // Constructors
 
         //- Construct null
-        codedBase();
+        codedBase() = default;
 
 
     //- Destructor
-    virtual ~codedBase();
+    virtual ~codedBase() = default;
 };
 
 
diff --git a/src/OpenFOAM/db/dynamicLibrary/dynamicCode/dynamicCode.C b/src/OpenFOAM/db/dynamicLibrary/dynamicCode/dynamicCode.C
index 7e63d8d298..efe56f30d9 100644
--- a/src/OpenFOAM/db/dynamicLibrary/dynamicCode/dynamicCode.C
+++ b/src/OpenFOAM/db/dynamicLibrary/dynamicCode/dynamicCode.C
@@ -36,6 +36,16 @@ License
 #include "dictionary.H"
 #include "foamVersion.H"
 
+#undef EXT_SO
+#ifdef __APPLE__
+    #define EXT_SO  ".dylib"
+#elif defined _WIN32
+    #define EXT_SO  ".dll"
+#else
+    #define EXT_SO  ".so"
+#endif
+
+
 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
 
 int Foam::dynamicCode::allowSystemOperations
@@ -151,10 +161,8 @@ bool Foam::dynamicCode::resolveTemplates
     const fileName templateDir(Foam::getEnv(codeTemplateEnvName));
 
     bool allOkay = true;
-    forAll(templateNames, fileI)
+    for (const fileName& templateName : templateNames)
     {
-        const fileName& templateName = templateNames[fileI];
-
         fileName file;
         if (!templateDir.empty() && isDir(templateDir))
         {
@@ -188,15 +196,16 @@ bool Foam::dynamicCode::resolveTemplates
 
 bool Foam::dynamicCode::writeCommentSHA1(Ostream& os) const
 {
-    const bool hasSHA1 = filterVars_.found("SHA1sum");
+    const auto fnd = filterVars_.cfind("SHA1sum");
 
-    if (hasSHA1)
+    if (!fnd.found())
     {
-        os  << "/* dynamicCode:\n * SHA1 = ";
-        os.writeQuoted(filterVars_["SHA1sum"], false) << "\n */\n";
+        return false;
     }
 
-    return hasSHA1;
+    os  << "/* dynamicCode:\n * SHA1 = ";
+    os.writeQuoted(*fnd, false) << "\n */\n";
+    return true;
 }
 
 
@@ -214,7 +223,7 @@ bool Foam::dynamicCode::createMakeFiles() const
     mkDir(dstFile.path());
 
     OFstream os(dstFile);
-    //Debug: Info << "Writing to " << dstFile << endl;
+    //Debug: Info<< "Writing to " << dstFile << endl;
     if (!os.good())
     {
         FatalErrorInFunction
@@ -225,9 +234,9 @@ bool Foam::dynamicCode::createMakeFiles() const
     writeCommentSHA1(os);
 
     // Write compile files
-    forAll(compileFiles_, fileI)
+    for (const fileName& file : compileFiles_)
     {
-        os.writeQuoted(compileFiles_[fileI], false) << nl;
+        os.writeQuoted(file, false) << nl;
     }
 
     os  << nl
@@ -317,13 +326,15 @@ Foam::fileName Foam::dynamicCode::codeRelPath() const
 }
 
 
+Foam::fileName Foam::dynamicCode::libPath() const
+{
+    return codeRoot_/libSubDir_/"lib" + codeName_ + EXT_SO;
+}
+
+
 Foam::fileName Foam::dynamicCode::libRelPath() const
 {
-    #ifdef __APPLE__
-    return codeRelPath()/libSubDir_/"lib" + codeName_ + ".dylib";
-    #else
-    return codeRelPath()/libSubDir_/"lib" + codeName_ + ".so";
-    #endif
+    return codeRelPath()/libSubDir_/"lib" + codeName_ + EXT_SO;
 }
 
 
@@ -336,7 +347,7 @@ void Foam::dynamicCode::clear()
     filterVars_.set("typeName", codeName_);
     filterVars_.set("SHA1sum", SHA1Digest().str());
 
-    // Provide default Make/options
+    // Default Make/options
     makeOptions_ =
         "EXE_INC = -g\n"
         "\n\nLIB_LIBS = ";
@@ -426,7 +437,7 @@ bool Foam::dynamicCode::copyOrCreateFiles(const bool verbose) const
             << "Could not find the code template(s): "
             << badFiles << nl
             << "Under the $" << codeTemplateEnvName
-            << " directory or via via the <etc>/"
+            << " directory or via the <etc>/"
             << codeTemplateDirName << " expansion"
             << exit(FatalError);
     }
@@ -440,10 +451,9 @@ bool Foam::dynamicCode::copyOrCreateFiles(const bool verbose) const
     mkDir(outputDir);
 
     // Copy/filter files
-    forAll(resolvedFiles, fileI)
+    for (const fileName& srcFile : resolvedFiles)
     {
-        const fileName& srcFile = resolvedFiles[fileI];
-        const fileName  dstFile(outputDir/srcFile.name());
+        const fileName dstFile(outputDir/srcFile.name());
 
         IFstream is(srcFile);
         //Debug: Info<< "Reading from " << is.name() << endl;
@@ -469,23 +479,20 @@ bool Foam::dynamicCode::copyOrCreateFiles(const bool verbose) const
 
 
     // Create files:
-    forAll(createFiles_, fileI)
+    for (const fileAndContent& content : createFiles_)
     {
-        const fileName dstFile
-        (
-            outputDir/stringOps::expand(createFiles_[fileI].first())
-        );
+        const fileName dstFile(outputDir/stringOps::expand(content.first()));
 
         mkDir(dstFile.path());
         OFstream os(dstFile);
-        //Debug: Info<< "Writing to " << createFiles_[fileI].first() << endl;
+        //Debug: Info<< "Writing to " << content.first() << endl;
         if (!os.good())
         {
             FatalErrorInFunction
                 << "Failed writing " << dstFile
                 << exit(FatalError);
         }
-        os.writeQuoted(createFiles_[fileI].second(), false) << nl;
+        os.writeQuoted(content.second(), false) << nl;
     }
 
 
@@ -515,8 +522,7 @@ bool Foam::dynamicCode::wmakeLibso() const
     else
     {
         // Even with details turned off, we want some feedback
-        Serr
-            << "Invoking wmake libso " << this->codePath().c_str() << endl;
+        Serr<< "Invoking wmake libso " << this->codePath().c_str() << endl;
     }
 
     if (Foam::system(cmd) == 0)
diff --git a/src/OpenFOAM/db/dynamicLibrary/dynamicCode/dynamicCode.H b/src/OpenFOAM/db/dynamicLibrary/dynamicCode/dynamicCode.H
index 4ed7ffaf3c..444057c311 100644
--- a/src/OpenFOAM/db/dynamicLibrary/dynamicCode/dynamicCode.H
+++ b/src/OpenFOAM/db/dynamicLibrary/dynamicCode/dynamicCode.H
@@ -219,21 +219,13 @@ public:
             return codeRoot_/codeDirName_;
         }
 
-        //- Library path for specified code name
-        //  Corresponds to codeRoot()/libSubDir()/lib\<codeName\>.so
-        fileName libPath() const
-        {
-            #ifdef __APPLE__
-            return codeRoot_/libSubDir_/"lib" + codeName_ + ".dylib";
-            #else
-            return codeRoot_/libSubDir_/"lib" + codeName_ + ".so";
-            #endif
-        }
-
         //- Path for specified code name relative to \<case\>
         //  Corresponds to topDirName/codeDirName()
         fileName codeRelPath() const;
 
+        //- Library path for specified code name
+        //  Corresponds to codeRoot()/libSubDir()/lib\<codeName\>.so
+        fileName libPath() const;
 
         //- Library path for specified code name relative to \<case\>
         //  Corresponds to
diff --git a/src/OpenFOAM/db/dynamicLibrary/dynamicCode/dynamicCodeContext.C b/src/OpenFOAM/db/dynamicLibrary/dynamicCode/dynamicCodeContext.C
index 602b713775..089b48d002 100644
--- a/src/OpenFOAM/db/dynamicLibrary/dynamicCode/dynamicCodeContext.C
+++ b/src/OpenFOAM/db/dynamicLibrary/dynamicCode/dynamicCodeContext.C
@@ -31,97 +31,104 @@ License
 
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
+Foam::dynamicCodeContext::dynamicCodeContext()
+:
+    dict_(std::cref<dictionary>(dictionary::null))
+{}
+
+
 Foam::dynamicCodeContext::dynamicCodeContext(const dictionary& dict)
 :
-    dict_(dict),
-    code_(),
-    localCode_(),
-    include_(),
-    options_(),
-    libs_()
+    dynamicCodeContext()
 {
-    // Expand dictionary entries
+    setCodeContext(dict);
+}
 
-    // Note: removes any leading/trailing whitespace
-    // - necessary for compilation options, convenient for includes
-    // and body.
 
-    const entry* codePtr = dict.findEntry("code", keyType::LITERAL);
+// * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * * //
 
-    if (codePtr)
-    {
-        codePtr->readEntry(code_);
-        stringOps::inplaceTrim(code_);
-        stringOps::inplaceExpand(code_, dict);
-    }
+bool Foam::dynamicCodeContext::valid() const
+{
+    return &(dict_.get()) != &(dictionary::null);
+}
 
-    const entry* includePtr = dict.findEntry("codeInclude", keyType::LITERAL);
 
-    if (includePtr)
-    {
-        includePtr->readEntry(include_);
-        stringOps::inplaceTrim(include_);
-        stringOps::inplaceExpand(include_, dict);
-    }
+void Foam::dynamicCodeContext::setCodeContext(const dictionary& dict)
+{
+    dict_ = std::cref<dictionary>(dict);
+    sha1_.clear();
 
-    const entry* optionsPtr = dict.findEntry("codeOptions", keyType::LITERAL);
+    // Expand dictionary entries.
+    // Removing any leading/trailing whitespace is necessary for compilation
+    // options, but is also convenient for includes and code body.
 
-    if (optionsPtr)
+    const entry* eptr;
+
+    options_.clear();
+    sha1_.append("<codeOptions>");
+    if ((eptr = dict.findEntry("codeOptions", keyType::LITERAL)) != nullptr)
     {
-        optionsPtr->readEntry(options_);
+        eptr->readEntry(options_);
         stringOps::inplaceTrim(options_);
         stringOps::inplaceExpand(options_, dict);
-    }
 
-    const entry* libsPtr = dict.findEntry("codeLibs", keyType::LITERAL);
+        sha1_.append(options_);
+        // No #line for options (Make/options)
+        // - preprocessed as a single line at this point. Can be fixed.
+    }
 
-    if (libsPtr)
+    libs_.clear();
+    sha1_.append("<codeLibs>");
+    if ((eptr = dict.findEntry("codeLibs", keyType::LITERAL)) != nullptr)
     {
-        libsPtr->readEntry(libs_);
+        eptr->readEntry(libs_);
         stringOps::inplaceTrim(libs_);
         stringOps::inplaceExpand(libs_, dict);
-    }
-
-    const entry* localPtr = dict.findEntry("localCode", keyType::LITERAL);
 
-    if (localPtr)
-    {
-        localPtr->readEntry(localCode_);
-        stringOps::inplaceTrim(localCode_);
-        stringOps::inplaceExpand(localCode_, dict);
+        sha1_.append(libs_);
+        // No #line for libs
+        // - preprocessed as a single line at this point. Can be fixed.
     }
 
-    // Calculate SHA1 digest from include, options, localCode, code
-    OSHA1stream os;
-    os  << include_ << options_ << libs_ << localCode_ << code_;
-    sha1_ = os.digest();
-
-
-    // Add line number after calculating sha1 since includes processorDDD
-    // in path which differs between processors.
-
-    if (codePtr)
+    include_.clear();
+    sha1_.append("<codeInclude>");
+    if ((eptr = dict.findEntry("codeInclude", keyType::LITERAL)) != nullptr)
     {
-        addLineDirective(code_, codePtr->startLineNumber(), dict.name());
+        eptr->readEntry(include_);
+        stringOps::inplaceTrim(include_);
+        stringOps::inplaceExpand(include_, dict);
+
+        sha1_.append(include_);
+        addLineDirective(include_, eptr->startLineNumber(), dict.name());
     }
 
-    if (includePtr)
+    code_.clear();
+    sha1_.append("<code>");
+    if ((eptr = dict.findEntry("code", keyType::LITERAL)) != nullptr)
     {
-        addLineDirective(include_, includePtr->startLineNumber(), dict.name());
+        eptr->readEntry(code_);
+        stringOps::inplaceTrim(code_);
+        stringOps::inplaceExpand(code_, dict);
+
+        sha1_.append(code_);
+        addLineDirective(code_, eptr->startLineNumber(), dict.name());
     }
 
-    // Do not add line directive to options_ (Make/options) and libs since
-    // they are preprocessed as a single line at this point. Can be fixed.
-    if (localPtr)
+    localCode_.clear();
+    sha1_.append("<localCode>");
+    if ((eptr = dict.findEntry("localCode", keyType::LITERAL)) != nullptr)
     {
-        addLineDirective(localCode_, localPtr->startLineNumber(), dict.name());
+        eptr->readEntry(localCode_);
+        stringOps::inplaceTrim(localCode_);
+        stringOps::inplaceExpand(localCode_, dict);
+
+        sha1_.append(localCode_);
+        addLineDirective(localCode_, eptr->startLineNumber(), dict.name());
     }
 }
 
 
-// * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * * //
-
-void Foam::dynamicCodeContext::addLineDirective
+unsigned Foam::dynamicCodeContext::addLineDirective
 (
     string& code,
     label lineNum,
@@ -130,10 +137,16 @@ void Foam::dynamicCodeContext::addLineDirective
 {
     ++lineNum;  // Change from 0-based to 1-based
 
-    if (lineNum > 0 && !name.empty())
+    const auto len = code.length();
+
+    if (lineNum > 0 && len && !name.empty())
     {
         code = "#line " + Foam::name(lineNum) + " \"" + name + "\"\n" + code;
+
+        return (code.length() - len);
     }
+
+    return 0;
 }
 
 
diff --git a/src/OpenFOAM/db/dynamicLibrary/dynamicCode/dynamicCodeContext.H b/src/OpenFOAM/db/dynamicLibrary/dynamicCode/dynamicCodeContext.H
index 7458bcb2ab..2e6c21ccab 100644
--- a/src/OpenFOAM/db/dynamicLibrary/dynamicCode/dynamicCodeContext.H
+++ b/src/OpenFOAM/db/dynamicLibrary/dynamicCode/dynamicCodeContext.H
@@ -37,8 +37,9 @@ SourceFiles
 #ifndef dynamicCodeContext_H
 #define dynamicCodeContext_H
 
+#include <functional>
 #include "dictionary.H"
-#include "SHA1Digest.H"
+#include "SHA1.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
@@ -51,19 +52,13 @@ namespace Foam
 
 class dynamicCodeContext
 {
-    // Private data
+    // Private Data
 
         //- The parent dictionary context
-        const dictionary& dict_;
+        std::reference_wrapper<const dictionary> dict_;
 
-        //- Optional "code" entry
-        string code_;
-
-        //- Optional "localCode" entry
-        string localCode_;
-
-        //- Optional "codeInclude" entry
-        string include_;
+        //- The SHA1 of the contents
+        SHA1 sha1_;
 
         //- Optional "codeOptions" entry
         string options_;
@@ -71,24 +66,39 @@ class dynamicCodeContext
         //- Optional "codeLibs" entry
         string libs_;
 
-        //- Calculated SHA1Digest
-        SHA1Digest sha1_;
+        //- Optional "codeInclude" entry
+        string include_;
+
+        //- Optional "code" entry
+        string code_;
+
+        //- Optional "localCode" entry
+        string localCode_;
 
 
 public:
 
     // Constructors
 
+        //- Construct null
+        dynamicCodeContext();
+
         //- Construct from a dictionary
-        dynamicCodeContext(const dictionary& dict);
+        explicit dynamicCodeContext(const dictionary& dict);
+
+
+    // Member Functions
 
+        //- Considered valid if not using dictionary::null as the context
+        bool valid() const;
 
-    // Member functions
+        //- Set code context from a dictionary
+        void setCodeContext(const dictionary& dict);
 
         //- Return the parent dictionary context
         const dictionary& dict() const
         {
-            return dict_;
+            return dict_.get();
         }
 
         //- Return the code-includes
@@ -121,20 +131,42 @@ public:
             return localCode_;
         }
 
-        //- Return SHA1 digest calculated from include, options, code
-        const SHA1Digest& sha1() const
+        //- Return SHA1 calculated from options, libs, include, code
+        const SHA1& sha1() const
         {
             return sha1_;
         }
 
-        //- Helper: add \#line directive
-        //  The lineNum is 0-based. No-op if the lineNum is negative.
-        static void addLineDirective
+        //- Add content to SHA1 hashing
+        void append(const std::string& str)
+        {
+            sha1_.append(str);
+        }
+
+
+        //- Helper: Prefix a \#line directive to code.
+        //  The input lineNum is 0-based.
+        //  Is a no-op if any of the arguments are invalid
+        //  (lineNum is negative, code or name are empty)
+        //
+        //  \return The change in string length caused by the directive.
+        //  This can potentially be used to recover the substring portions.
+        static unsigned addLineDirective
         (
             string& code,
             label lineNum,
             const fileName& name
         );
+
+
+    // Member Operators
+
+        //- Cast to dictionary
+        operator const dictionary&() const
+        {
+            return dict_.get();
+        }
+
 };
 
 
diff --git a/src/OpenFOAM/fields/pointPatchFields/derived/codedFixedValue/codedFixedValuePointPatchField.C b/src/OpenFOAM/fields/pointPatchFields/derived/codedFixedValue/codedFixedValuePointPatchField.C
index e842924dcf..357e3ceb83 100644
--- a/src/OpenFOAM/fields/pointPatchFields/derived/codedFixedValue/codedFixedValuePointPatchField.C
+++ b/src/OpenFOAM/fields/pointPatchFields/derived/codedFixedValue/codedFixedValuePointPatchField.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2016 OpenCFD Ltd.
+    \\  /    A nd           | Copyright (C) 2016-2019 OpenCFD Ltd.
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
                             | Copyright (C) 2012-2016 OpenFOAM Foundation
@@ -71,27 +71,26 @@ const
 {
     const objectRegistry& obr = this->db();
 
-    if (obr.foundObject<IOdictionary>("codeDict"))
+    const IOdictionary* dictptr = obr.cfindObject<IOdictionary>("codeDict");
+    if (dictptr)
     {
-        return obr.lookupObject<IOdictionary>("codeDict");
+        return *dictptr;
     }
-    else
-    {
-        return obr.store
+
+    return obr.store
+    (
+        new IOdictionary
         (
-            new IOdictionary
+            IOobject
             (
-                IOobject
-                (
-                    "codeDict",
-                    this->db().time().system(),
-                    this->db(),
-                    IOobject::MUST_READ_IF_MODIFIED,
-                    IOobject::NO_WRITE
-                )
+                "codeDict",
+                this->db().time().system(),
+                this->db(),
+                IOobject::MUST_READ_IF_MODIFIED,
+                IOobject::NO_WRITE
             )
-        );
-    }
+        )
+    );
 }
 
 
@@ -113,7 +112,6 @@ void Foam::codedFixedValuePointPatchField<Type>::prepare
     dynCode.setFilterVariable("typeName", name_);
 
     // Set TemplateType and FieldType filter variables
-    // (for pointPatchField)
     setFieldTemplates(dynCode);
 
     // Compile filtered C template
@@ -122,23 +120,22 @@ void Foam::codedFixedValuePointPatchField<Type>::prepare
     // Copy filtered H template
     dynCode.addCopyFile(codeTemplateH);
 
-
-    // Debugging: make BC verbose
+    // Debugging: make verbose
     //   dynCode.setFilterVariable("verbose", "true");
     //   Info<<"compile " << name_ << " sha1: "
     //       << context.sha1() << endl;
 
     // Define Make/options
     dynCode.setMakeOptions
-        (
-            "EXE_INC = -g \\\n"
-            "-I$(LIB_SRC)/finiteVolume/lnInclude \\\n"
-            + context.options()
-            + "\n\nLIB_LIBS = \\\n"
-            + "    -lOpenFOAM \\\n"
-            + "    -lfiniteVolume \\\n"
-            + context.libs()
-        );
+    (
+        "EXE_INC = -g \\\n"
+        "-I$(LIB_SRC)/finiteVolume/lnInclude \\\n"
+      + context.options()
+      + "\n\nLIB_LIBS = \\\n"
+        "    -lOpenFOAM \\\n"
+        "    -lfiniteVolume \\\n"
+      + context.libs()
+    );
 }
 
 
diff --git a/src/dynamicMesh/motionSolvers/displacement/codedPoints0/codedPoints0MotionSolver.C b/src/dynamicMesh/motionSolvers/displacement/codedPoints0/codedPoints0MotionSolver.C
index e3c0f914dd..e2fddda71d 100644
--- a/src/dynamicMesh/motionSolvers/displacement/codedPoints0/codedPoints0MotionSolver.C
+++ b/src/dynamicMesh/motionSolvers/displacement/codedPoints0/codedPoints0MotionSolver.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2017 OpenCFD Ltd.
+    \\  /    A nd           | Copyright (C) 2017-2019 OpenCFD Ltd.
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -63,7 +63,7 @@ void Foam::codedPoints0MotionSolver::prepare
     // Copy filtered H template
     dynCode.addCopyFile("codedPoints0MotionSolverTemplate.H");
 
-    // Debugging: make BC verbose
+    // Debugging: make verbose
     // dynCode.setFilterVariable("verbose", "true");
     // Info<<"compile " << name_ << " sha1: "
     //     << context.sha1() << endl;
@@ -73,12 +73,15 @@ void Foam::codedPoints0MotionSolver::prepare
     (
         "EXE_INC = -g \\\n"
         "-I$(LIB_SRC)/finiteVolume/lnInclude \\\n"
-        "-I$(LIB_SRC)/fvMotionSolvers/lnInclude \\\n"
-        "-I$(LIB_SRC)/dynamicMesh/lnInclude \\\n"
         "-I$(LIB_SRC)/meshTools/lnInclude \\\n"
+        "-I$(LIB_SRC)/dynamicMesh/lnInclude \\\n"
+        "-I$(LIB_SRC)/fvMotionSolvers/lnInclude \\\n"
       + context.options()
       + "\n\nLIB_LIBS = \\\n"
-      + "    -lfvMotionSolvers \\\n"
+        "    -lfiniteVolume \\\n"
+        "    -lmeshTools \\\n"
+        "    -ldynamicMesh \\\n"
+        "    -lfvMotionSolvers \\\n"
       + context.libs()
     );
 }
diff --git a/src/dynamicMesh/motionSolvers/displacement/codedPoints0/codedPoints0MotionSolver.H b/src/dynamicMesh/motionSolvers/displacement/codedPoints0/codedPoints0MotionSolver.H
index d095d9481b..d54141102e 100644
--- a/src/dynamicMesh/motionSolvers/displacement/codedPoints0/codedPoints0MotionSolver.H
+++ b/src/dynamicMesh/motionSolvers/displacement/codedPoints0/codedPoints0MotionSolver.H
@@ -107,17 +107,17 @@ protected:
         //- Adapt the context for the current object
         virtual void prepare(dynamicCode&, const dynamicCodeContext&) const;
 
-        // Return a description (type + name) for the output
+        //- Return a description (type + name) for the output
         virtual string description() const;
 
-        // Clear any redirected objects
+        //- Clear any redirected objects
         virtual void clearRedirect() const;
 
-        // Get the dictionary to initialize the codeContext
+        // The dictionary to initialize the codeContext
         virtual const dictionary& codeDict() const;
 
 
-        //- No copy assignment construct
+        //- No copy construct
         codedPoints0MotionSolver(const codedPoints0MotionSolver&) = delete;
 
         //- No copy assignment
@@ -156,10 +156,10 @@ public:
         virtual void solve();
 
         //- Update local data for geometry changes
-        virtual void movePoints(const pointField&);
+        virtual void movePoints(const pointField& fld);
 
         //-  Update local data for topology changes
-        virtual void updateMesh(const mapPolyMesh&);
+        virtual void updateMesh(const mapPolyMesh& mpm);
 };
 
 
diff --git a/src/finiteVolume/fields/fvPatchFields/derived/codedFixedValue/codedFixedValueFvPatchField.C b/src/finiteVolume/fields/fvPatchFields/derived/codedFixedValue/codedFixedValueFvPatchField.C
index 3ec2b3a5b1..8ca016ba8e 100644
--- a/src/finiteVolume/fields/fvPatchFields/derived/codedFixedValue/codedFixedValueFvPatchField.C
+++ b/src/finiteVolume/fields/fvPatchFields/derived/codedFixedValue/codedFixedValueFvPatchField.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2011, 2016 OpenCFD Ltd.
+    \\  /    A nd           | Copyright (C) 2011-2011, 2016-2019 OpenCFD Ltd.
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
                             | Copyright (C) 2011-2016 OpenFOAM Foundation
@@ -54,7 +54,7 @@ void Foam::codedFixedValueFvPatchField<Type>::setFieldTemplates
 {
     word fieldType(pTraits<Type>::typeName);
 
-    // template type for fvPatchField
+    // Template type for fvPatchField
     dynCode.setFilterVariable("TemplateType", fieldType);
 
     // Name for fvPatchField - eg, ScalarField, VectorField, ...
@@ -70,27 +70,26 @@ const Foam::IOdictionary& Foam::codedFixedValueFvPatchField<Type>::dict() const
 {
     const objectRegistry& obr = this->db();
 
-    if (obr.foundObject<IOdictionary>("codeDict"))
+    const IOdictionary* dictptr = obr.cfindObject<IOdictionary>("codeDict");
+    if (dictptr)
     {
-        return obr.lookupObject<IOdictionary>("codeDict");
+        return *dictptr;
     }
-    else
-    {
-        return obr.store
+
+    return obr.store
+    (
+        new IOdictionary
         (
-            new IOdictionary
+            IOobject
             (
-                IOobject
-                (
-                    "codeDict",
-                    this->db().time().system(),
-                    this->db(),
-                    IOobject::MUST_READ_IF_MODIFIED,
-                    IOobject::NO_WRITE
-                )
+                "codeDict",
+                this->db().time().system(),
+                this->db(),
+                IOobject::MUST_READ_IF_MODIFIED,
+                IOobject::NO_WRITE
             )
-        );
-    }
+        )
+    );
 }
 
 
@@ -108,36 +107,35 @@ void Foam::codedFixedValueFvPatchField<Type>::prepare
     const dynamicCodeContext& context
 ) const
 {
-    // take no chances - typeName must be identical to name_
+    // Take no chances - typeName must be identical to name_
     dynCode.setFilterVariable("typeName", name_);
 
-    // set TemplateType and FieldType filter variables
-    // (for fvPatchField)
+    // Set TemplateType and FieldType filter variables
     setFieldTemplates(dynCode);
 
-    // compile filtered C template
+    // Compile filtered C template
     dynCode.addCompileFile(codeTemplateC);
 
-    // copy filtered H template
+    // Copy filtered H template
     dynCode.addCopyFile(codeTemplateH);
 
-
-    // debugging: make BC verbose
+    // debugging: make verbose
     //  dynCode.setFilterVariable("verbose", "true");
-    //  Info<<"compile " << name_ << " sha1: "
+    //  DetailInfo
+    //      <<"compile " << name_ << " sha1: "
     //      << context.sha1() << endl;
 
-    // define Make/options
+    // Define Make/options
     dynCode.setMakeOptions
-        (
-            "EXE_INC = -g \\\n"
-            "-I$(LIB_SRC)/finiteVolume/lnInclude \\\n"
-            + context.options()
-            + "\n\nLIB_LIBS = \\\n"
-            + "    -lOpenFOAM \\\n"
-            + "    -lfiniteVolume \\\n"
-            + context.libs()
-        );
+    (
+        "EXE_INC = -g \\\n"
+        "-I$(LIB_SRC)/finiteVolume/lnInclude \\\n"
+      + context.options()
+      + "\n\nLIB_LIBS = \\\n"
+        "    -lOpenFOAM \\\n"
+        "    -lfiniteVolume \\\n"
+      + context.libs()
+    );
 }
 
 
diff --git a/src/finiteVolume/fields/fvPatchFields/derived/codedMixed/codedMixedFvPatchField.C b/src/finiteVolume/fields/fvPatchFields/derived/codedMixed/codedMixedFvPatchField.C
index 7e2bff9185..5591be8055 100644
--- a/src/finiteVolume/fields/fvPatchFields/derived/codedMixed/codedMixedFvPatchField.C
+++ b/src/finiteVolume/fields/fvPatchFields/derived/codedMixed/codedMixedFvPatchField.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2016 OpenCFD Ltd.
+    \\  /    A nd           | Copyright (C) 2016-2019 OpenCFD Ltd.
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
                             | Copyright (C) 2011-2016 OpenFOAM Foundation
@@ -54,7 +54,7 @@ void Foam::codedMixedFvPatchField<Type>::setFieldTemplates
 {
     word fieldType(pTraits<Type>::typeName);
 
-    // template type for fvPatchField
+    // Template type for fvPatchField
     dynCode.setFilterVariable("TemplateType", fieldType);
 
     // Name for fvPatchField - eg, ScalarField, VectorField, ...
@@ -70,27 +70,26 @@ const Foam::IOdictionary& Foam::codedMixedFvPatchField<Type>::dict() const
 {
     const objectRegistry& obr = this->db();
 
-    if (obr.foundObject<IOdictionary>("codeDict"))
+    const IOdictionary* dictptr = obr.cfindObject<IOdictionary>("codeDict");
+    if (dictptr)
     {
-        return obr.lookupObject<IOdictionary>("codeDict");
+        return *dictptr;
     }
-    else
-    {
-        return obr.store
+
+    return obr.store
+    (
+        new IOdictionary
         (
-            new IOdictionary
+            IOobject
             (
-                IOobject
-                (
-                    "codeDict",
-                    this->db().time().system(),
-                    this->db(),
-                    IOobject::MUST_READ_IF_MODIFIED,
-                    IOobject::NO_WRITE
-                )
+                "codeDict",
+                this->db().time().system(),
+                this->db(),
+                IOobject::MUST_READ_IF_MODIFIED,
+                IOobject::NO_WRITE
             )
-        );
-    }
+        )
+    );
 }
 
 
@@ -108,36 +107,34 @@ void Foam::codedMixedFvPatchField<Type>::prepare
     const dynamicCodeContext& context
 ) const
 {
-    // take no chances - typeName must be identical to name_
+    // Take no chances - typeName must be identical to name_
     dynCode.setFilterVariable("typeName", name_);
 
-    // set TemplateType and FieldType filter variables
-    // (for fvPatchField)
+    // Set TemplateType and FieldType filter variables
     setFieldTemplates(dynCode);
 
-    // compile filtered C template
+    // Compile filtered C template
     dynCode.addCompileFile(codeTemplateC);
 
-    // copy filtered H template
+    // Copy filtered H template
     dynCode.addCopyFile(codeTemplateH);
 
-
-    // debugging: make BC verbose
+    // Debugging: make verbose
     //  dynCode.setFilterVariable("verbose", "true");
     //  Info<<"compile " << name_ << " sha1: "
     //      << context.sha1() << endl;
 
-    // define Make/options
+    // Define Make/options
     dynCode.setMakeOptions
-        (
-            "EXE_INC = -g \\\n"
-            "-I$(LIB_SRC)/finiteVolume/lnInclude \\\n"
-            + context.options()
-            + "\n\nLIB_LIBS = \\\n"
-            + "    -lOpenFOAM \\\n"
-            + "    -lfiniteVolume \\\n"
-            + context.libs()
-        );
+    (
+        "EXE_INC = -g \\\n"
+        "-I$(LIB_SRC)/finiteVolume/lnInclude \\\n"
+      + context.options()
+      + "\n\nLIB_LIBS = \\\n"
+        "    -lOpenFOAM \\\n"
+        "    -lfiniteVolume \\\n"
+      + context.libs()
+    );
 }
 
 
diff --git a/src/functionObjects/utilities/codedFunctionObject/codedFunctionObject.C b/src/functionObjects/utilities/codedFunctionObject/codedFunctionObject.C
index ce45990ae1..c639cff8a8 100644
--- a/src/functionObjects/utilities/codedFunctionObject/codedFunctionObject.C
+++ b/src/functionObjects/utilities/codedFunctionObject/codedFunctionObject.C
@@ -75,7 +75,7 @@ void Foam::functionObjects::codedFunctionObject::prepare
     // Copy filtered H template
     dynCode.addCopyFile("functionObjectTemplate.H");
 
-    // Debugging: make BC verbose
+    // Debugging: make verbose
     // dynCode.setFilterVariable("verbose", "true");
     // Info<<"compile " << name_ << " sha1: "
     //     << context.sha1() << endl;
@@ -88,9 +88,9 @@ void Foam::functionObjects::codedFunctionObject::prepare
         "-I$(LIB_SRC)/meshTools/lnInclude \\\n"
       + context.options()
       + "\n\nLIB_LIBS = \\\n"
-      + "    -lOpenFOAM \\\n"
-      + "    -lfiniteVolume \\\n"
-      + "    -lmeshTools \\\n"
+        "    -lOpenFOAM \\\n"
+        "    -lfiniteVolume \\\n"
+        "    -lmeshTools \\\n"
       + context.libs()
     );
 }
@@ -187,79 +187,115 @@ bool Foam::functionObjects::codedFunctionObject::read(const dictionary& dict)
 {
     timeFunctionObject::read(dict);
 
+    codedBase::setCodeContext(dict);
+
     dict.readCompat<word>("name", {{"redirectType", 1706}}, name_);
 
-    const entry* dataPtr = dict.findEntry("codeData", keyType::LITERAL);
+    label nKeywords = 0;
+
+    const entry* eptr;
 
-    if (dataPtr)
+    codeData_.clear();
+    codedBase::append("<codeData>");
+    if ((eptr = dict.findEntry("codeData", keyType::LITERAL)) != nullptr)
     {
-        dataPtr->readEntry(codeData_);
+        eptr->readEntry(codeData_);
+        stringOps::inplaceTrim(codeData_);
         stringOps::inplaceExpand(codeData_, dict);
+
+        codedBase::append(codeData_);
+
         dynamicCodeContext::addLineDirective
         (
             codeData_,
-            dataPtr->startLineNumber(),
+            eptr->startLineNumber(),
             dict.name()
         );
-    }
 
-    const entry* readPtr = dict.findEntry("codeRead", keyType::LITERAL);
+        ++nKeywords;
+    }
 
-    if (readPtr)
+    codeRead_.clear();
+    codedBase::append("<codeRead>");
+    if ((eptr = dict.findEntry("codeRead", keyType::LITERAL)) != nullptr)
     {
-        readPtr->readEntry(codeRead_);
+        eptr->readEntry(codeRead_);
+        stringOps::inplaceTrim(codeRead_);
         stringOps::inplaceExpand(codeRead_, dict);
+
+        codedBase::append(codeRead_);
+
         dynamicCodeContext::addLineDirective
         (
             codeRead_,
-            readPtr->startLineNumber(),
+            eptr->startLineNumber(),
             dict.name()
         );
-    }
 
-    const entry* execPtr = dict.findEntry("codeExecute", keyType::LITERAL);
+        ++nKeywords;
+    }
 
-    if (execPtr)
+    codeExecute_.clear();
+    codedBase::append("<codeExecute>");
+    if ((eptr = dict.findEntry("codeExecute", keyType::LITERAL)) != nullptr)
     {
-        execPtr->readEntry(codeExecute_);
+        eptr->readEntry(codeExecute_);
+        stringOps::inplaceTrim(codeExecute_);
         stringOps::inplaceExpand(codeExecute_, dict);
+
+        codedBase::append(codeExecute_);
+
         dynamicCodeContext::addLineDirective
         (
             codeExecute_,
-            execPtr->startLineNumber(),
+            eptr->startLineNumber(),
             dict.name()
         );
-    }
 
-    const entry* writePtr = dict.findEntry("codeWrite", keyType::LITERAL);
+        ++nKeywords;
+    }
 
-    if (writePtr)
+    codeWrite_.clear();
+    codedBase::append("<codeWrite>");
+    if ((eptr = dict.findEntry("codeWrite", keyType::LITERAL)) != nullptr)
     {
-        writePtr->readEntry(codeWrite_);
+        eptr->readEntry(codeWrite_);
+        stringOps::inplaceTrim(codeWrite_);
         stringOps::inplaceExpand(codeWrite_, dict);
+
+        codedBase::append(codeWrite_);
+
         dynamicCodeContext::addLineDirective
         (
             codeWrite_,
-            writePtr->startLineNumber(),
+            eptr->startLineNumber(),
             dict.name()
         );
-    }
 
-    const entry* endPtr = dict.findEntry("codeEnd", keyType::LITERAL);
+        ++nKeywords;
+    }
 
-    if (endPtr)
+    codeEnd_.clear();
+    codedBase::append("<codeEnd>");
+    if ((eptr = dict.findEntry("codeEnd", keyType::LITERAL)) != nullptr)
     {
-        endPtr->readEntry(codeEnd_);
+        eptr->readEntry(codeEnd_);
+        stringOps::inplaceTrim(codeEnd_);
         stringOps::inplaceExpand(codeEnd_, dict);
+
+        codedBase::append(codeEnd_);
+
         dynamicCodeContext::addLineDirective
         (
             codeEnd_,
-            endPtr->startLineNumber(),
+            eptr->startLineNumber(),
             dict.name()
         );
+
+        ++nKeywords;
     }
 
-    if (!dataPtr && !readPtr && !execPtr && !writePtr && !endPtr)
+    if (!nKeywords)
     {
         IOWarningInFunction(dict)
             << "No critical \"code\" prefixed keywords were found."
diff --git a/src/functionObjects/utilities/codedFunctionObject/codedFunctionObject.H b/src/functionObjects/utilities/codedFunctionObject/codedFunctionObject.H
index 7bac4e67b6..c1b597f877 100644
--- a/src/functionObjects/utilities/codedFunctionObject/codedFunctionObject.H
+++ b/src/functionObjects/utilities/codedFunctionObject/codedFunctionObject.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011 OpenCFD Ltd.
+    \\  /    A nd           | Copyright (C) 2011, 2019 OpenCFD Ltd.
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
                             | Copyright (C) 2011-2017 OpenFOAM Foundation
@@ -123,13 +123,13 @@ protected:
         //- Adapt the context for the current object
         virtual void prepare(dynamicCode&, const dynamicCodeContext&) const;
 
-        // Return a description (type + name) for the output
+        //- Return a description (type + name) for the output
         virtual string description() const;
 
-        // Clear any redirected objects
+        //- Clear any redirected objects
         virtual void clearRedirect() const;
 
-        // Get the dictionary to initialize the codeContext
+        //- The dictionary to initialize the codeContext
         virtual const dictionary& codeDict() const;
 
 
diff --git a/src/fvOptions/sources/general/codedSource/CodedSource.C b/src/fvOptions/sources/general/codedSource/CodedSource.C
index f995b87ede..f07a64b5a2 100644
--- a/src/fvOptions/sources/general/codedSource/CodedSource.C
+++ b/src/fvOptions/sources/general/codedSource/CodedSource.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2016 OpenCFD Ltd.
+    \\  /    A nd           | Copyright (C) 2016-2019 OpenCFD Ltd.
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
                             | Copyright (C) 2012-2016 OpenFOAM Foundation
@@ -58,27 +58,28 @@ void Foam::fv::CodedSource<Type>::prepare
     // copy filtered H template
     dynCode.addCopyFile("codedFvOptionTemplate.H");
 
-    // debugging: make BC verbose
-    //         dynCode.setFilterVariable("verbose", "true");
-    //         Info<<"compile " << name_ << " sha1: "
-    //             << context.sha1() << endl;
+    // debugging: make  verbose
+    // dynCode.setFilterVariable("verbose", "true");
+    // DetailInfo
+    //     <<"compile " << name_ << " sha1: "
+    //     << context.sha1() << endl;
 
     // define Make/options
     dynCode.setMakeOptions
-        (
-            "EXE_INC = -g \\\n"
-            "-I$(LIB_SRC)/finiteVolume/lnInclude \\\n"
-            "-I$(LIB_SRC)/meshTools/lnInclude \\\n"
-            "-I$(LIB_SRC)/sampling/lnInclude \\\n"
-            "-I$(LIB_SRC)/fvOptions/lnInclude \\\n"
-            + context.options()
-            + "\n\nLIB_LIBS = \\\n"
-            + "    -lmeshTools \\\n"
-            + "    -lfvOptions \\\n"
-            + "    -lsampling \\\n"
-            + "    -lfiniteVolume \\\n"
-            + context.libs()
-        );
+    (
+        "EXE_INC = -g \\\n"
+        "-I$(LIB_SRC)/finiteVolume/lnInclude \\\n"
+        "-I$(LIB_SRC)/fvOptions/lnInclude \\\n"
+        "-I$(LIB_SRC)/meshTools/lnInclude \\\n"
+        "-I$(LIB_SRC)/sampling/lnInclude \\\n"
+      + context.options()
+      + "\n\nLIB_LIBS = \\\n"
+        "    -lfvOptions \\\n"
+        "    -lmeshTools \\\n"
+        "    -lsampling \\\n"
+        "    -lfiniteVolume \\\n"
+      + context.libs()
+    );
 }
 
 
diff --git a/src/fvOptions/sources/general/codedSource/CodedSource.H b/src/fvOptions/sources/general/codedSource/CodedSource.H
index 6e670bdb96..16d0777f45 100644
--- a/src/fvOptions/sources/general/codedSource/CodedSource.H
+++ b/src/fvOptions/sources/general/codedSource/CodedSource.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           |
+    \\  /    A nd           | Copyright (C) 2019 OpenCFD Ltd.
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
                             | Copyright (C) 2012-2016 OpenFOAM Foundation
@@ -131,12 +131,12 @@ template<class Type>
 class CodedSource
 :
     public cellSetOption,
-    public codedBase
+    protected codedBase
 {
 
 protected:
 
-    // Protected data
+    // Protected Data
 
         word name_;
 
@@ -156,13 +156,13 @@ protected:
         //- Adapt the context for the current object
         virtual void prepare(dynamicCode&, const dynamicCodeContext&) const;
 
-        // Return a description (type + name) for the output
+        //- Return a description (type + name) for the output
         virtual string description() const;
 
-        // Clear any redirected objects
+        //- Clear any redirected objects
         virtual void clearRedirect() const;
 
-        // Get the dictionary to initialize the codeContext
+        //- Get the dictionary to initialize the codeContext
         virtual const dictionary& codeDict() const;
 
 
@@ -189,42 +189,42 @@ public:
         //- Dynamically compiled fvOption
         option& redirectFvOption() const;
 
-        // Evaluation
-
-            //- Correct field
-            virtual void correct
-            (
-                GeometricField<Type, fvPatchField, volMesh>&
-            );
-
-            //- Explicit and implicit matrix contributions
-            virtual void addSup
-            (
-                fvMatrix<Type>& eqn,
-                const label fieldi
-            );
-
-            //- Explicit and implicit matrix contributions
-            //  to compressible equation
-            virtual void addSup
-            (
-                const volScalarField& rho,
-                fvMatrix<Type>& eqn,
-                const label fieldi
-            );
-
-            //- Set value
-            virtual void constrain
-            (
-                fvMatrix<Type>& eqn,
-                const label fieldi
-            );
-
-
-        // IO
-
-            //- Read source dictionary
-            virtual bool read(const dictionary& dict);
+
+    // Evaluation
+
+        //- Correct field
+        virtual void correct
+        (
+            GeometricField<Type, fvPatchField, volMesh>&
+        );
+
+        //- Explicit/implicit matrix contributions
+        virtual void addSup
+        (
+            fvMatrix<Type>& eqn,
+            const label fieldi
+        );
+
+        //- Explicit/implicit matrix contributions to compressible equation
+        virtual void addSup
+        (
+            const volScalarField& rho,
+            fvMatrix<Type>& eqn,
+            const label fieldi
+        );
+
+        //- Set value
+        virtual void constrain
+        (
+            fvMatrix<Type>& eqn,
+            const label fieldi
+        );
+
+
+    // IO
+
+        //- Read source dictionary
+        virtual bool read(const dictionary& dict);
 };
 
 
diff --git a/src/fvOptions/sources/general/codedSource/CodedSourceIO.C b/src/fvOptions/sources/general/codedSource/CodedSourceIO.C
index 6bd56cb6c5..0e0b1ea70e 100644
--- a/src/fvOptions/sources/general/codedSource/CodedSourceIO.C
+++ b/src/fvOptions/sources/general/codedSource/CodedSourceIO.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           |
+    \\  /    A nd           | Copyright (C) 2019 OpenCFD Ltd.
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
                             | Copyright (C) 2012-2016 OpenFOAM Foundation
@@ -33,63 +33,78 @@ License
 template<class Type>
 bool Foam::fv::CodedSource<Type>::read(const dictionary& dict)
 {
-    if (cellSetOption::read(dict))
+    codedBase::setCodeContext(coeffs_);
+
+    if (!cellSetOption::read(dict))
+    {
+        return false;
+    }
+
+    coeffs_.readEntry("fields", fieldNames_);
+    applied_.setSize(fieldNames_.size(), false);
+
+    dict.readCompat<word>("name", {{"redirectType", 1706}}, name_);
+
+    // Code chunks
+
+    codedBase::append("<codeCorrect>");
+    {
+        const entry& e =
+            coeffs_.lookupEntry("codeCorrect", keyType::LITERAL);
+
+        e.readEntry(codeCorrect_);
+        stringOps::inplaceTrim(codeCorrect_);
+        stringOps::inplaceExpand(codeCorrect_, coeffs_);
+
+        codedBase::append(codeCorrect_);
+
+        dynamicCodeContext::addLineDirective
+        (
+            codeCorrect_,
+            e.startLineNumber(),
+            coeffs_.name()
+        );
+    }
+
+    codedBase::append("<codeAddSup>");
     {
-        coeffs_.readEntry("fields", fieldNames_);
-        applied_.setSize(fieldNames_.size(), false);
-
-        dict.readCompat<word>("name", {{"redirectType", 1706}}, name_);
-
-        // Code snippets
-        {
-            const entry& e =
-                coeffs_.lookupEntry("codeCorrect", keyType::LITERAL);
-
-            e.readEntry(codeCorrect_);
-            stringOps::inplaceTrim(codeCorrect_);
-            stringOps::inplaceExpand(codeCorrect_, coeffs_);
-            dynamicCodeContext::addLineDirective
-            (
-                codeCorrect_,
-                e.startLineNumber(),
-                coeffs_.name()
-            );
-        }
-
-        {
-            const entry& e =
-                coeffs_.lookupEntry("codeAddSup", keyType::LITERAL);
-
-            e.readEntry(codeAddSup_);
-            stringOps::inplaceTrim(codeAddSup_);
-            stringOps::inplaceExpand(codeAddSup_, coeffs_);
-            dynamicCodeContext::addLineDirective
-            (
-                codeAddSup_,
-                e.startLineNumber(),
-                coeffs_.name()
-            );
-        }
-
-        {
-            const entry& e =
-                coeffs_.lookupEntry("codeSetValue", keyType::LITERAL);
-
-            e.readEntry(codeSetValue_);
-            stringOps::inplaceTrim(codeSetValue_);
-            stringOps::inplaceExpand(codeSetValue_, coeffs_);
-            dynamicCodeContext::addLineDirective
-            (
-                codeSetValue_,
-                e.startLineNumber(),
-                coeffs_.name()
-            );
-        }
-
-        return true;
+        const entry& e =
+            coeffs_.lookupEntry("codeAddSup", keyType::LITERAL);
+
+        e.readEntry(codeAddSup_);
+        stringOps::inplaceTrim(codeAddSup_);
+        stringOps::inplaceExpand(codeAddSup_, coeffs_);
+
+        codedBase::append(codeAddSup_);
+
+        dynamicCodeContext::addLineDirective
+        (
+            codeAddSup_,
+            e.startLineNumber(),
+            coeffs_.name()
+        );
+    }
+
+    codedBase::append("<codeSetValue>");
+    {
+        const entry& e =
+            coeffs_.lookupEntry("codeSetValue", keyType::LITERAL);
+
+        e.readEntry(codeSetValue_);
+        stringOps::inplaceTrim(codeSetValue_);
+        stringOps::inplaceExpand(codeSetValue_, coeffs_);
+
+        codedBase::append(codeSetValue_);
+
+        dynamicCodeContext::addLineDirective
+        (
+            codeSetValue_,
+            e.startLineNumber(),
+            coeffs_.name()
+        );
     }
 
-    return false;
+    return true;
 }
 
 
-- 
GitLab