diff --git a/BuildIssues.txt b/BuildIssues.txt
index e995ea510550e8af3d38fede5b211cffd57812e4..a05b5301c3c3217f6ef357024abaea952f16974f 100644
--- a/BuildIssues.txt
+++ b/BuildIssues.txt
@@ -118,34 +118,4 @@ your `~/.spack/packages.yaml` file:
 It appears that spack will otherwise ignore any paraview+qt version
 and attempt to install a paraview~qt version instead.
 
----------------------------
-Building on Darwin (Mac-OS)
----------------------------
-
-Support for Darwin is incomplete, but has been provisioned for.
-
-The following are typical (as of yet) unresolved issues.
-
-* Scotch, ptscotch:
-  - The librt linkage is required for Linux, but not for Darwin.
-
-  Current resolution:
-  Edit or patch
-      src/parallel/decompose/ptscotchDecomp/Make/options
-      src/parallel/decompose/scotchDecomp/Make/options
-
-  to remove the '-lrt' library
-
-* CGAL:
-  - ThirdParty CGAL will normally need to be compiled without mpfr/gmp.
-    This should be done manually prior to building OpenFOAM or other
-    ThirdParty. Eg,
-
-        cd $WM_THIRD_PARTY_DIR
-        ./makeCGAL gmp-none mpfr-none
-
-  The erroneous references to gmp/mpfr library can be directly removed
-  from the wmake/rules/General/CGAL, but it is more advisable to
-  override them instead in the wmake/rules/darwin64Clang/CGAL file.
-
 --
diff --git a/applications/test/00-dummy/dummy/dummyLib.C b/applications/test/00-dummy/dummy/dummyLib.C
index 383c431de51f8fa823ec98d8fcc96611c52171af..9963595c01953ce3c438dcd79239ad9f3caf5cda 100644
--- a/applications/test/00-dummy/dummy/dummyLib.C
+++ b/applications/test/00-dummy/dummy/dummyLib.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2018 OpenCFD Ltd.
+    \\  /    A nd           | Copyright (C) 2018-2019 OpenCFD Ltd.
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -30,6 +30,9 @@ License
 #if defined WM_SP
 # define PRECISION    "SP"
 # define SCALAR_SIZE  (8*sizeof(float))
+#elif defined(WM_SPDP)
+# define PRECISION    "SPDP"
+# define SCALAR_SIZE  (8*sizeof(float))
 #elif defined WM_DP
 # define PRECISION    "DP"
 # define SCALAR_SIZE  (8*sizeof(double))
@@ -38,9 +41,23 @@ License
 # define SCALAR_SIZE  (8*sizeof(long double))
 #endif
 
+// Test additional exported symbols
+#ifdef _WIN32
+    #define defineWindowsLibEntryPoint(libName)                               \
+        extern "C" void lib_##libName##_entry_point() {}
+#else
+    #define defineWindowsLibEntryPoint(libName)  /* Nothing */
+#endif
+
 
 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
 
+// The 'extern C' export is independent of namespace
+namespace Foam
+{
+    defineWindowsLibEntryPoint(dummyLib);
+}
+
 const std::string Foam::Detail::dummyLib::arch(WM_ARCH);
 
 const std::string Foam::Detail::dummyLib::compiler(WM_COMPILER);
diff --git a/applications/test/Matrix/Test-Matrix.C b/applications/test/Matrix/Test-Matrix.C
index 7c9cb61195f2624a006c1ab43fed33a322addf6d..dbccf225fabf27df0105deb71fa58e9740d6b051 100644
--- a/applications/test/Matrix/Test-Matrix.C
+++ b/applications/test/Matrix/Test-Matrix.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) 2011-2016 OpenFOAM Foundation
@@ -25,162 +25,946 @@ License
 
 \*---------------------------------------------------------------------------*/
 
-#include "scalarMatrices.H"
+#include "MatrixTools.H"
 #include "LUscalarMatrix.H"
 #include "LLTMatrix.H"
-#include "QRMatrix.H"
-#include "vector.H"
-#include "tensor.H"
-#include "IFstream.H"
+#include "Random.H"
+#include "SortList.H"
+#include <algorithm>
 
 using namespace Foam;
+using namespace Foam::MatrixTools;
 
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-// Main program:
+#define isEqual MatrixTools::equal
 
-int main(int argc, char *argv[])
+void horizontalLine()
 {
-    SquareMatrix<scalar> hmm(3);
+    Info<< "+---------+---------+---------+---------+---------+" << nl;
+}
 
-    hmm(0, 0) = -3.0;
-    hmm(0, 1) = 10.0;
-    hmm(0, 2) = -4.0;
-    hmm(1, 0) = 2.0;
-    hmm(1, 1) = 3.0;
-    hmm(1, 2) = 10.0;
-    hmm(2, 0) = 2.0;
-    hmm(2, 1) = 6.0;
-    hmm(2, 2) = 1.0;
 
-    //Info<< hmm << endl << hmm - 2.0*(-hmm) << endl;
-    Info<< max(hmm) << endl;
-    Info<< min(hmm) << endl;
+// Copy values into matrix
+template<class Form, class Type>
+void assignMatrix
+(
+    Matrix<Form, Type>& mat,
+    std::initializer_list<typename Matrix<Form, Type>::cmptType> list
+)
+{
+    const label nargs = list.size();
 
-    SquareMatrix<scalar> hmm2(3, I);
+    if (nargs != mat.size())
+    {
+        FatalErrorInFunction
+            << "Mismatch in matrix dimension ("
+            << mat.m() << ", "
+            << mat.n() << ") and number of args (" << nargs << ')' << nl
+            << exit(FatalError);
+     }
+
+    std::copy(list.begin(), list.end(), mat.begin());
+}
 
-    hmm = hmm2;
 
-    Info<< hmm << endl;
+template<class MatrixType>
+MatrixType makeRandomMatrix
+(
+    const labelPair& dims,
+    Random& rndGen
+)
+{
+    MatrixType mat(dims);
 
-    //SquareMatrix<scalar> hmm3(Sin);
+    std::generate
+    (
+        mat.begin(),
+        mat.end(),
+        [&]{return rndGen.GaussNormal<typename MatrixType::cmptType>();}
+    );
 
-    //Info<< hmm3 << endl;
+    return mat;
+}
 
-    SquareMatrix<scalar> hmm4;
 
-    hmm4 = hmm2;
+template<class MatrixType>
+Ostream& operator<<(Ostream& os, const ConstMatrixBlock<MatrixType>& mat)
+{
+    return MatrixTools::printMatrix(os, mat);
+}
 
-    Info<< hmm4 << endl;
 
-    SquareMatrix<scalar> hmm5;
+template<class MatrixType>
+Ostream& operator<<(Ostream& os, const MatrixBlock<MatrixType>& mat)
+{
+    return MatrixTools::printMatrix(os, mat);
+}
+
+
+// * * * * * * * * * * * * * * * Main Program  * * * * * * * * * * * * * * * //
 
-    hmm4 = hmm5;
-    Info<< hmm5 << endl;
+int main(int argc, char *argv[])
+{
+    typedef SquareMatrix<scalar> SMatrix;
+    typedef SquareMatrix<complex> SCMatrix;
+    typedef RectangularMatrix<scalar> RMatrix;
+    typedef RectangularMatrix<complex> RCMatrix;
 
+    Random rndGen(1234);
+
+    #if 1
     {
-        RectangularMatrix<scalar> rm1(5, 6, 3.1);
-        rm1(0, 1) = 4.5;
-        RectangularMatrix<scalar> rm1b(rm1.block(2, 2, 0, 0));
-        Info<< "rm1b = " << rm1b << endl;
+        horizontalLine();
+
+        Info<< "## Matrix Constructors & Assignments:" << nl << nl;
+
+        Info<< "# SquareMatrix<scalar> examples:" << nl;
+        {
+            const label mRows = 2;
+            const label nCols = 2;
+            Matrix<SMatrix, scalar> MS0(mRows, nCols);
+            Matrix<SMatrix, scalar> MS1(mRows, nCols, Zero);
+            Matrix<SMatrix, scalar> MS2(mRows, nCols, 17.44);
+            Matrix<SMatrix, scalar> MS3(MS2);
+
+            SMatrix S0(mRows);
+            SMatrix S1(mRows, Zero);
+            SMatrix S2(mRows, I);
+            SMatrix S3(mRows, 17.44);
+            SMatrix S4(2, Zero);
+            SMatrix S5(labelPair{mRows, nCols});
+            SMatrix S6(mRows, nCols, Zero);
+            SMatrix S7({mRows, nCols}, Zero);
+            SMatrix S8({mRows, nCols}, 17.44);
+            assignMatrix
+            (
+                S8,
+                {
+                    1, 2,    // 0th row
+                    3, 4     // 1st row and so on
+                }
+            );
+
+            S1 = Zero;
+            S2 = 13.13;
+            S3 = I;
+        }
+
+        Info<< "# RectangularMatrix<scalar> examples:" << nl;
+        {
+            const label mRows = 2;
+            const label nCols = 3;
+            Matrix<RMatrix, scalar> MR0(mRows, nCols);
+            Matrix<RMatrix, scalar> MR1(mRows, nCols, Zero);
+            Matrix<RMatrix, scalar> MR2(mRows, nCols, 17.44);
+
+            RMatrix R0(mRows, nCols);
+            RMatrix R1(labelPair{mRows, nCols});
+            RMatrix R2(mRows, nCols, Zero);
+            RMatrix R3({mRows, nCols}, Zero);
+            RMatrix R4(mRows, nCols, -17.44);
+            RMatrix R5({mRows, nCols}, -17.44);
+            RMatrix R6(3, 4, Zero);
+            RMatrix R7({3, 4}, Zero);
+            assignMatrix
+            (
+                R7,
+                {
+                    1, 2, 3, 4,
+                    5, 6, 7, 8.8,
+                    9, 10, 11, 12
+                }
+            );
+            R0 = Zero;
+            R2 = -13.13;
+        }
+
+        Info<< "# SquareMatrix<complex> examples:" << nl;
+        {
+            const label mRows = 2;
+            const label nCols = 2;
+            Matrix<SCMatrix, complex> MS0(mRows, nCols);
+            Matrix<SCMatrix, complex> MS1(mRows, nCols, Zero);
+            Matrix<SCMatrix, complex> MS2(mRows, nCols, complex(17.44, 44.17));
+            Matrix<SCMatrix, complex> MS3(MS2);
+
+            SCMatrix S0(mRows);
+            SCMatrix S1(mRows, Zero);
+            SCMatrix S2(mRows, I);
+            SCMatrix S3(mRows, complex(17.44,0));
+            SCMatrix S4(2, Zero);
+            SCMatrix S5(labelPair{mRows, nCols});
+            SCMatrix S6(mRows, nCols, Zero);
+            SCMatrix S7({mRows, nCols}, Zero);
+            SCMatrix S8({mRows, nCols}, complex(17.44,0));
+            assignMatrix
+            (
+                S8,
+                {
+                    complex(1,0), complex(2,2),
+                    complex(4,2), complex(5,0)
+                }
+            );
+
+            S1 = Zero;
+            S2 = complex(13.13,0);
+            S3 = I;
+        }
+
+        Info<< nl;
+        horizontalLine();
     }
+    #endif
 
-    {
-        scalarSymmetricSquareMatrix symmMatrix(3, Zero);
 
-        symmMatrix(0, 0) = 4;
-        symmMatrix(1, 0) = 12;
-        symmMatrix(1, 1) = 37;
-        symmMatrix(2, 0) = -16;
-        symmMatrix(2, 1) = -43;
-        symmMatrix(2, 2) = 98;
+    #if 1
+    {
+        horizontalLine();
+
+        Info<< "## Access Functions:" << nl;
+
+        SMatrix S(3, Zero);
+        assignMatrix
+        (
+            S,
+            {
+                -3, 11, -4,
+                2, 3, 10,
+                2, 6, 1
+            }
+        );
+        S(0,1) = 10;
+
+        Info<< "# SquareMatrix<scalar> example:" << nl;
+        printMatrix(Info, S) << nl;
+
+        const label mRows = S.m();
+        const label nCols = S.n();
+        const label size = S.size();
+        const labelPair sizes = S.sizes();
+        const bool isEmpty = S.empty();
+        const long constPointer = long(S.cdata());
+        long pointer = long(S.data());
+
+        Info
+            << "Number of rows =" << tab << mRows << nl
+            << "Number of columns = " << tab << nCols << nl
+            << "Number of elements = " << tab << size << nl
+            << "Number of rows/columns = " << tab << sizes << nl
+            << "Matrix is empty = " << tab << isEmpty << nl
+            << "Constant pointer = " << tab << constPointer << nl
+            << "Pointer = " << tab << pointer << nl
+            << nl;
+
+        horizontalLine();
+    }
+    #endif
 
-        Info<< "Symmetric Square Matrix = " << symmMatrix << endl;
 
-        Info<< "Inverse = " << inv(symmMatrix) << endl;
-        Info<< "Determinant = " << det(symmMatrix) << endl;
+    #if 1
+    {
+        horizontalLine();
+
+        Info<< "## Block Access Functions:" << nl;
+
+        RMatrix R(4, 3, Zero);
+        assignMatrix
+        (
+            R,
+            {
+                -3, 11, -4,
+                2, 3, 10,
+                2, 6, 1,
+                1, 2, 3
+            }
+        );
+
+        Info<< "# RectangularMatrix<scalar> example:" << nl;
+        printMatrix(Info, R) << nl;
+
+        // Indices begin at 0
+        const label columnI = 1;
+        const label rowI = 2;
+        const label colStartI = 1;
+        const label rowStartI = 1;
+        const label szRows = 2;
+        const label szCols = 2;
+
+        Info
+            << "column: " << R.subColumn(columnI) << nl
+            << "sub-column: " << R.subColumn(columnI, rowStartI) << nl
+            << "sub-sub-column: " << R.subColumn(columnI, rowStartI, szRows) << nl
+            << "row: " << R.subRow(rowI) << nl
+            << "sub-row: " << R.subRow(rowI, colStartI) << nl
+            << "sub-sub-row: " << R.subRow(rowI, colStartI, szCols) << nl
+            << "sub-block: " << R.subMatrix(rowStartI, colStartI) << nl
+            << "sub-block with row size: " << R.subMatrix(rowStartI, colStartI, szRows) << nl
+            << "sub-block with row|col size: " << R.subMatrix(rowStartI, colStartI, szRows, szCols) << nl;
+
+        horizontalLine();
+    }
+    #endif
 
-        scalarSymmetricSquareMatrix symmMatrix2(symmMatrix);
-        LUDecompose(symmMatrix2);
 
-        Info<< "Inverse = " << invDecomposed(symmMatrix2) << endl;
-        Info<< "Determinant = " << detDecomposed(symmMatrix2) << endl;
+    #if 1
+    {
+        horizontalLine();
+
+        Info<< "## Edit Functions:" << nl;
+
+        RMatrix R(2, 2, Zero);
+        assignMatrix
+        (
+            R,
+            {
+                1, 2,
+                3, 4
+            }
+        );
+
+        Info<< "# Before Matrix.clear():" << nl << R << nl;
+        R.clear();
+        Info<< "# After Matrix.clear():" << nl << R << nl;
+
+        Info<< "# Before Matrix.resize(m, n):" << nl << R;
+        R.resize(3, 2);
+        Info<< "# After Matrix.resize(m, n):" << nl << R << nl << nl;
+
+        // Steal matrix contents
+        Info<< "# Before Matrix.release():" << nl << R << nl;
+        List<scalar> newOwner(R.release());
+        Info<< "# After Matrix.release():" << nl << R
+            << "& corresponding List content:" << nl << newOwner << nl << nl;
+
+        R.resize(3, 2);
+        assignMatrix
+        (
+            R,
+            {
+                1, 2,
+                5, 6,
+                9e-19, 1e-17
+            }
+        );
+
+        Info<< "# Before Matrix.round():" << nl << R << nl;
+        R.round();
+        Info<< "# After Matrix.round():" << nl << R << nl << nl;
+
+        Info<< "# Before Matrix.T() (Transpose):" << nl << R << nl;
+        RMatrix RT = R.T();
+        Info<< "# After Matrix.T():" << nl << RT << nl << nl;
+
+        RCMatrix RC(3, 2, Zero);
+        assignMatrix
+        (
+            RC,
+            {
+                complex(1, 0), complex(2,5),
+                complex(4, 3), complex(1,-1),
+                complex(1, 2), complex(2,9)
+            }
+        );
+
+        Info<< "# Before Matrix.T() (Hermitian transpose):" << nl << RC << nl;
+        RCMatrix RCH = RC.T();
+        Info<< "# After Matrix.T():" << nl << RCH << nl << nl;
+
+        Info<< "# Diagonal and trace:" << nl;
+        RMatrix R1(5, 7, 3.4);
+        {
+            List<scalar> diagR = R1.diag();
+            scalar traceR = R1.trace();
+            Info<< "RectangularMatrix<scalar>:"
+                << nl << R1 << nl
+                << "Major diagonal of RectangularMatrix:"
+                << nl << diagR << nl
+                << "Trace of RectangularMatrix:"
+                << nl << traceR << nl << nl;
+        }
 
-        scalarDiagonalMatrix rhs(3, 0);
-        rhs[0] = 1;
-        rhs[1] = 2;
-        rhs[2] = 3;
+        Info<< "# List assignment to the main diagonal of Matrix:" << nl;
+        {
+            SMatrix S1(5, I);
+            Info<< "Before List assignment:" << nl;
+            printMatrix(Info, S1);
+            List<scalar> lst(5, 2.0);
+            S1.diag(lst);
+            Info<< "After List assignment:" << nl;
+            printMatrix(Info, S1);
+        }
 
-        LUsolve(symmMatrix, rhs);
+        Info<< "# Diagonal sort of Matrix:" << nl;
+        {
+            auto S1
+            (
+                makeRandomMatrix<SMatrix>
+                (
+                    {3, 3}, rndGen
+                )
+            );
+
+            List<scalar> diag = S1.diag();
+            SortList<scalar> incrDiag(diag);
+            incrDiag.sort();
+
+            Info<< "Diagonal list:" << diag << nl
+                << "Ascending diagonal list: " << incrDiag << nl << nl;
+        }
 
-        Info<< "Decomposition = " << symmMatrix << endl;
-        Info<< "Solution = " << rhs << endl;
+        horizontalLine();
     }
+    #endif
 
 
-    scalarSquareMatrix squareMatrix(3, Zero);
+    #if 1
+    {
+        horizontalLine();
+
+        Info<< "## Transpose Verifications:" << nl;
 
-    squareMatrix(0, 0) = 4;
-    squareMatrix(0, 1) = 12;
-    squareMatrix(0, 2) = -16;
-    squareMatrix(1, 0) = 12;
-    squareMatrix(1, 1) = 37;
-    squareMatrix(1, 2) = -43;
-    squareMatrix(2, 0) = -16;
-    squareMatrix(2, 1) = -43;
-    squareMatrix(2, 2) = 98;
+        const label numberOfTests = 10;
+
+        for (label i = 0; i < numberOfTests; ++i)
+        {
+            const label mRows = rndGen.position(1,10);
+            const label nCols = rndGen.position(1,10);
+
+            Info << "# SquareMatrix<scalar> example:" << nl;
+            {
+                Info<< "A(mxm) where m = " << mRows << nl;
+                auto A(makeRandomMatrix<SMatrix>({mRows, mRows}, rndGen));
+                auto B(makeRandomMatrix<SMatrix>({mRows, mRows}, rndGen));
+
+                Info<< nl << "# (A.T()).T() = A:" << nl;
+                isEqual((A.T()).T(), A, true);
+
+                Info<< nl << "# (A + B).T() = A.T() + B.T():" << nl;
+                isEqual((A + B).T(), A.T() + B.T(), true);
+
+                Info<< nl << "# (A*B).T() = B.T()*A.T():" << nl;
+                isEqual((A*B).T(), B.T()*A.T(), true);
+                Info<< nl << nl;
+            }
+
+            Info << "# RectangularMatrix<scalar> example:" << nl;
+            {
+                Info<< "A(mxn) where"
+                    << " m = " << mRows << ","
+                    << " n = " << nCols << nl;
+                auto A(makeRandomMatrix<RMatrix>({mRows, nCols}, rndGen));
+                auto B(makeRandomMatrix<RMatrix>({mRows, nCols}, rndGen));
+                auto C(makeRandomMatrix<RMatrix>({nCols, mRows}, rndGen));
+
+                Info<< nl << "# (A.T()).T() = A:" << nl;
+                isEqual((A.T()).T(), A, true);
+
+                Info<< nl << "# (A + B).T() = A.T() + B.T():" << nl;
+                isEqual((A + B).T(), A.T() + B.T(), true);
+
+                Info<< nl << "# (A*C).T() = C.T()*C.T():" << nl;
+                isEqual((A*C).T(), C.T()*A.T(), true);
+                Info<< nl << nl;
+            }
+
+            Info << "# SquareMatrix<complex> example:" << nl;
+            {
+                Info<< "A(mxm) where m = " << mRows << nl;
+                SCMatrix A(mRows);
+                SCMatrix B(mRows);
+
+                for (auto& val : A)
+                {
+                    val.Re() = rndGen.GaussNormal<scalar>();
+                    val.Im() = rndGen.GaussNormal<scalar>();
+                }
+                for (auto& val : B)
+                {
+                    val.Re() = rndGen.GaussNormal<scalar>();
+                    val.Im() = rndGen.GaussNormal<scalar>();
+                }
+
+                Info<< nl << "# (A.T()).T() = A:" << nl;
+                isEqual((A.T()).T(), A, true);
+
+                Info<< nl << "# (A + B).T() = A.T() + B.T():" << nl;
+                isEqual((A + B).T(), A.T() + B.T(), true);
+
+                Info<< nl << "# (A*B).T() = B.T()*A.T():" << nl;
+                isEqual((A*B).T(), B.T()*A.T(), true);
+                Info<< nl << nl;
+            }
+        }
 
-    Info<< nl << "Square Matrix = " << squareMatrix << endl;
+        horizontalLine();
+    }
+    #endif
 
-    const scalarField source(3, 1);
 
+    #if 1
     {
+        horizontalLine();
+
+        Info<< "## Scalar Arithmetic Operations:" << nl;
+
+        if (true)
         {
-            scalarSquareMatrix sm(squareMatrix);
-            Info<< "det = " << det(sm) << endl;
+            SMatrix S1(3, Zero);
+            assignMatrix
+            (
+                S1,
+                {
+                    4.1, 12.5, -16.3,
+                    -192.3, -9.1, -3.0,
+                    1.0, 5.02, -4.4
+                }
+            );
+            SMatrix S2 = S1;
+            SMatrix S3(3, Zero);
+
+            Info<< "SquareMatrix<scalar> S1 = " << S1 << nl;
+            Info<< "SquareMatrix<scalar> S2 = " << S2 << nl;
+            Info<< "SquareMatrix<scalar> S3 = " << S3 << nl;
+
+            S3 = S1*S2;
+            Info<< "S1*S2 = " << S3 << nl;
+
+            S3 = S1 - S2;
+            Info<< "S1 - S2 = " << S3 << nl;
+
+            S3 = S1 + S2;
+            Info<< "S1 + S2 = " << S3 << nl;
+
+//          S3 *= S1; // Not Implemented
+
+            S3 -= S1;
+            Info<< "S3 -= S1; S3 = " << S3 << nl;
+
+            S3 += S1;
+            Info<< "S3 += S1; S3 = " << S3 << nl;
+
+
+            Info<< nl << "# Scalar broadcasting:" << nl;
+
+            S3 *= 5.0;
+            Info<< "S3 *= 5.0; S3 = " << S3 << nl;
+
+            S3 /= 5.0;
+            Info<< "S3 /= 5.0; S3 = " << S3 << nl;
+
+            S3 -= 1.0;
+            Info<< "S3 -= 1.0; S3 = " << S3 << nl;
+
+            S3 += 1.0;
+            Info<< "S3 += 1.0; S3 = " << S3 << nl;
+
+
+            Info<< nl << "# Operations between different matrix types:" << nl;
+            RMatrix R1 = S1;
+            Info<< "RectangularMatrix<scalar> R1 = " << R1 << nl;
+
+            // RectangularMatrix*SquareMatrix returns RectangularMatrix
+            // S3 = S3*R1; // Not implemented
+            R1 = S3*R1;
+            Info<< "R1 = S3*R1; R1 = " << R1 << nl;
+
+            S3 = S3 - R1;
+            Info<< "S3 = S3 - R1; S3 = " << S3 << nl;
+
+            S3 = S3 + R1;
+            Info<< "S3 = S3 + R1; S3 = " << S3 << nl;
+
+            R1 = S3 + R1;
+            Info<< "R1 = S3 + R1; R1 = " << R1 << nl;
+
+
+            Info<< nl << "# Extrema operations:" << nl;
+
+            Info<< "min(S3) = " << min(S3) << nl
+                << "max(S3) = " << max(S3) << nl
+                << "minMax(S3) = " << minMax(S3) << nl;
         }
 
-        scalarSquareMatrix sm(squareMatrix);
-        labelList rhs(3, 0);
-        label sign;
-        LUDecompose(sm, rhs, sign);
+        if (true)
+        {
+            Info<< nl << "# Operations with ListTypes<scalar>:" << nl;
+
+            SMatrix A(3, Zero);
+            assignMatrix
+            (
+                A,
+                {
+                    4.1, 12.5, -16.3,
+                    -192.3, -9.1, -3.0,
+                    1.0, 5.02, -4.4
+                }
+            );
+            const List<scalar> lst({1, 2, 3});
+            RMatrix colVector(3, 1, Zero);
+            assignMatrix
+            (
+                colVector,
+                {1, 2, 3}
+            );
+            RMatrix rowVector(1, 3, Zero);
+            assignMatrix
+            (
+                rowVector,
+                {1, 2, 3}
+            );
+
+            Info<< "A = " << A << nl;
+            Info<< "colVector = " << colVector << nl;
+            Info<< "rowVector = " << rowVector << nl;
+
+            const Field<scalar> field1(A.Amul(lst));
+            const Field<scalar> field2(A*lst);
+            const Field<scalar> field3(A.Tmul(lst));
+            const Field<scalar> field4(lst*A);
+
+            Info
+                << "Field1 = A*lst = A.Amul(lst):" << nl << field1 << nl
+                << "Field2 = A*lst:" << nl << field2 << nl
+                << "A*colVector:" << nl << A*colVector << nl
+                << "Field3 = lst*A = A.Tmul(lst):" << nl << field3 << nl
+                << "Field4 = lst*A:" << nl << field4 << nl
+                << "rowVector*A:" << nl << rowVector*A << nl
+                << nl;
+        }
 
-        Info<< "Decomposition = " << sm << endl;
-        Info<< "Pivots = " << rhs << endl;
-        Info<< "Sign = " << sign << endl;
-        Info<< "det = " << detDecomposed(sm, sign) << endl;
+        if (true)
+        {
+            Info<< nl << "# Implicit inner/outer products:" << nl;
+
+            const scalar r = 2.0;
+            RMatrix A(3, 2, Zero);
+            assignMatrix
+            (
+                A,
+                {
+                    1, 2,
+                    3, 4,
+                    5, 6
+                }
+            );
+            const RMatrix B(A);
+            const RMatrix C(B);
+
+            Info<< nl << "# Inner product:" << nl;
+            {
+                Info<< "- Explicit vs Implicit => A.T()*B == A&B:" << nl;
+                isEqual(A.T()*B, A&B, true);
+
+                Info<< "- Commutative => A&B == B&A:" << nl;
+                isEqual(A&B, B&A, true);
+
+                Info<< "- Distributive => A&(B+C) == A&B + A&C:" << nl;
+                isEqual(A&(B + C), (A&B) + (A&C), true);
+
+                Info<< "- Bilinear => A&(rB+C) == r(A&B) + (A&C):" << nl;
+                isEqual(A&(r*B + C), r*(A&B) + (A&C), true);
+
+                Info<< "- Scalar multiplication => (rA)&(rB) == rr(A&B):" << nl;
+                isEqual((r*A)&(r*B), r*r*(A&B), true);
+            }
+
+            Info<< nl << "# Outer product:" << nl;
+            {
+                Info<< "- Explicit vs Implicit => A*B.T() == A^B:" << nl;
+                isEqual(A*B.T(), A^B, true);
+
+                Info<< "- Commutative => A^B == B^A:" << nl;
+                isEqual(A^B, B^A, true);
+
+                Info<< "- Distributive => A^(B+C) == A^B + A^C:" << nl;
+                isEqual(A^(B + C), (A^B) + (A^C), true);
+
+                Info<< "- Scalar multiplication => r*(A^B) == (r*A)^B:" << nl;
+                isEqual(r*(A^B), (r*A)^B, true);
+            }
+        }
+
+        Info<< nl;
+        horizontalLine();
     }
+    #endif
 
+
+    #if 1
     {
-        LUscalarMatrix LU(squareMatrix);
-        scalarField x(LU.solve(source));
-        Info<< "LU solve residual " << (squareMatrix*x - source) << endl;
-
-        scalarSquareMatrix inv(3);
-        LU.inv(inv);
-        Info<< "LU inv " << inv << endl;
-        Info<< "LU inv*squareMatrix " << (inv*squareMatrix) << endl;
+        horizontalLine();
+
+        Info<< "## Complex Arithmetic Operations:" << nl;
+
+        if (true)
+        {
+            SCMatrix S1(3, Zero);
+            assignMatrix
+            (
+                S1,
+                {
+                    complex(4.1, 1.0), complex(12.5, -1), complex(-16.3,-3),
+                    complex(-192.3, 5), complex(-9.1, 3), complex(-3.0, 1),
+                    complex(1.0, 3), complex(5.02, 0.3), complex(-4.4, 1)
+                }
+            );
+            SCMatrix S2 = S1;
+            SCMatrix S3(3, Zero);
+
+            Info<< "SquareMatrix<complex> S1 = " << S1 << nl;
+            Info<< "SquareMatrix<complex> S2 = " << S2 << nl;
+            Info<< "SquareMatrix<complex> S3 = " << S3 << nl;
+
+            S3 = S1*S2;
+            Info<< "S1*S2 = " << S3 << nl;
+
+            S3 = S1 - S2;
+            Info<< "S1 - S2 = " << S3 << nl;
+
+            S3 = S1 + S2;
+            Info<< "S1 + S2 = " << S3 << nl;
+
+//          S3 *= S1; // Not Implemented
+
+            S3 -= S1;
+            Info<< "S3 -= S1; S3 = " << S3 << nl;
+
+            S3 += S1;
+            Info<< "S3 += S1; S3 = " << S3 << nl;
+
+
+            Info<< nl << "# Complex broadcasting:" << nl;
+
+            S3 *= complex(5, 0);
+            Info<< "S3 *= complex(5, 0); S3 = " << S3 << nl;
+
+            S3 /= complex(5, 0);
+            Info<< "S3 /= complex(5, 0); S3 = " << S3 << nl;
+
+            S3 -= complex(1, 0);
+            Info<< "S3 -= complex(1, 0); S3 = " << S3 << nl;
+
+            S3 += complex(1, 0);
+            Info<< "S3 += complex(1, 0); S3 = " << S3 << nl;
+
+
+            Info<< nl << "# Operations between different matrix types:" << nl;
+            RCMatrix R1 = S1;
+            Info<< "RectangularMatrix<complex> R1 = " << R1 << nl;
+
+            R1 = S3*R1;
+            Info<< "R1 = S3*R1; R1 = " << R1 << nl;
+
+            S3 = S3 - R1;
+            Info<< "S3 = S3 - R1; S3 = " << S3 << nl;
+
+            S3 = S3 + R1;
+            Info<< "S3 = S3 + R1:" << S3 << nl;
+
+            // Extrama operations // Not Implemented
+        }
+
+        if (true)
+        {
+            Info<< nl << "# Operations with ListTypes<complex>:" << nl;
+
+            SCMatrix A(3, Zero);
+            assignMatrix
+            (
+                A,
+                {
+                    complex(4.1, 1.0), complex(12.5, -1), complex(-16.3,-3),
+                    complex(-192.3, 5), complex(-9.1, 3), complex(-3.0, 1),
+                    complex(1.0, 3), complex(5.02, 0.3), complex(-4.4, 1)
+                }
+            );
+            const List<complex> lst({complex(1,1), complex(2,2), complex(3,3)});
+            RCMatrix colVector(3, 1, Zero);
+            assignMatrix
+            (
+                colVector,
+                {complex(1,1), complex(2,2), complex(3,3)}
+            );
+            RCMatrix rowVector(1, 3, Zero);
+            assignMatrix
+            (
+                rowVector,
+                {complex(1,1), complex(2,2), complex(3,3)}
+            );
+
+            Info<< "A = " << A << nl;
+            Info<< "colVector = " << colVector << nl;
+            Info<< "rowVector = " << rowVector << nl;
+
+            const Field<complex> field1(A.Amul(lst));
+            const Field<complex> field2(A*lst);
+            const Field<complex> field3(A.Tmul(lst));
+            const Field<complex> field4(lst*A);
+
+            Info
+                << "Field1 = A*lst = A.Amul(lst):" << nl << field1 << nl
+                << "Field2 = A*lst:" << nl << field2 << nl
+                << "A*colVector:" << nl << A*colVector << nl
+                << "Field3 = lst*A = A.Tmul(lst):" << nl << field3 << nl
+                << "Field4 = lst*A:" << nl << field4 << nl
+                << "rowVector*A:" << nl << rowVector*A << nl
+                << nl;
+        }
+
+        #if 1
+        {
+            Info<< nl << "# Implicit inner/outer products:" << nl;
+
+            const complex r(2.0,1.0);
+            RCMatrix A(3, 2, Zero);
+            assignMatrix
+            (
+                A,
+                {
+                    complex(1,0), complex(2,1),
+                    complex(3,-0.3), complex(4,-1),
+                    complex(0.5,-0.1), complex(6,0.4)
+                }
+            );
+            const RCMatrix B(A);
+            const RCMatrix C(B);
+
+            Info<< nl << "# Inner product:" << nl;
+            {
+                Info<< "- Explicit vs Implicit => A.T()*B == A&B:" << nl;
+                isEqual(A.T()*B, A&B, true);
+
+                Info<< "- Commutative => A&B == B&A:" << nl;
+                isEqual(A&B, B&A, true);
+
+                Info<< "- Distributive => A&(B+C) == A&B + A&C:" << nl;
+                isEqual(A&(B + C), (A&B) + (A&C), true);
+
+                Info<< "- Bilinear => A&(rB+C) == r(A&B) + (A&C):" << nl;
+                isEqual(A&(r*B + C), r*(A&B) + (A&C), true);
+            }
+
+            Info<< nl << "# Outer product:" << nl;
+            {
+                Info<< "- Explicit vs Implicit => A*B.T() == A^B:" << nl;
+                isEqual(A*B.T(), A^B, true);
+
+                Info<< "- Commutative => A^B == B^A:" << nl;
+                isEqual(A^B, B^A, true);
+
+                Info<< "- Distributive => A^(B+C) == A^B + A^C:" << nl;
+                isEqual(A^(B + C), (A^B) + (A^C), true);
+
+                Info<< "- Scalar multiplication => r*(A^B) == (r*A)^B:" << nl;
+                isEqual(r*(A^B), (r*A)^B, true);
+            }
+        }
+        #endif
+
+        Info<< nl;
+        horizontalLine();
     }
+    #endif
 
+
+    #if 1
     {
-        LLTMatrix<scalar> LLT(squareMatrix);
-        scalarField x(LLT.solve(source));
-        Info<< "LLT solve residual " << (squareMatrix*x - source) << endl;
+        horizontalLine();
+
+        Info<< "## SymmetricSquareMatrix<scalar> algorithms:" << nl;
+
+        scalarSymmetricSquareMatrix symm(3, Zero);
+
+        symm(0, 0) = 4;
+        symm(1, 0) = 12;
+        symm(1, 1) = 37;
+        symm(2, 0) = -16;
+        symm(2, 1) = -43;
+        symm(2, 2) = 98;
+
+        Info<< "SymmetricSquareMatrix = " << nl << symm << nl
+            << "Inverse = " << nl << inv(symm) << nl
+            << "Determinant = " << det(symm) << nl;
+
+        scalarSymmetricSquareMatrix symm2(symm);
+        LUDecompose(symm2);
+        Info<< "LU decomposition:" << nl
+            << "Inverse = " << nl << invDecomposed(symm2) << nl
+            << "Determinant = " << detDecomposed(symm2) << nl;
+
+        scalarDiagonalMatrix rhs(3, 0);
+        rhs[0] = 1;
+        rhs[1] = 2;
+        rhs[2] = 3;
+
+        LUsolve(symm, rhs);
+        Info<< "Solving linear system through LU decomposition:" << nl
+            << "Decomposition = " << nl << symm << nl
+            << "Solution = " << rhs << nl;
     }
+    #endif
 
+
+    #if 1
     {
-        QRMatrix<scalarSquareMatrix> QR(squareMatrix);
-        scalarField x(QR.solve(source));
+        scalarSquareMatrix squareMatrix(3, Zero);
+
+        scalarSquareMatrix S(3, Zero);
+        assignMatrix
+        (
+            S,
+            {
+                4, 12, -16,
+                12, 37, -43,
+                -16, -43, 98
+            }
+        );
+
+        const scalarField source(3, 1);
+
+        Info<< nl << "Square Matrix = " << S << endl;
 
-        Info<< "QR solve residual "
-            << (squareMatrix*x - source) << endl;
+        if (true)
+        {
+            {
+                scalarSquareMatrix S2(S);
+                Info<< "Determinant = " << det(S2) << nl;
+            }
+
+            scalarSquareMatrix S2(S);
+            labelList rhs(3, 0);
+            label sign;
+            LUDecompose(S2, rhs, sign);
+
+            Info<< "LU decomposition = " << S2 << nl
+                << "Pivots = " << rhs << nl
+                << "Sign = " << sign << nl
+                << "Determinant = " << detDecomposed(S2, sign) << nl;
+        }
+
+        if (true)
+        {
+            LUscalarMatrix LU(S);
+            scalarField x(LU.solve(source));
+            scalarSquareMatrix inv(3);
+            LU.inv(inv);
+            Info<< "LU.solve(source) residual: " << (S*x - source)
+                << nl << "LU inv " << inv << nl
+                << "LU inv*S " << (inv*S) << nl;
+        }
 
-        Info<< "QR inverse solve residual "
-            << (x - QR.inv()*source) << endl;
+        if (true)
+        {
+            LLTMatrix<scalar> LLT(S);
+            scalarField x(LLT.solve(source));
+            Info<< "LLT solve residual " << (S*x - source) << nl;
+        }
 
-        Info<< "QR inv *squareMatrix " << (QR.inv()*squareMatrix) << endl;
+        horizontalLine();
     }
+    #endif
+
 
-    Info<< "\nEnd\n" << endl;
+    Info<< nl << "End" << nl;
 
     return 0;
 }
diff --git a/applications/test/complex/Test-complex.C b/applications/test/complex/Test-complex.C
index 938f63fb8eb3db5d501368b56bf9b59bbb54fa9d..57551c50607ec80c8661519498c8c457522cb771 100644
--- a/applications/test/complex/Test-complex.C
+++ b/applications/test/complex/Test-complex.C
@@ -24,11 +24,12 @@ License
 Application
 
 Description
-    Some tests for complex numbers
+    Tests for complex numbers
 
 \*---------------------------------------------------------------------------*/
 
 #include "argList.H"
+#include "complex.H"
 #include "complexFields.H"
 #include "ops.H"
 #include "ListOps.H"
@@ -41,15 +42,14 @@ void print1(const complex& z)
 }
 
 
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-//  Main program:
+// * * * * * * * * * * * * * * * Main Program  * * * * * * * * * * * * * * * //
 
 int main(int argc, char *argv[])
 {
     Info<< "complex()     : " << complex() << nl
         << "complex(zero) : " << complex(Zero) << nl
-        << "complex::zero : " << complex::zero << nl
-        << "complex::one  : " << complex::one << nl
+        << "pTraits<complex>::zero : " << pTraits<complex>::zero << nl
+        << "pTraits<complex>::one  : " << pTraits<complex>::one << nl
         << "complex(scalar) : " << complex(3.14519) << nl
         << nl;
 
@@ -57,7 +57,6 @@ int main(int argc, char *argv[])
     Info<< "std::complex : " << c1 << nl;
     Info<< "sin: " << std::sin(c1) << nl;
 
-
     Info<< "complexVector::zero : " << complexVector::zero << nl
         << "complexVector::one  : " << complexVector::one << nl
         << nl;
@@ -98,6 +97,7 @@ int main(int argc, char *argv[])
         c.Im() *= 5;
     }
 
+    Info<< "sumProd: " << sumProd(fld1, fld2) << nl;
 
     fld1 *= 10;
     Info<< "scalar multiply: " << flatOutput(fld1) << nl;
@@ -113,11 +113,140 @@ int main(int argc, char *argv[])
 
     // Info<< "operator * : " << (fld1 * fld2) << nl;
     // Info<< "operator / : " << (fld1 / fld2) << nl;
-    Info<< "operator / : " << (fld1 / 2) << nl;
+    // Info<< "operator / : " << (fld1 / 2) << nl;
     // Info<< "operator / : " << (fld1 / fld2) << nl;
-    Info<< "sqrt   : " << sqrt(fld1) << nl;
+    // Info<< "sqrt   : " << sqrt(fld1) << nl;
     // Info<< "pow(2) : " << pow(fld1, 2) << nl;
 
+    #if 1
+    Info<< nl << "## Elementary complex-complex arithmetic operations:" << nl;
+    {
+        const complex a(6, 1);
+        complex b = a;
+
+        Info << "# Compound assignment operations:" << nl;
+
+        Info<< "a = " << a << ", b = " << b << nl;
+
+        // Addition
+        b += a;
+        Info<< "b += a:" << tab << "b =" << b << nl;
+
+        // Subtraction
+        b -= a;
+        Info<< "b -= a:" << tab << "b =" << b << nl;
+
+        // Multiplication
+        b *= a;
+        Info<< "b *= a:" << tab << "b =" << b << nl;
+
+        // Division
+        b /= a;
+        Info<< "b /= a:" << tab << "b =" << b << nl;
+    }
+    #endif
+
+
+    #if 1
+    Info<< nl << "## Elementary complex-scalar arithmetic operations:" << nl;
+    {
+        const scalar a = 5;
+        complex b(6, 1);
+
+        Info << "# Non-assignment operations:" << nl;
+
+        Info<< "(scalar) a = " << a << ", b = " << b << nl;
+
+        // Addition
+        b = a + b;
+        Info<< "b = a + b: " << tab << b << nl;
+
+        b = b + a;
+        Info<< "b = b + a: " << tab << b << nl;
+
+        // Subtraction
+        b = a - b;
+        Info<< "b = a - b: " << tab << b << nl;
+
+        b = b - a;
+        Info<< "b = b - a: " << tab << b << nl;
+
+        // Multiplication
+        b = a*b;
+        Info<< "b = a*b: " << tab << b << nl;
+
+        b = b*a;
+        Info<< "b = b*a: " << tab << b << nl;
+
+        // Division
+        b = a/b;
+        Info<< "b = a/b = scalar(a)/b = complex(a)/b:" << tab << b << nl;
+
+        b = b/a;
+        Info<< "b = b/a: " << tab << b << nl;
+
+
+        Info << "# Compound assignment operations:" << nl;
+
+        Info<< "(scalar) a = " << a << ", b = " << b << nl;
+
+        // Addition: complex+scalar
+        b += a;
+        Info<< "b += a (only real part):" << tab << b << nl;
+
+        // Subtraction: complex-scalar
+        b -= a;
+        Info<< "b -= a (only real part):" << tab << b << nl;
+
+        // Multiplication: complex*scalar
+        b *= a;
+        Info<< "b *= a (real and imag parts):" << tab << b << nl;
+
+        // Division: complex/scalar
+        b /= a;
+        Info<< "b /= a (real and imag parts):" << tab << b << nl;
+
+    }
+    #endif
+
+
+    #if 1
+    Info<< nl << "## Other mathematical expressions:" << nl;
+    {
+        const complex a(4.3, -3.14);
+        const complex b(0, -4.3);
+        const complex c(-4.3, 0);
+
+        Info<< "a = " << a << ", b = " << b << ", c = " << c << nl;
+
+        // Square-root
+        Info<< "sqrt(a) = " << Foam::sqrt(a) << ", "
+            << "sqrt(b) = " << Foam::sqrt(b) << ", "
+            << "sqrt(c) = " << Foam::sqrt(c) << nl;
+
+        // Square
+        Info<< "sqr(a) = " << sqr(a) << ", "
+            << "sqr(b) = " << sqr(b) << ", "
+            << "sqr(c) = " << sqr(c) << nl;
+
+        // n^th power
+        Info<< "pow(a, -1) = " << pow(a, -1) << ", "
+            << "pow(b, -1) = " << pow(b, -1) << ", "
+            << "pow(c, -1) = " << pow(c, -1) << nl;
+
+        // Exponential
+        Info<< "exp(a) = " << exp(a) << ", "
+            << "exp(b) = " << exp(b) << ", "
+            << "exp(c) = " << exp(c) << nl;
+
+        // Natural logarithm
+        Info<< "log(a) = " << log(a) << ", "
+            << "log(b) = " << log(b) << ", "
+            << "log(c) = " << log(c) << nl;
+
+    }
+    #endif
+
 
     // Make some changes
     {
@@ -150,6 +279,7 @@ int main(int argc, char *argv[])
     // Info<< "min/max = " << MinMax<complex>(fld1) << nl;
 
     Info<< "\nEnd\n" << endl;
+
     return 0;
 }
 
diff --git a/applications/test/dictionary2/Test-dictionary2.C b/applications/test/dictionary2/Test-dictionary2.C
index d66e0d0590074d8430e5a953e2370e9f2cbd547a..b05c18c3c34fa4c62b23b533515db887d064053d 100644
--- a/applications/test/dictionary2/Test-dictionary2.C
+++ b/applications/test/dictionary2/Test-dictionary2.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2017-2018 OpenCFD Ltd.
+    \\  /    A nd           | Copyright (C) 2017-2019 OpenCFD Ltd.
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -34,6 +34,8 @@ Description
 #include "IOobject.H"
 #include "IFstream.H"
 #include "dictionary.H"
+#include "ops.H"
+#include "scalarRange.H"
 #include "stringOps.H"
 
 using namespace Foam;
@@ -108,6 +110,42 @@ scalar try_getScalar(const dictionary& dict, const word& k)
 }
 
 
+// Try with getCheck<scalar>
+template<class Predicate>
+scalar try_getCheckScalar
+(
+    const dictionary& dict,
+    const word& k,
+    const Predicate& pred
+)
+{
+    scalar val(-GREAT);
+
+    const bool throwingIOError = FatalIOError.throwExceptions();
+    const bool throwingError = FatalError.throwExceptions();
+
+    try
+    {
+        val = dict.getCheck<scalar>(k, pred);
+        Info<< "getCheck<scalar>(" << k << ") = " << val << nl;
+    }
+    catch (const Foam::IOerror& err)
+    {
+        Info<< "getCheck<scalar>(" << k << ") Caught FatalIOError "
+            << err << nl << endl;
+    }
+    catch (const Foam::error& err)
+    {
+        Info<< "getCheck<scalar>(" << k << ") Caught FatalError "
+            << err << nl << endl;
+    }
+    FatalError.throwExceptions(throwingError);
+    FatalIOError.throwExceptions(throwingIOError);
+
+    return val;
+}
+
+
 // Try with *entry (from findEntry) and get<scalar>
 scalar try_getScalar(const entry* eptr, const word& k)
 {
@@ -311,6 +349,7 @@ int main(int argc, char *argv[])
             IStringStream
             (
                 "good 3.14159;\n"
+                "negative -3.14159;\n"
                 "empty;\n"
                 // "bad  text;\n"            // always fails
                 // "bad  3.14159 1234;\n"    // fails for readScalar
@@ -338,6 +377,26 @@ int main(int argc, char *argv[])
             try_getScalar(dict2, "empty");
         }
 
+
+        // With getCheck<scalar>
+        {
+            Info<< nl << "Test some input with getCheck<scalar>()" << nl;
+
+            try_getCheckScalar(dict2, "good", scalarRange::gt0());
+            try_getCheckScalar(dict2, "negative", scalarRange::gt0());
+
+            try_getCheckScalar(dict2, "good", greaterOp1<scalar>(0));
+            try_getCheckScalar(dict2, "negative", greaterOp1<scalar>(0));
+
+            Info<< nl << "with lambda" << nl;
+            try_getCheckScalar
+            (
+                dict2,
+                "good",
+                [](const scalar x) { return x > 0; }
+            );
+        }
+
         // With findEntry and get<scalar>
         {
             Info<< nl
diff --git a/applications/test/regex1/Test-regex1.C b/applications/test/regex1/Test-regex1.C
index ca5bfb60cd4d59cc3f2611dd2b4bf44da5255815..9bc38d64b2b6e484d28651c977ce574354cd1e7b 100644
--- a/applications/test/regex1/Test-regex1.C
+++ b/applications/test/regex1/Test-regex1.C
@@ -27,12 +27,16 @@ Description
 \*---------------------------------------------------------------------------*/
 
 #include "argList.H"
+#include "IOobject.H"
 #include "IOstreams.H"
 #include "IFstream.H"
 #include "Switch.H"
 
+#include "SubStrings.H"
 #include "regExpCxx.H"
+#ifndef _WIN32
 #include "regExpPosix.H"
+#endif
 
 using namespace Foam;
 
@@ -83,6 +87,7 @@ static Ostream& operator<<(Ostream& os, const regExpCxx::results_type& sm)
 
 
 // Simple output of match groups
+#ifndef _WIN32
 static Ostream& operator<<(Ostream& os, const regExpPosix::results_type& sm)
 {
     for (std::smatch::size_type i = 1; i < sm.size(); ++i)
@@ -92,6 +97,7 @@ static Ostream& operator<<(Ostream& os, const regExpPosix::results_type& sm)
 
     return os;
 }
+#endif
 
 
 template<class RegexType>
@@ -209,7 +215,6 @@ void generalTests()
 }
 
 
-
 template<class RegexType>
 void testExpressions(const UList<regexTest>& tests)
 {
@@ -293,11 +298,13 @@ int main(int argc, char *argv[])
         "Test C++11 regular expressions"
     );
 
+    #ifndef _WIN32
     argList::addBoolOption
     (
         "posix",
         "Test POSIX regular expressions"
     );
+    #endif
 
     argList::addArgument("file");
     argList::addArgument("...");
@@ -306,6 +313,17 @@ int main(int argc, char *argv[])
 
     #include "setRootCase.H"
 
+    if (std::is_same<regExp, regExpCxx>::value)
+    {
+        Info<<"Foam::regExp uses C++11 regex" << nl << nl;
+    }
+    #ifndef _WIN32
+    if (std::is_same<regExp, regExpPosix>::value)
+    {
+        Info<<"Foam::regExp uses POSIX regex" << nl << nl;
+    }
+    #endif
+
     if (!args.count({"cxx", "posix"}))
     {
         Info<< "Specified one or more of -cxx, -posix" << nl;
@@ -321,10 +339,12 @@ int main(int argc, char *argv[])
             generalTests<regExpCxx>();
         }
 
+        #ifndef _WIN32
         if (args.found("posix"))
         {
             generalTests<regExpPosix>();
         }
+        #endif
     }
 
     for (label argi = 1; argi < args.size(); ++argi)
@@ -339,10 +359,12 @@ int main(int argc, char *argv[])
             testExpressions<regExpCxx>(tests);
         }
 
+        #ifndef _WIN32
         if (args.found("posix"))
         {
             testExpressions<regExpPosix>(tests);
         }
+        #endif
     }
 
     Info<< "\nDone" << nl << endl;
diff --git a/applications/test/regex1/testRegexps2 b/applications/test/regex1/testRegexps2
new file mode 100644
index 0000000000000000000000000000000000000000..d74f8cec152bd7afa0eb89f5281099fef0771f5c
--- /dev/null
+++ b/applications/test/regex1/testRegexps2
@@ -0,0 +1,23 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v1812                                 |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+// Pattern, String
+(
+    ( true  "(U|k|epsilon)"  "U" )
+    ( false "(U|k|epsilon)"  "alpha" )
+    ( true  "ab.*"  "abc" )
+    ( true  ".*"  "abc" )
+
+    ( true "div\(phi,alpha.*)"   "div(phi,alpha.gas)" )   // quoting error
+    ( true "div\(phi,alpha.*\)"   "div(phi,alpha.gas)" )
+    ( true "div\(phi,alpha\..*\)" "div(phi,alpha.gas)" )
+)
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
diff --git a/applications/test/scalarPredicates/Test-scalarPredicates.C b/applications/test/scalarPredicates/Test-scalarPredicates.C
index 22338e91746fcb1dde1b22d304bd9297bc9d9c9f..587ca38b0d4f83aaefa871167ca3e828fb887881 100644
--- a/applications/test/scalarPredicates/Test-scalarPredicates.C
+++ b/applications/test/scalarPredicates/Test-scalarPredicates.C
@@ -36,6 +36,8 @@ Description
 #include "FlatOutput.H"
 #include "Tuple2.H"
 #include "StringStream.H"
+#include "ops.H"
+#include "bitSet.H"
 
 using namespace Foam;
 
@@ -44,7 +46,7 @@ void doTest(const scalarList& values, const predicates::scalars& accept)
 {
     // Also tests that output is suppressed
     Info<<"Have: " << accept.size() << " predicates" << accept << endl;
-    Info<<"values: " << flatOutput(values)  << endl;
+    Info<<"values: " << flatOutput(values) << endl;
 
     for (const scalar& value : values)
     {
@@ -60,6 +62,30 @@ void doTest(const scalarList& values, const predicates::scalars& accept)
 }
 
 
+template<class Predicate>
+void testPredicate(const scalarList& values, const Predicate& pred)
+{
+    bitSet matches;
+
+    label i=0;
+
+    for (const scalar& value : values)
+    {
+        if (pred(value))
+        {
+            matches.set(i);
+        }
+
+        ++i;
+    }
+
+    IndirectList<scalar> matched(values, matches.toc());
+
+    Info<< "matched: " << flatOutput(matched.addressing())
+        << " = " << flatOutput(matched) << nl;
+}
+
+
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 //  Main program:
 
@@ -149,6 +175,16 @@ int main(int argc, char *argv[])
     }
 
 
+    Info<< nl << "Test with ops" << nl;
+    Info<<"values: " << flatOutput(values) << endl;
+    {
+        testPredicate(values, lessOp1<scalar>(10));
+        testPredicate(values, greaterOp1<scalar>(100));
+
+        // Also with dissimilar type
+        testPredicate(values, lessEqOp1<label>(0));
+    }
+
     Info<< "\nEnd\n" << endl;
 
     return 0;
diff --git a/applications/test/wmake1/Test-wmake1.C b/applications/test/wmake1/Test-wmake1.C
index 614d9189fb8e2c9964383340c2c7b0f7330ae0b1..ac3469c2049a1ab468dd7b8ac9003c31f21bd696 100644
--- a/applications/test/wmake1/Test-wmake1.C
+++ b/applications/test/wmake1/Test-wmake1.C
@@ -47,6 +47,12 @@ int main(int argc, char *argv[])
 {
     printTest();
 
+    #ifdef FULLDEBUG
+    Info<< nl << "Compiled with FULLDEBUG" << nl;
+    #else
+    Info<< nl << "Regular compilation" << nl;
+    #endif
+
     Info<< "\nEnd\n" << nl;
 
     return 0;
diff --git a/applications/utilities/mesh/generation/snappyHexMesh/snappyHexMesh.C b/applications/utilities/mesh/generation/snappyHexMesh/snappyHexMesh.C
index d3040ffac3b7ad04499d8477745ff565fe150cb5..898ddae241ad7244e1a602a8544d57911fc1bde6 100644
--- a/applications/utilities/mesh/generation/snappyHexMesh/snappyHexMesh.C
+++ b/applications/utilities/mesh/generation/snappyHexMesh/snappyHexMesh.C
@@ -779,7 +779,7 @@ int main(int argc, char *argv[])
     const bool overwrite = args.found("overwrite");
     const bool checkGeometry = args.found("checkGeometry");
     const bool surfaceSimplify = args.found("surfaceSimplify");
-    const bool dryRun = args.optionFound("dry-run");
+    const bool dryRun = args.found("dry-run");
 
     if (dryRun)
     {
@@ -788,7 +788,6 @@ int main(int argc, char *argv[])
     }
 
 
-
     #include "createNamedMesh.H"
     Info<< "Read mesh in = "
         << runTime.cpuTimeIncrement() << " s" << endl;
diff --git a/applications/utilities/parallelProcessing/redistributePar/redistributePar.C b/applications/utilities/parallelProcessing/redistributePar/redistributePar.C
index f24962b01dabf2fd624df22793a831f7856ab799..d1bda27c3195ed18bb91a2bd2279a5d4f02dc103 100644
--- a/applications/utilities/parallelProcessing/redistributePar/redistributePar.C
+++ b/applications/utilities/parallelProcessing/redistributePar/redistributePar.C
@@ -2307,7 +2307,9 @@ int main(int argc, char *argv[])
     // ~~~~~~~~~~~~~~~~
     // (replacement for setRootCase that does not abort)
 
-    Foam::argList args(argc, argv);
+    argList args(argc, argv);
+    #include "foamDlOpenLibs.H"
+
     const bool reconstruct = args.found("reconstruct");
     const bool writeCellDist = args.found("cellDist");
     const bool dryrun = args.found("dry-run");
diff --git a/applications/utilities/preProcessing/foamUpgradeCyclics/foamUpgradeCyclics.C b/applications/utilities/preProcessing/foamUpgradeCyclics/foamUpgradeCyclics.C
index 5c7ea648140e2fce89841b45cf893800300d077a..c948cbf9ab0a1eb531ddcdc784d76a21805d9db8 100644
--- a/applications/utilities/preProcessing/foamUpgradeCyclics/foamUpgradeCyclics.C
+++ b/applications/utilities/preProcessing/foamUpgradeCyclics/foamUpgradeCyclics.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) 2011-2016 OpenFOAM Foundation
@@ -313,7 +313,7 @@ void rewriteField
         if
         (
             boundaryField.found(patchName)
-        && !boundaryField.found(newName, false, false)
+        && !boundaryField.found(newName, keyType::LITERAL)
         )
         {
             Info<< "    Changing entry " << patchName << " to " << newName
diff --git a/applications/utilities/preProcessing/mapFields/mapFields.C b/applications/utilities/preProcessing/mapFields/mapFields.C
index f7d399a6031817f5883e7c72474e40a69da18d36..249cfc3d3b124f204b79931a28b26cc7a691ea8f 100644
--- a/applications/utilities/preProcessing/mapFields/mapFields.C
+++ b/applications/utilities/preProcessing/mapFields/mapFields.C
@@ -276,11 +276,11 @@ int main(int argc, char *argv[])
 
 
     argList args(argc, argv);
-
     if (!args.check())
     {
         FatalError.exit();
     }
+    #include "foamDlOpenLibs.H"
 
     fileName rootDirTarget(args.rootPath());
     fileName caseDirTarget(args.globalCaseName());
diff --git a/applications/utilities/preProcessing/mapFieldsPar/mapFieldsPar.C b/applications/utilities/preProcessing/mapFieldsPar/mapFieldsPar.C
index 4b580f6a878ddc639e1c97ae57870fd2bcd86b9c..13494ace9e23efc6bb909bf34b6dd2689ab4b5ad 100644
--- a/applications/utilities/preProcessing/mapFieldsPar/mapFieldsPar.C
+++ b/applications/utilities/preProcessing/mapFieldsPar/mapFieldsPar.C
@@ -208,6 +208,7 @@ int main(int argc, char *argv[])
     );
 
     argList args(argc, argv);
+    #include "foamDlOpenLibs.H"
 
     fileName rootDirTarget(args.rootPath());
     fileName caseDirTarget(args.globalCaseName());
diff --git a/bin/Co b/bin/Co
deleted file mode 120000
index e575b13fb589e1fd45abb5f7f48c3c63b76d5a3c..0000000000000000000000000000000000000000
--- a/bin/Co
+++ /dev/null
@@ -1 +0,0 @@
-deprecated/Co
\ No newline at end of file
diff --git a/bin/Lambda2 b/bin/Lambda2
deleted file mode 120000
index 14361924c1decc04d9c9f8677f18115ec240153c..0000000000000000000000000000000000000000
--- a/bin/Lambda2
+++ /dev/null
@@ -1 +0,0 @@
-deprecated/Lambda2
\ No newline at end of file
diff --git a/bin/Mach b/bin/Mach
deleted file mode 120000
index a780ea0a91c41cc002e078f765be6cfc1ace2402..0000000000000000000000000000000000000000
--- a/bin/Mach
+++ /dev/null
@@ -1 +0,0 @@
-deprecated/Mach
\ No newline at end of file
diff --git a/bin/Pe b/bin/Pe
deleted file mode 120000
index 78e3ff2dc661b3dfba287f3ba21bf90b36a0f142..0000000000000000000000000000000000000000
--- a/bin/Pe
+++ /dev/null
@@ -1 +0,0 @@
-deprecated/Pe
\ No newline at end of file
diff --git a/bin/Q b/bin/Q
deleted file mode 120000
index a0ae7b33e18365fa90e43319457baff5b53b79a7..0000000000000000000000000000000000000000
--- a/bin/Q
+++ /dev/null
@@ -1 +0,0 @@
-deprecated/Q
\ No newline at end of file
diff --git a/bin/R b/bin/R
deleted file mode 120000
index cde1a96978c5a80958591c6c8b7e2dfb4359be5e..0000000000000000000000000000000000000000
--- a/bin/R
+++ /dev/null
@@ -1 +0,0 @@
-deprecated/R
\ No newline at end of file
diff --git a/bin/createTurbulenceFields b/bin/createTurbulenceFields
deleted file mode 120000
index 008ddca6e97c9daaf037ff0bf4f3b22b1846a13e..0000000000000000000000000000000000000000
--- a/bin/createTurbulenceFields
+++ /dev/null
@@ -1 +0,0 @@
-deprecated/createTurbulenceFields
\ No newline at end of file
diff --git a/bin/deprecated/Co b/bin/deprecated/Co
deleted file mode 100755
index c29f870fb6804be00f62ac7ef44b54b94408cdcd..0000000000000000000000000000000000000000
--- a/bin/deprecated/Co
+++ /dev/null
@@ -1,41 +0,0 @@
-#!/bin/sh
-#------------------------------------------------------------------------------
-# =========                 |
-# \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
-#  \\    /   O peration     |
-#   \\  /    A nd           |
-#    \\/     M anipulation  |
-#-------------------------------------------------------------------------------
-#                           | Copyright (C) 2016 OpenFOAM Foundation
-#------------------------------------------------------------------------------
-# 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 <http://www.gnu.org/licenses/>.
-#
-# Script
-#     Co
-#
-# Description
-#     Script to suggest using the new "-postProcess" solver option.
-#
-#------------------------------------------------------------------------------
-Script=${0##*/}
-
-echo $Script "has been superceded by the -postProcess solver option:"
-echo "<solverName> -func CourantNo"
-echo "e.g."
-echo "pimpleFoam -postProcess -func CourantNo"
-
-#------------------------------------------------------------------------------
diff --git a/bin/deprecated/Lambda2 b/bin/deprecated/Lambda2
deleted file mode 120000
index 7b00da8e40ebd1030970ddd69f73d5a820da0dee..0000000000000000000000000000000000000000
--- a/bin/deprecated/Lambda2
+++ /dev/null
@@ -1 +0,0 @@
-supercededByPostProcess
\ No newline at end of file
diff --git a/bin/deprecated/Mach b/bin/deprecated/Mach
deleted file mode 100755
index 9854d354f79f09fdebc524a03671ac24a8860ed7..0000000000000000000000000000000000000000
--- a/bin/deprecated/Mach
+++ /dev/null
@@ -1,41 +0,0 @@
-#!/bin/sh
-#------------------------------------------------------------------------------
-# =========                 |
-# \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
-#  \\    /   O peration     |
-#   \\  /    A nd           |
-#    \\/     M anipulation  |
-#-------------------------------------------------------------------------------
-#                           | Copyright (C) 2016 OpenFOAM Foundation
-#------------------------------------------------------------------------------
-# 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 <http://www.gnu.org/licenses/>.
-#
-# Script
-#     Mach
-#
-# Description
-#     Script to suggest using the new "-postProcess" solver option.
-#
-#------------------------------------------------------------------------------
-Script=${0##*/}
-
-echo $Script "has been superceded by the -postProcess solver option:"
-echo "<solverName> -func MachNo"
-echo "e.g."
-echo "sonicFoam -postProcess -func MachNo"
-
-#------------------------------------------------------------------------------
diff --git a/bin/deprecated/Pe b/bin/deprecated/Pe
deleted file mode 100755
index ca7d1c155fe6361f3036a89814da7cf4400af088..0000000000000000000000000000000000000000
--- a/bin/deprecated/Pe
+++ /dev/null
@@ -1,41 +0,0 @@
-#!/bin/sh
-#------------------------------------------------------------------------------
-# =========                 |
-# \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
-#  \\    /   O peration     |
-#   \\  /    A nd           |
-#    \\/     M anipulation  |
-#-------------------------------------------------------------------------------
-#                           | Copyright (C) 2016 OpenFOAM Foundation
-#------------------------------------------------------------------------------
-# 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 <http://www.gnu.org/licenses/>.
-#
-# Script
-#     Pe
-#
-# Description
-#     Script to suggest using the new "-postProcess" solver option.
-#
-#------------------------------------------------------------------------------
-Script=${0##*/}
-
-echo $Script "has been superceded by the -postProcess solver option:"
-echo "<solverName> -func PecletNo"
-echo "e.g."
-echo "pimpleFoam -postProcess -func PecletNo"
-
-#------------------------------------------------------------------------------
diff --git a/bin/deprecated/Q b/bin/deprecated/Q
deleted file mode 120000
index 7b00da8e40ebd1030970ddd69f73d5a820da0dee..0000000000000000000000000000000000000000
--- a/bin/deprecated/Q
+++ /dev/null
@@ -1 +0,0 @@
-supercededByPostProcess
\ No newline at end of file
diff --git a/bin/deprecated/R b/bin/deprecated/R
deleted file mode 120000
index ff6b4704c676ee88d208606b8f93dbb37e4fe62e..0000000000000000000000000000000000000000
--- a/bin/deprecated/R
+++ /dev/null
@@ -1 +0,0 @@
-supercededByPostProcessOption
\ No newline at end of file
diff --git a/bin/deprecated/createTurbulenceFields b/bin/deprecated/createTurbulenceFields
deleted file mode 100755
index 90f492d6d84626dedd5df7eb8763a1af235c3120..0000000000000000000000000000000000000000
--- a/bin/deprecated/createTurbulenceFields
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/bin/sh
-#------------------------------------------------------------------------------
-# =========                 |
-# \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
-#  \\    /   O peration     |
-#   \\  /    A nd           |
-#    \\/     M anipulation  |
-#-------------------------------------------------------------------------------
-#                           | Copyright (C) 2016 OpenFOAM Foundation
-#------------------------------------------------------------------------------
-# 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 <http://www.gnu.org/licenses/>.
-#
-# Script
-#     createTurbulenceFields
-#
-# Description
-#     Replacement script to suggest using the new "-postProcess"
-#     solver command-line option.
-#
-#------------------------------------------------------------------------------
-Script=${0##*/}
-
-echo $Script "has been superceded by the \
-'-postProcess' solver command-line option, e.g."
-
-echo "simpleFoam -postProcess -func 'turbulenceFields(R, omega)'"
-
-#------------------------------------------------------------------------------
diff --git a/bin/deprecated/enstrophy b/bin/deprecated/enstrophy
deleted file mode 120000
index 7b00da8e40ebd1030970ddd69f73d5a820da0dee..0000000000000000000000000000000000000000
--- a/bin/deprecated/enstrophy
+++ /dev/null
@@ -1 +0,0 @@
-supercededByPostProcess
\ No newline at end of file
diff --git a/bin/deprecated/execFlowFunctionObjects b/bin/deprecated/execFlowFunctionObjects
deleted file mode 100755
index c31517e00b1b610469b48ff826c46093e57575dc..0000000000000000000000000000000000000000
--- a/bin/deprecated/execFlowFunctionObjects
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/bin/sh
-#------------------------------------------------------------------------------
-# =========                 |
-# \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
-#  \\    /   O peration     |
-#   \\  /    A nd           |
-#    \\/     M anipulation  |
-#-------------------------------------------------------------------------------
-#                           | Copyright (C) 2016 OpenFOAM Foundation
-#------------------------------------------------------------------------------
-# 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 <http://www.gnu.org/licenses/>.
-#
-# Script
-#     execFlowFunctionObjects
-#
-# Description
-#     Replacement execFlowFunctionObjects to suggest using the "-postProcess"
-#     solver command-line option.
-#
-#------------------------------------------------------------------------------
-
-echo "execFlowFunctionObjects has been superceded by the \
-'-postProcess' solver command-line option, e.g."
-
-echo "simpleFoam -help -postProcess"
-simpleFoam -help -postProcess
-
-#------------------------------------------------------------------------------
diff --git a/bin/deprecated/flowType b/bin/deprecated/flowType
deleted file mode 120000
index 7b00da8e40ebd1030970ddd69f73d5a820da0dee..0000000000000000000000000000000000000000
--- a/bin/deprecated/flowType
+++ /dev/null
@@ -1 +0,0 @@
-supercededByPostProcess
\ No newline at end of file
diff --git a/bin/deprecated/foamCalc b/bin/deprecated/foamCalc
deleted file mode 100755
index 5749b653a4dfa50e23be8299340c86cce9865648..0000000000000000000000000000000000000000
--- a/bin/deprecated/foamCalc
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/bin/sh
-#------------------------------------------------------------------------------
-# =========                 |
-# \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
-#  \\    /   O peration     |
-#   \\  /    A nd           |
-#    \\/     M anipulation  |
-#-------------------------------------------------------------------------------
-#                           | Copyright (C) 2016 OpenFOAM Foundation
-#------------------------------------------------------------------------------
-# 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 <http://www.gnu.org/licenses/>.
-#
-# Script
-#     foamCalc
-#
-# Description
-#     Replacement foamCalc to suggest using the new "postProcess" utility.
-#
-#------------------------------------------------------------------------------
-
-echo "foamCalc has been superceded by the postProcess utility:"
-echo "    postProcess -help"
-postProcess -help
-
-#------------------------------------------------------------------------------
diff --git a/bin/deprecated/foamDebugSwitches b/bin/deprecated/foamDebugSwitches
deleted file mode 100755
index c04e31bccc967dd3c4c3270919379998b0d3d55c..0000000000000000000000000000000000000000
--- a/bin/deprecated/foamDebugSwitches
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/bin/sh
-#------------------------------------------------------------------------------
-# =========                 |
-# \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
-#  \\    /   O peration     |
-#   \\  /    A nd           |
-#    \\/     M anipulation  |
-#-------------------------------------------------------------------------------
-#                           | Copyright (C) 2016 OpenFOAM Foundation
-#------------------------------------------------------------------------------
-# 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 <http://www.gnu.org/licenses/>.
-#
-# Script
-#     foamDebugSwitches
-#
-# Description
-#     Script to suggest using the new "foamList" utility.
-#
-#------------------------------------------------------------------------------
-Script=${0##*/}
-
-echo $Script "has been superceded by the foamList utility:"
-echo "foamList -debug"
-
-#------------------------------------------------------------------------------
diff --git a/bin/deprecated/foamGraphExecTime b/bin/deprecated/foamGraphExecTime
deleted file mode 100755
index 7a4ebc0b8f272de8db3895d003b59a335770b878..0000000000000000000000000000000000000000
--- a/bin/deprecated/foamGraphExecTime
+++ /dev/null
@@ -1,54 +0,0 @@
-#!/bin/sh
-#------------------------------------------------------------------------------
-# =========                 |
-# \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
-#  \\    /   O peration     |
-#   \\  /    A nd           |
-#    \\/     M anipulation  |
-#-------------------------------------------------------------------------------
-#                           | Copyright (C) 2011-2017 OpenFOAM Foundation
-#------------------------------------------------------------------------------
-# 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 <http://www.gnu.org/licenses/>.
-#
-# Script
-#     foamGraphExecTime
-#
-# Description
-#     Deprecated script extract the 'ExecutionTime' for each time-step from a
-#     log file for graphing.
-#
-#     Superseded by the more general foamLog script.
-#------------------------------------------------------------------------------
-Script=${0##*/}
-
-if [ ! -f "$1" ]; then
-    echo "$Script: $1 is not a valid filename"
-    exit 1
-fi
-
-tmpTime=newTime$$.dat
-cat $1 | \
-    grep "ExecutionTime = " | \
-    awk 'BEGIN { NENTRIES = 0 ; TPREV = 0.0 }{NENTRIES++; printf("%f %e\n", NENTRIES, $3 - TPREV); TPREV = $3}' - > $tmpTime
-
-if [ "$(cat $tmpTime | wc -l)" -gt 1 ]; then
-    mv $tmpTime executionTime.dat
-fi
-
-rm -f $tmpTime
-
-#------------------------------------------------------------------------------
diff --git a/bin/deprecated/foamGraphResKE b/bin/deprecated/foamGraphResKE
deleted file mode 100755
index 2f9e7aab1bb634bcd7e147f79320180724ff8fab..0000000000000000000000000000000000000000
--- a/bin/deprecated/foamGraphResKE
+++ /dev/null
@@ -1,66 +0,0 @@
-#!/bin/sh
-#------------------------------------------------------------------------------
-# =========                 |
-# \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
-#  \\    /   O peration     |
-#   \\  /    A nd           |
-#    \\/     M anipulation  |
-#-------------------------------------------------------------------------------
-#                           | Copyright (C) 2011-2017 OpenFOAM Foundation
-#------------------------------------------------------------------------------
-# 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 <http://www.gnu.org/licenses/>.
-#
-# Script
-#     foamGraphResKE
-#
-# Description
-#     Deprecated script extract initial turbulence residuals for each time-step
-#     from a log file for graphing.
-#
-#     Superseded by the more general foamLog script.
-#------------------------------------------------------------------------------
-Script=${0##*/}
-
-if [ ! -f "$1" ]; then
-    echo "$Script: $1 is not a valid filename"
-    exit 1
-fi
-
-scan()
-{
-    tmpFile=new$1$$.dat
-    cat $2 | \
-        grep "Solving for $1" | \
-        grep -v "solution singularity" | \
-        sed s/,//g | \
-        awk 'BEGIN { NENTRIES = 0 }{NENTRIES++; printf("%d %e\n", NENTRIES, $8)}' - > $tmpFile
-
-    if [ "$(cat $tmpFile | wc -l)" -gt 1 ]; then
-        echo >> residualKE.dat
-        cat $tmpFile >> residualKE.dat
-    fi
-
-    rm $tmpFile
-}
-
-rm -f residualKE.dat
-scan "k" $1
-scan "epsilon" $1
-scan "omega" $1
-scan "nuTilda" $1
-
-#------------------------------------------------------------------------------
diff --git a/bin/deprecated/foamGraphResUVWP b/bin/deprecated/foamGraphResUVWP
deleted file mode 100755
index ec0d14513ce2c260ed96a3d8e6abe6d7338ff752..0000000000000000000000000000000000000000
--- a/bin/deprecated/foamGraphResUVWP
+++ /dev/null
@@ -1,66 +0,0 @@
-#!/bin/sh
-#------------------------------------------------------------------------------
-# =========                 |
-# \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
-#  \\    /   O peration     |
-#   \\  /    A nd           |
-#    \\/     M anipulation  |
-#-------------------------------------------------------------------------------
-#                           | Copyright (C) 2011-2017 OpenFOAM Foundation
-#------------------------------------------------------------------------------
-# 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 <http://www.gnu.org/licenses/>.
-#
-# Script
-#     foamGraphResUVWP
-#
-# Description
-#     Deprecated script extract initial velocity and pressure residuals for each
-#     time-step from a log file for graphing.
-#
-#     Superseded by the more general foamLog script.
-#------------------------------------------------------------------------------
-Script=${0##*/}
-
-if [ ! -f "$1" ]; then
-    echo "$Script: $1 is not a valid filename"
-    exit 1
-fi
-
-scan()
-{
-    tmpFile=new$1$$.dat
-    cat $2 | \
-        grep "Solving for $1" | \
-        grep -v "solution singularity" | \
-        sed s/,//g | \
-        awk 'BEGIN { NENTRIES = 0 }{NENTRIES++; printf("%d %e\n", NENTRIES, $8)}' - > $tmpFile
-
-    if [ "$(cat $tmpFile | wc -l)" -gt 1 ]; then
-        echo >> residualUVWP.dat
-        cat $tmpFile >> residualUVWP.dat
-    fi
-
-    rm $tmpFile
-}
-
-rm -f residualUVWP.dat
-scan "Ux" $1
-scan "Uy" $1
-scan "Uz" $1
-scan "p" $1
-
-#------------------------------------------------------------------------------
diff --git a/bin/deprecated/patchAverage b/bin/deprecated/patchAverage
deleted file mode 100755
index 26b14907bc77b8558f19b117dcb7653c6964d5af..0000000000000000000000000000000000000000
--- a/bin/deprecated/patchAverage
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/bin/sh
-#------------------------------------------------------------------------------
-# =========                 |
-# \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
-#  \\    /   O peration     |
-#   \\  /    A nd           |
-#    \\/     M anipulation  |
-#-------------------------------------------------------------------------------
-#                           | Copyright (C) 2016 OpenFOAM Foundation
-#------------------------------------------------------------------------------
-# 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 <http://www.gnu.org/licenses/>.
-#
-# Script
-#     patchAverage
-#
-# Description
-#     Script to suggest using the new "postProcess" utility.
-#
-#------------------------------------------------------------------------------
-Script=${0##*/}
-
-echo $Script "has been superceded by the postProcess utility:"
-echo "    postProcess -func '"$Script"(name=inlet,p)'"
-
-#------------------------------------------------------------------------------
diff --git a/bin/deprecated/patchIntegrate b/bin/deprecated/patchIntegrate
deleted file mode 100755
index 11d906793042f79d7acf50237cfd99a20992b77a..0000000000000000000000000000000000000000
--- a/bin/deprecated/patchIntegrate
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/bin/sh
-#------------------------------------------------------------------------------
-# =========                 |
-# \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
-#  \\    /   O peration     |
-#   \\  /    A nd           |
-#    \\/     M anipulation  |
-#-------------------------------------------------------------------------------
-#                           | Copyright (C) 2016 OpenFOAM Foundation
-#------------------------------------------------------------------------------
-# 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 <http://www.gnu.org/licenses/>.
-#
-# Script
-#     patchIntegrate
-#
-# Description
-#     Script to suggest using the new "postProcess" utility.
-#
-#------------------------------------------------------------------------------
-Script=${0##*/}
-
-echo $Script "has been superceded by the postProcess utility:"
-echo "    postProcess -func '"$Script"(name=inlet,p)'"
-
-#------------------------------------------------------------------------------
diff --git a/bin/deprecated/probeLocations b/bin/deprecated/probeLocations
deleted file mode 100755
index cec259f6add8a792554603588ee3104153df1bf0..0000000000000000000000000000000000000000
--- a/bin/deprecated/probeLocations
+++ /dev/null
@@ -1,41 +0,0 @@
-#!/bin/sh
-#------------------------------------------------------------------------------
-# =========                 |
-# \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
-#  \\    /   O peration     |
-#   \\  /    A nd           |
-#    \\/     M anipulation  |
-#-------------------------------------------------------------------------------
-#                           | Copyright (C) 2016 OpenFOAM Foundation
-#------------------------------------------------------------------------------
-# 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 <http://www.gnu.org/licenses/>.
-#
-# Script
-#     probeLocations
-#
-# Description
-#     Script to suggest using the new "postProcess" utility.
-#
-#------------------------------------------------------------------------------
-Script=${0##*/}
-
-echo $Script "has been superceded by the postProcess utility:"
-echo "    postProcess -func probes"
-echo "or"
-echo "    postProcess -func 'probes(p, U)'"
-
-#------------------------------------------------------------------------------
diff --git a/bin/deprecated/ptot b/bin/deprecated/ptot
deleted file mode 100755
index 0ae6ed9dae7b4add0da5ca2b4cbb9a4aff0bc01a..0000000000000000000000000000000000000000
--- a/bin/deprecated/ptot
+++ /dev/null
@@ -1,41 +0,0 @@
-#!/bin/sh
-#------------------------------------------------------------------------------
-# =========                 |
-# \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
-#  \\    /   O peration     |
-#   \\  /    A nd           |
-#    \\/     M anipulation  |
-#-------------------------------------------------------------------------------
-#                           | Copyright (C) 2016 OpenFOAM Foundation
-#------------------------------------------------------------------------------
-# 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 <http://www.gnu.org/licenses/>.
-#
-# Script
-#     ptot
-#
-# Description
-#     Script to suggest using the new "postProcess" utility.
-#
-#------------------------------------------------------------------------------
-Script=${0##*/}
-
-echo $Script "has been superceded by the postProcess utility:"
-echo "    postProcess -func 'totalPressureIncompressible(U,p)'"
-echo "or"
-echo "    postProcess -func 'totalPressureCompressible(rho,U,p)'"
-
-#------------------------------------------------------------------------------
diff --git a/bin/deprecated/sample b/bin/deprecated/sample
deleted file mode 100755
index f3d82e472a92a1baa04f891da65106041dc0601b..0000000000000000000000000000000000000000
--- a/bin/deprecated/sample
+++ /dev/null
@@ -1,45 +0,0 @@
-#!/bin/sh
-#------------------------------------------------------------------------------
-# =========                 |
-# \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
-#  \\    /   O peration     |
-#   \\  /    A nd           |
-#    \\/     M anipulation  |
-#-------------------------------------------------------------------------------
-#                           | Copyright (C) 2016 OpenFOAM Foundation
-#------------------------------------------------------------------------------
-# 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 <http://www.gnu.org/licenses/>.
-#
-# Script
-#     probeLocations
-#
-# Description
-#     Script to suggest using the new "postProcess" utility.
-#
-#------------------------------------------------------------------------------
-Script=${0##*/}
-
-echo $Script "has been superceded by the postProcess utility:"
-echo "    postProcess -func $Script"
-echo
-echo "To re-use existing 'sampleDict' files simply add the following entries:"
-echo "    type sets;"
-echo "    libs (\"libsampling.so\");"
-echo "and run"
-echo "    postProcess -func sampleDict"
-
-#------------------------------------------------------------------------------
diff --git a/bin/deprecated/streamFunction b/bin/deprecated/streamFunction
deleted file mode 120000
index 7b00da8e40ebd1030970ddd69f73d5a820da0dee..0000000000000000000000000000000000000000
--- a/bin/deprecated/streamFunction
+++ /dev/null
@@ -1 +0,0 @@
-supercededByPostProcess
\ No newline at end of file
diff --git a/bin/deprecated/stressComponents b/bin/deprecated/stressComponents
deleted file mode 100755
index 208463c41b31bbb43f76395b2bba6d241758771f..0000000000000000000000000000000000000000
--- a/bin/deprecated/stressComponents
+++ /dev/null
@@ -1,41 +0,0 @@
-#!/bin/sh
-#------------------------------------------------------------------------------
-# =========                 |
-# \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
-#  \\    /   O peration     |
-#   \\  /    A nd           |
-#    \\/     M anipulation  |
-#-------------------------------------------------------------------------------
-#                           | Copyright (C) 2016-2017 OpenFOAM Foundation
-#------------------------------------------------------------------------------
-# 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 <http://www.gnu.org/licenses/>.
-#
-# Script
-#     stressComponents
-#
-# Description
-#     Script to suggest using the new "-postProcess" solver option.
-#
-#------------------------------------------------------------------------------
-Script=${0##*/}
-
-echo $Script "has been superseded by the -postProcess solver option:"
-echo "<solverName> -funcs '(R components(turbulenceProperties:R))'"
-echo "e.g."
-echo "simpleFoam -postProcess -funcs '(R components(turbulenceProperties:R))'"
-
-#------------------------------------------------------------------------------
diff --git a/bin/deprecated/supercededByPostProcess b/bin/deprecated/supercededByPostProcess
deleted file mode 100755
index 2dfcb7c23449f82c11796851b91c01093fe9ae40..0000000000000000000000000000000000000000
--- a/bin/deprecated/supercededByPostProcess
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/bin/sh
-#------------------------------------------------------------------------------
-# =========                 |
-# \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
-#  \\    /   O peration     |
-#   \\  /    A nd           |
-#    \\/     M anipulation  |
-#-------------------------------------------------------------------------------
-#                           | Copyright (C) 2016 OpenFOAM Foundation
-#------------------------------------------------------------------------------
-# 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 <http://www.gnu.org/licenses/>.
-#
-# Script
-#     supercededByPostProcess
-#
-# Description
-#     Script to suggest using the new "postProcess" utility.
-#
-#------------------------------------------------------------------------------
-Script=${0##*/}
-
-echo $Script "has been superceded by the postProcess utility:"
-echo "    postProcess -func" $Script
-
-#------------------------------------------------------------------------------
diff --git a/bin/deprecated/supercededByPostProcessOption b/bin/deprecated/supercededByPostProcessOption
deleted file mode 100755
index 273d325f174efd299aa15d499f68d80fcd6ae3d5..0000000000000000000000000000000000000000
--- a/bin/deprecated/supercededByPostProcessOption
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/bin/sh
-#------------------------------------------------------------------------------
-# =========                 |
-# \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
-#  \\    /   O peration     |
-#   \\  /    A nd           |
-#    \\/     M anipulation  |
-#-------------------------------------------------------------------------------
-#                           | Copyright (C) 2016 OpenFOAM Foundation
-#------------------------------------------------------------------------------
-# 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 <http://www.gnu.org/licenses/>.
-#
-# Script
-#     supercededByPostProcessOption
-#
-# Description
-#     Replacement script to suggest using the new "-postProcess"
-#     solver command-line option.
-#
-#------------------------------------------------------------------------------
-Script=${0##*/}
-
-echo $Script "has been superceded by the \
-'-postProcess' solver command-line option, e.g."
-
-echo "simpleFoam -postProcess -func" $Script
-
-#------------------------------------------------------------------------------
diff --git a/bin/deprecated/vorticity b/bin/deprecated/vorticity
deleted file mode 120000
index 7b00da8e40ebd1030970ddd69f73d5a820da0dee..0000000000000000000000000000000000000000
--- a/bin/deprecated/vorticity
+++ /dev/null
@@ -1 +0,0 @@
-supercededByPostProcess
\ No newline at end of file
diff --git a/bin/deprecated/wallGradU b/bin/deprecated/wallGradU
deleted file mode 100755
index 92ae5b809c31ec0794e5274da4595138a3c9216e..0000000000000000000000000000000000000000
--- a/bin/deprecated/wallGradU
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/bin/sh
-#------------------------------------------------------------------------------
-# =========                 |
-# \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
-#  \\    /   O peration     |
-#   \\  /    A nd           |
-#    \\/     M anipulation  |
-#-------------------------------------------------------------------------------
-#                           | Copyright (C) 2017 OpenFOAM Foundation
-#------------------------------------------------------------------------------
-# 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 <http://www.gnu.org/licenses/>.
-#
-# Script
-#     wallGradU
-#
-# Description
-#     Script to suggest using the new "postProcess" utility.
-#
-#------------------------------------------------------------------------------
-Script=${0##*/}
-
-echo $Script "has been superseded by the postProcess utility:"
-echo "    postProcess -func 'grad(U)'"
-
-#------------------------------------------------------------------------------
diff --git a/bin/deprecated/wallHeatFlux b/bin/deprecated/wallHeatFlux
deleted file mode 120000
index ff6b4704c676ee88d208606b8f93dbb37e4fe62e..0000000000000000000000000000000000000000
--- a/bin/deprecated/wallHeatFlux
+++ /dev/null
@@ -1 +0,0 @@
-supercededByPostProcessOption
\ No newline at end of file
diff --git a/bin/deprecated/wallShearStress b/bin/deprecated/wallShearStress
deleted file mode 120000
index ff6b4704c676ee88d208606b8f93dbb37e4fe62e..0000000000000000000000000000000000000000
--- a/bin/deprecated/wallShearStress
+++ /dev/null
@@ -1 +0,0 @@
-supercededByPostProcessOption
\ No newline at end of file
diff --git a/bin/deprecated/wdot b/bin/deprecated/wdot
deleted file mode 100755
index 9f4d43d71bcb19eee1c43b36461d423740ac9175..0000000000000000000000000000000000000000
--- a/bin/deprecated/wdot
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/bin/sh
-#------------------------------------------------------------------------------
-# =========                 |
-# \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
-#  \\    /   O peration     |
-#   \\  /    A nd           |
-#    \\/     M anipulation  |
-#-------------------------------------------------------------------------------
-#                           | Copyright (C) 2017 OpenFOAM Foundation
-#------------------------------------------------------------------------------
-# 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 <http://www.gnu.org/licenses/>.
-#
-# Script
-#     wdot
-#
-# Description
-#     Script to suggest using the new "postProcess" utility.
-#
-#------------------------------------------------------------------------------
-Script=${0##*/}
-
-echo $Script "has been superseded by the postProcess utility:"
-echo "postProcess -func XiReactionRate"
-
-#------------------------------------------------------------------------------
diff --git a/bin/deprecated/writeCellCentres b/bin/deprecated/writeCellCentres
deleted file mode 120000
index 7b00da8e40ebd1030970ddd69f73d5a820da0dee..0000000000000000000000000000000000000000
--- a/bin/deprecated/writeCellCentres
+++ /dev/null
@@ -1 +0,0 @@
-supercededByPostProcess
\ No newline at end of file
diff --git a/bin/deprecated/yPlus b/bin/deprecated/yPlus
deleted file mode 120000
index ff6b4704c676ee88d208606b8f93dbb37e4fe62e..0000000000000000000000000000000000000000
--- a/bin/deprecated/yPlus
+++ /dev/null
@@ -1 +0,0 @@
-supercededByPostProcessOption
\ No newline at end of file
diff --git a/bin/enstrophy b/bin/enstrophy
deleted file mode 120000
index 3c4b1df251b8ae002c939e3c8e6be15b15624bcf..0000000000000000000000000000000000000000
--- a/bin/enstrophy
+++ /dev/null
@@ -1 +0,0 @@
-deprecated/enstrophy
\ No newline at end of file
diff --git a/bin/execFlowFunctionObjects b/bin/execFlowFunctionObjects
deleted file mode 120000
index ff820179432372c1a4f1b6bab9bbf888211387c6..0000000000000000000000000000000000000000
--- a/bin/execFlowFunctionObjects
+++ /dev/null
@@ -1 +0,0 @@
-deprecated/execFlowFunctionObjects
\ No newline at end of file
diff --git a/bin/flowType b/bin/flowType
deleted file mode 120000
index cf8bfb7d33cbe5c6c0f6dae60f3547b5ff9c8df6..0000000000000000000000000000000000000000
--- a/bin/flowType
+++ /dev/null
@@ -1 +0,0 @@
-deprecated/flowType
\ No newline at end of file
diff --git a/bin/foamCalc b/bin/foamCalc
deleted file mode 120000
index 40110e155c0a219be33dbeab36729414b5d6bbac..0000000000000000000000000000000000000000
--- a/bin/foamCalc
+++ /dev/null
@@ -1 +0,0 @@
-deprecated/foamCalc
\ No newline at end of file
diff --git a/bin/foamGetDict b/bin/foamGetDict
index 35ded94201d883fe0bc3dc0cffdb9ebc5d901126..846cf62ec5f9bc7e1481e42a0840b8b9c72ca5c9 100755
--- a/bin/foamGetDict
+++ b/bin/foamGetDict
@@ -45,6 +45,7 @@ options:
   -case <dir>       Alternative case directory, default is the cwd
   -ext  <ext>       File extension
   -cfg              Same as '-e cfg' for '.cfg' files
+  -f | -force       Force overwrite of existing files
   -no-ext           Files without extension
   -target <dir>     Target directory (default: system, or auto-detected)
   -with-api=NUM     Alternative api value for searching
@@ -86,7 +87,7 @@ projectApi="$FOAM_API"
 #-------------------------------------------------------------------------------
 
 searchExt="<any>"
-unset targetDir
+unset targetDir optForce
 
 while [ "$#" -gt 0 ]
 do
@@ -113,6 +114,9 @@ do
     -cfg)
         searchExt="cfg"
         ;;
+    -f | -force)
+        optForce=true
+        ;;
     -target)
         [ "$#" -ge 2 ] || die "'$1' option requires an argument"
         targetDir="$2"
@@ -221,12 +225,27 @@ findFiles()
 }
 
 
-# Slightly dressed up version of 'cp -v'
+# Slightly dressed up version of 'cp -v' that does not clobber existing files
 copyFile()
 {
+    local targetFile="$2"
+
+    [ -d "$2" ] && targetFile="$targetFile/${1##*/}"
+
     echo 1>&2
-    echo "Copying $1 to $2" 1>&2
-    \cp "$1" "$2"
+    if [ -f "$targetFile" ]
+    then
+        if [ "$optForce" = true ]
+        then
+            echo "Overwrite $1 to $2" 1>&2
+            \cp "$1" "$2"
+        else
+            echo "Skip copy $1 to $2" 1>&2
+        fi
+    else
+        echo "Copying $1 to $2" 1>&2
+        \cp "$1" "$2"
+    fi
     echo 1>&2
 }
 
diff --git a/bin/foamGraphExecTime b/bin/foamGraphExecTime
deleted file mode 120000
index f6fb34291e3add055762aa55040d0dd9399e629b..0000000000000000000000000000000000000000
--- a/bin/foamGraphExecTime
+++ /dev/null
@@ -1 +0,0 @@
-deprecated/foamGraphExecTime
\ No newline at end of file
diff --git a/bin/foamGraphResKE b/bin/foamGraphResKE
deleted file mode 120000
index 6f00aa885bdb31c8eea867fda622b4a22153635a..0000000000000000000000000000000000000000
--- a/bin/foamGraphResKE
+++ /dev/null
@@ -1 +0,0 @@
-deprecated/foamGraphResKE
\ No newline at end of file
diff --git a/bin/foamGraphResUVWP b/bin/foamGraphResUVWP
deleted file mode 120000
index 0414911d86e7853708469898aef5fab34650b480..0000000000000000000000000000000000000000
--- a/bin/foamGraphResUVWP
+++ /dev/null
@@ -1 +0,0 @@
-deprecated/foamGraphResUVWP
\ No newline at end of file
diff --git a/bin/patchAverage b/bin/patchAverage
deleted file mode 120000
index 56f120034e1e8cad025936f2162256c854a8dd27..0000000000000000000000000000000000000000
--- a/bin/patchAverage
+++ /dev/null
@@ -1 +0,0 @@
-deprecated/patchAverage
\ No newline at end of file
diff --git a/bin/patchIntegrate b/bin/patchIntegrate
deleted file mode 120000
index 86bf0e1807d6885fad98707fd9f57a6eba668df7..0000000000000000000000000000000000000000
--- a/bin/patchIntegrate
+++ /dev/null
@@ -1 +0,0 @@
-deprecated/patchIntegrate
\ No newline at end of file
diff --git a/bin/probeLocations b/bin/probeLocations
deleted file mode 120000
index b0ae936d8c919784bdd39ad18d951275085167fe..0000000000000000000000000000000000000000
--- a/bin/probeLocations
+++ /dev/null
@@ -1 +0,0 @@
-deprecated/probeLocations
\ No newline at end of file
diff --git a/bin/ptot b/bin/ptot
deleted file mode 120000
index 8d3449ff63d2674aa81dae9bcd425247a2a77af4..0000000000000000000000000000000000000000
--- a/bin/ptot
+++ /dev/null
@@ -1 +0,0 @@
-deprecated/ptot
\ No newline at end of file
diff --git a/bin/sample b/bin/sample
deleted file mode 120000
index 3cf64426e386e375580b76bb58dd8786170f4751..0000000000000000000000000000000000000000
--- a/bin/sample
+++ /dev/null
@@ -1 +0,0 @@
-deprecated/sample
\ No newline at end of file
diff --git a/bin/streamFunction b/bin/streamFunction
deleted file mode 120000
index 1670122cfd0fa100ac2da52d58146de683420eb3..0000000000000000000000000000000000000000
--- a/bin/streamFunction
+++ /dev/null
@@ -1 +0,0 @@
-deprecated/streamFunction
\ No newline at end of file
diff --git a/bin/stressComponents b/bin/stressComponents
deleted file mode 120000
index 2f3bb9ee3620dbe36bc4de3042c5f5510ce9152b..0000000000000000000000000000000000000000
--- a/bin/stressComponents
+++ /dev/null
@@ -1 +0,0 @@
-deprecated/stressComponents
\ No newline at end of file
diff --git a/bin/tools/CleanFunctions b/bin/tools/CleanFunctions
index 06b6c3921a3d2d43b1ea763c0abab033b3785863..d05354592b457906ed89e1144a41e14acdc88bcd 100644
--- a/bin/tools/CleanFunctions
+++ b/bin/tools/CleanFunctions
@@ -39,7 +39,7 @@ cleanTimeDirectories()
 
 cleanDynamicCode()
 {
-    if [ -d system -a -d dynamicCode ]
+    if [ -d dynamicCode ] && [ -d system ]
     then
         rm -rf dynamicCode > /dev/null 2>&1
     fi
@@ -73,22 +73,28 @@ cleanSnappyFiles()
 }
 
 
+cleanPostProcessing()
+{
+    rm -rf Ensight EnSight ensightWrite insitu VTK > /dev/null 2>&1
+    rm -rf postProcessing > /dev/null 2>&1
+    rm -rf cuttingPlane > /dev/null 2>&1
+    rm -rf surfaceSampling > /dev/null 2>&1
+}
+
+
 cleanCase()
 {
     cleanTimeDirectories
+    cleanPostProcessing
     cleanDynamicCode
 
     rm -rf processor* > /dev/null 2>&1
-    rm -rf postProcessing > /dev/null 2>&1
     rm -rf TDAC > /dev/null 2>&1
     rm -rf probes* > /dev/null 2>&1
     rm -rf forces* > /dev/null 2>&1
     rm -rf graphs* > /dev/null 2>&1
     rm -rf sets > /dev/null 2>&1
-    rm -rf surfaceSampling > /dev/null 2>&1
-    rm -rf cuttingPlane > /dev/null 2>&1
     rm -rf system/machines > /dev/null 2>&1
-    rm -rf Ensight EnSight ensightWrite insitu VTK > /dev/null 2>&1
 
     # From mpirunDebug
     rm -f gdbCommands  mpirun.schema
@@ -149,7 +155,7 @@ removeCase()
 
 cleanSamples()
 {
-    rm -rf ./sets ./samples ./sampleSurfaces > /dev/null 2>&1
+    rm -rf sets samples sampleSurfaces > /dev/null 2>&1
 }
 
 
diff --git a/bin/tools/RunFunctions b/bin/tools/RunFunctions
index d1a4007c4752afc9f8622d11db77ae595ea7cd37..12f0265c2fb0c39b0f3c744947c054fcc6edac9a 100644
--- a/bin/tools/RunFunctions
+++ b/bin/tools/RunFunctions
@@ -241,6 +241,12 @@ runParallel()
     # Any additional parsed arguments (eg, decomposeParDict)
     local appArgs="-parallel"
 
+    local mpirun="mpirun"
+    if [ "$FOAM_MPI" = msmpi ]
+    then
+        mpirun="mpiexec"
+    fi
+
     # Parse options until executable is encountered
     while [ $# -gt 0 -a -z "$appRun" ]
     do
@@ -287,11 +293,11 @@ runParallel()
         if [ "$logMode" = append ]
         then
         (
-            mpirun -np $nProcs $appRun $appArgs "$@" </dev/null >> $logFile 2>&1
+            $mpirun -np $nProcs $appRun $appArgs "$@" </dev/null >> $logFile 2>&1
         )
         else
         (
-            mpirun -np $nProcs $appRun $appArgs "$@" </dev/null > $logFile 2>&1
+            $mpirun -np $nProcs $appRun $appArgs "$@" </dev/null > $logFile 2>&1
         )
         fi
     fi
diff --git a/bin/vorticity b/bin/vorticity
deleted file mode 120000
index 2a65ebaac6667155de7e5a9cf7fcdd568930e08c..0000000000000000000000000000000000000000
--- a/bin/vorticity
+++ /dev/null
@@ -1 +0,0 @@
-deprecated/vorticity
\ No newline at end of file
diff --git a/bin/wallGradU b/bin/wallGradU
deleted file mode 120000
index 70dbc7d577a7f50e1685f771a80a0c72c13a136e..0000000000000000000000000000000000000000
--- a/bin/wallGradU
+++ /dev/null
@@ -1 +0,0 @@
-deprecated/wallGradU
\ No newline at end of file
diff --git a/bin/wallHeatFlux b/bin/wallHeatFlux
deleted file mode 120000
index f5445f1117aaa585e7bc5a619da7251d309fa9b6..0000000000000000000000000000000000000000
--- a/bin/wallHeatFlux
+++ /dev/null
@@ -1 +0,0 @@
-deprecated/wallHeatFlux
\ No newline at end of file
diff --git a/bin/wallShearStress b/bin/wallShearStress
deleted file mode 120000
index 31456be8313e34f335a4d9892a021c07ad758752..0000000000000000000000000000000000000000
--- a/bin/wallShearStress
+++ /dev/null
@@ -1 +0,0 @@
-deprecated/wallShearStress
\ No newline at end of file
diff --git a/bin/wdot b/bin/wdot
deleted file mode 120000
index 433eb780387c0cfb2a23845e7f4726a62d21b459..0000000000000000000000000000000000000000
--- a/bin/wdot
+++ /dev/null
@@ -1 +0,0 @@
-deprecated/wdot
\ No newline at end of file
diff --git a/bin/writeCellCentres b/bin/writeCellCentres
deleted file mode 120000
index 807b2c74fd29503998f48db02c3d305f2d84e39c..0000000000000000000000000000000000000000
--- a/bin/writeCellCentres
+++ /dev/null
@@ -1 +0,0 @@
-deprecated/writeCellCentres
\ No newline at end of file
diff --git a/bin/yPlus b/bin/yPlus
deleted file mode 120000
index e002dec748cf04bfdab0163ff9e71676488d59e7..0000000000000000000000000000000000000000
--- a/bin/yPlus
+++ /dev/null
@@ -1 +0,0 @@
-deprecated/yPlus
\ No newline at end of file
diff --git a/doc/codingStyleGuide.org b/doc/codingStyleGuide.org
deleted file mode 100644
index 4df1aa03b4a9f026ad03004ae04a99ff8aa5e266..0000000000000000000000000000000000000000
--- a/doc/codingStyleGuide.org
+++ /dev/null
@@ -1,539 +0,0 @@
-#                            -*- mode: org; -*-
-#
-#+TITLE:                 OpenFOAM C++ Style Guide
-#+AUTHOR:                  OpenFOAM Foundation
-#+DATE:                         2011-2016
-#+LINK:                    http://OpenFOAM.com
-#+OPTIONS: author:nil ^:{}
-#+STARTUP: hidestars
-#+STARTUP: odd
-
-* Code
-*** General
-    + 80 character lines max
-    + The normal indentation is 4 spaces per logical level.
-    + Use spaces for indentation, not tab characters.
-    + Avoid trailing whitespace.
-    + The body of control statements (eg, =if=, =else=, =while=, /etc./). is
-      always delineated with braces.  A possible exception can be
-      made in conjunction with =break= or =continue= as part of a control
-      structure.
-    + The body of =case= statements is usually delineated with braces.
-    + Stream output
-      + =<<= is always four characters after the start of the stream,
-        so that the =<<= symbols align, i.e.
-        #+begin_src C++
-        Info<< ...
-        os  << ...
-        #+end_src
-        so
-        #+begin_src C++
-        WarningInFunction
-            << "Warning message"
-        #+end_src
-        *not*
-        #+begin_src C++
-        WarningInFunction
-        << "Warning message"
-        #+end_src
-
-    + Remove unnecessary class section headers, i.e. remove
-#+begin_src C++
-// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
-
-    // Check
-
-    // Edit
-
-    // Write
-#+end_src
-      if they contain nothing, even if planned for 'future use'
-
-    + Class titles should be centred
-#+begin_src C++
-/*---------------------------------------------------------------------------*\
-                        Class exampleClass Declaration
-\*---------------------------------------------------------------------------*/
-#+end_src
-      *not*
-#+begin_src C++
-/*---------------------------------------------------------------------------*\
-                Class exampleClass Declaration
-\*---------------------------------------------------------------------------*/
-#+end_src
-
-*** The /.H/ Header Files
-    + Header file spacing
-      + Leave two empty lines between sections
-        (as per functions in the /.C/ file /etc./)
-    + Use =//- Comment= comments in header file to add descriptions to class
-      data and functions do be included in the Doxygen documentation:
-      + Text on the line starting with =//-= becomes the Doxygen brief
-        description;
-      + Text on subsequent lines becomes the Doxygen detailed description /e.g./
-        #+begin_src C++
-        //- A function which returns a thing
-        //  This is a detailed description of the function
-        //  which processes stuff and returns other stuff
-        //  depending on things.
-        thing function(stuff1, stuff2);
-        #+end_src
-      + List entries start with =-= or =-#= for numbered lists but cannot start
-        on the line immediately below the brief description so
-        #+begin_src C++
-        //- Compare triFaces
-        //  Returns:
-        //  -  0: different
-        //  - +1: identical
-        //  - -1: same face, but different orientation
-        static int compare(const triFace&, const triFace&);
-        #+end_src
-        or
-        #+begin_src C++
-        //- Compare triFaces returning 0, +1 or -1
-        //
-        //  -  0: different
-        //  - +1: identical
-        //  - -1: same face, but different orientation
-        static int compare(const triFace&, const triFace&);
-        #+end_src
-        *not*
-        #+begin_src C++
-        //- Compare triFaces returning 0, +1 or -1
-        //  -  0: different
-        //  - +1: identical
-        //  - -1: same face, but different orientation
-        static int compare(const triFace&, const triFace&);
-        #+end_src
-      + List can be nested for example
-        #+begin_src C++
-        //- Search for \em name
-        //  in the following hierarchy:
-        //  -# user settings
-        //    - ~/.OpenFOAM/\<VERSION\>/
-        //      <em>for version-specific files</em>
-        //    - ~/.OpenFOAM/
-        //      <em>for version-independent files</em>
-        //  -# group settings
-        //    - $WM_PROJECT_DIR/site/\<VERSION\>
-        //      <em>for version-specific files</em>
-        //    - $WM_PROJECT_DIR/site/
-        //      <em>for version-independent files</em>
-        //  -# other (shipped) settings
-        //    - $WM_PROJECT_DIR/etc/
-        //
-        //  \return the full path name or fileName() if the name cannot be found
-        //  Optionally abort if the file cannot be found
-        fileName findEtcFile(const fileName&, bool mandatory=false);
-        #+end_src
-      + For more details see the Doxygen documentation.
-    + Destructor
-      + When adding a comment to the destructor use =//-= and code as a normal
-        function:
-        #+begin_src C++
-        //- Destructor
-        ~className();
-        #+end_src
-    + Inline functions
-      + Use inline functions where appropriate in a separate /classNameI.H/
-        file.  Avoid cluttering the header file with function bodies.
-
-*** The /.C/ Source Files
-    + Do not open/close namespaces in a /.C/ file
-      + Fully scope the function name, i.e.
-        #+begin_src C++
-        Foam::returnType Foam::className::functionName()
-        #+end_src
-        *not*
-        #+begin_src C++
-        namespace Foam
-        {
-            ...
-            returnType className::functionName()
-            ...
-        }
-        #+end_src
-        *Exception*
-        When there are multiple levels of namespace, they may be used in the
-        /.C/ file to avoid excessive clutter, i.e.
-        #+begin_src C++
-        namespace Foam
-        {
-        namespace compressible
-        {
-        namespace RASModels
-        {
-            ...
-        } // End namespace RASModels
-        } // End namespace compressible
-        } // End namespace Foam
-        #+end_src
-
-    + Use two empty lines between functions
-
-*** Coding Practice
-    + Passing data as arguments or return values:
-      + Pass bool, label, scalar and other primitive types as copy,
-        anything larger by reference.
-    + =const=
-      + Use everywhere it is applicable.
-    + Variable initialisation using
-      #+begin_src C++
-      const className& variableName = otherClass.data();
-      #+end_src
-      *not*
-      #+begin_src C++
-      const className& variableName(otherClass.data());
-      #+end_src
-    + Virtual functions
-      + If a class is virtual, make all derived classes virtual.
-
-*** Conditional Statements
-    #+begin_src C++
-    if (condition)
-    {
-        code;
-    }
-    #+end_src
-    OR
-    #+begin_src C++
-    if
-    (
-       long condition
-    )
-    {
-        code;
-    }
-    #+end_src
-    *not* (no space between =if= and =(= used)
-    #+begin_src C++
-    if(condition)
-    {
-        code;
-    }
-    #+end_src
-
-*** =for= and =while= Loops
-    #+begin_src C++
-    for (i = 0; i < maxI; ++i)
-    {
-        code;
-    }
-    #+end_src
-    OR
-    #+begin_src C++
-    for
-    (
-        i = 0;
-        i < maxI;
-        ++i
-    )
-    {
-        code;
-    }
-    #+end_src
-    *not* this (no space between =for= and =(= used)
-    #+begin_src C++
-    for(i = 0; i < maxI; ++i)
-    {
-        code;
-    }
-    #+end_src
-    Range-base for should have a space surrounding the ':'
-    #+begin_src C++
-    for (auto i : range)
-    {
-        code;
-    }
-    #+end_src
-    Note that when indexing through iterators, it is often more efficient
-    to use the pre-increment form. Eg, =++iter= instead of =iter++=
-
-*** =forAll=, =forAllIters=, =forAllConstIters=, /etc./ loops
-    Like =for= loops, but
-    #+begin_src C++
-    forAll(
-    #+end_src
-    *not*
-    #+begin_src C++
-    forAll (
-    #+end_src
-    In many cases, the new =forAllIters= and =forAllConstIters= macros
-    provide a good means of cycling through iterators (when a range-base
-    for doesn't apply). These use the C++11 decltype and work without
-    explicitly specifying the container class:
-    #+begin_src C++
-    forAllIters(myEdgeHash, iter)
-    #+end_src
-    Using the older =forAllIter= and =forAllConstIter= macros will
-    still be seen.  However, since they are macros, they will fail if
-    the iterated object contains any commas /e.g./ following will FAIL!:
-    #+begin_src C++
-    forAllIter(HashTable<labelPair, edge, Hash<edge>>, myEdgeHash, iter)
-    #+end_src
-    These convenience macros are also generally avoided in other
-    container classes and OpenFOAM primitive classes.
-    In certain cases, the range-based for can also be used.
-
-*** Splitting Over Multiple Lines
-***** Splitting return type and function name
-      + Split initially after the function return type and left align
-      + Do not put =const= onto its own line - use a split to keep it with
-        the function name and arguments.
-        #+begin_src C++
-        const Foam::longReturnTypeName&
-        Foam::longClassName::longFunctionName const
-        #+end_src
-        *not*
-        #+begin_src C++
-        const Foam::longReturnTypeName&
-            Foam::longClassName::longFunctionName const
-        #+end_src
-        *nor*
-        #+begin_src C++
-        const Foam::longReturnTypeName& Foam::longClassName::longFunctionName
-        const
-        #+end_src
-        *nor*
-        #+begin_src C++
-        const Foam::longReturnTypeName& Foam::longClassName::
-        longFunctionName const
-        #+end_src
-      + If it needs to be split again, split at the function name (leaving
-        behind the preceding scoping =::=s), and again, left align, i.e.
-        #+begin_src C++
-        const Foam::longReturnTypeName&
-        Foam::veryveryveryverylongClassName::
-        veryveryveryverylongFunctionName const
-        #+end_src
-
-***** Splitting long lines at an "="
-     Indent after split
-     #+begin_src C++
-     variableName =
-         longClassName.longFunctionName(longArgument);
-     #+end_src
-     OR (where necessary)
-     #+begin_src C++
-     variableName =
-         longClassName.longFunctionName
-         (
-             longArgument1,
-             longArgument2
-         );
-     #+end_src
-     *not*
-     #+begin_src C++
-     variableName =
-     longClassName.longFunctionName(longArgument);
-     #+end_src
-     *nor*
-     #+begin_src C++
-     variableName = longClassName.longFunctionName
-     (
-         longArgument1,
-         longArgument2
-     );
-     #+end_src
-
-*** Maths and Logic
-    + Operator spacing
-      #+begin_src C++
-      a + b, a - b
-      a*b, a/b
-      a & b, a ^ b
-      a = b, a != b
-      a < b, a > b, a >= b, a <= b
-      a || b, a && b
-      #+end_src
-
-    + Splitting formulae over several lines:
-      Split and indent as per "splitting long lines at an ="
-      with the operator on the lower line.  Align operator so that first
-      variable, function or bracket on the next line is 4 spaces indented i.e.
-      #+begin_src C++
-      variableName =
-          a*(a + b)
-         *exp(c/d)
-         *(k + t);
-      #+end_src
-      This is sometimes more legible when surrounded by extra parentheses:
-      #+begin_src C++
-      variableName =
-      (
-          a*(a + b)
-         *exp(c/d)
-         *(k + t)
-      );
-      #+end_src
-
-    + Splitting logical tests over several lines:
-      outdent the operator so that the next variable to test is aligned with
-      the four space indentation, i.e.
-      #+begin_src C++
-      if
-      (
-          a == true
-       && b == c
-      )
-      #+end_src
-
-* Documentation
-*** General
-    + For readability in the comment blocks, certain tags are used that are
-      translated by pre-filtering the file before sending it to Doxygen.
-    + The tags start in column 1, the contents follow on the next lines and
-      indented by 4 spaces. The filter removes the leading 4 spaces from the
-      following lines until the next tag that starts in column 1.
-    + The 'Class' and 'Description' tags are the most important ones.
-    + The first paragraph following the 'Description' will be used for the
-      brief description, the remaining paragraphs become the detailed
-      description.  For example,
-      #+begin_example C++
-      Class
-          Foam::myClass
-
-      Description
-          A class for specifying the documentation style.
-
-          The class is implemented as a set of recommendations that may
-          sometimes be useful.
-      #+end_example
-
-    + The class name must be qualified by its namespace, otherwise Doxygen
-      will think you are documenting some other class.
-    + If you don't have anything to say about the class (at the moment), use
-      the namespace-qualified class name for the description. This aids with
-      finding these under-documented classes later.
-      #+begin_example C++
-      Class
-          Foam::myUnderDocumentedClass
-
-      Description
-          Foam::myUnderDocumentedClass
-      #+end_example
-    + Use 'Class' and 'Namespace' tags in the header files.
-      The Description block then applies to documenting the class.
-    + Use 'InClass' and 'InNamespace' in the source files.
-      The Description block then applies to documenting the file itself.
-      #+begin_example C++
-      InClass
-          Foam::myClass
-
-      Description
-          Implements the read and writing of files.
-      #+end_example
-
-*** Doxygen Special Commands
-    Doxygen has a large number of special commands with a =\= prefix.
-
-    Since the filtering removes the leading spaces within the blocks, the
-    Doxygen commands can be inserted within the block without problems.
-    #+begin_example C++
-    InClass
-        Foam::myClass
-
-    Description
-        Implements the read and writing of files.
-
-        An example input file:
-        \verbatim
-            patchName
-            {
-                type        patchType;
-                refValue    100;
-                value       uniform 1;
-            }
-        \endverbatim
-
-        Within the implementation, a loop over all patches is done:
-        \code
-            forAll(patches, patchi)
-            {
-                ...  // some operation
-            }
-        \endcode
-    #+end_example
-
-*** HTML Special Commands
-    Since Doxygen also handles HTML tags to a certain extent, the angle
-    brackets need quoting in the documentation blocks. Non-HTML tags cause
-    Doxygen to complain, but seem to work anyhow.  /e.g./,
-    + The template with type =<HR>= is a bad example.
-    + The template with type =\<HR\>= is a better example.
-    + The template with type =<Type>= causes Doxygen to complain about an
-      unknown html type, but it seems to work okay anyhow.
-
-*** Documenting Namespaces
-    + If namespaces are explicitly declared with the =Namespace()= macro,
-      they should be documented there.
-    + If the namespaces is used to hold sub-models, the namespace can be
-      documented in the same file as the class with the model selector.
-      /e.g./,
-      #+begin_example C++
-      documented namespace 'Foam::functionEntries' within the
-      class 'Foam::functionEntry'
-      #+end_example
-    + If nothing else helps, find some sensible header.
-      /e.g./,
-      #+begin_example C++
-      namespace 'Foam' is documented in the foamVersion.H file
-      #+end_example
-
-*** Documenting Applications
-    Any number of classes might be defined by a particular application, but
-    these classes will not, however, be available to other parts of
-    OpenFOAM. At the moment, the sole purpose for running Doxygen on the
-    applications is to extract program usage information for the '-doc'
-    option.
-
-    The documentation for a particular application is normally contained
-    within the first comment block in a /.C/ source file. The solution is this
-    to invoke a special filter for the "/applications/{solver,utilities}/"
-    directories that only allows the initial comment block for the /.C/ files
-    through.
-
-    The layout of the application documentation has not yet been finalized,
-    but foamToVTK shows an initial attempt.
-
-*** Orthography
-    Given the origins of OpenFOAM, the British spellings (/e.g./, neighbour and
-    not neighbor) are generally favoured.
-
-    Both '-ize' and the '-ise' variant are found in the code comments. If
-    used as a variable or class method name, it is probably better to use
-    '-ize', which is considered the main form by the Oxford University
-    Press. /e.g./,
-    #+begin_src C++
-    myClass.initialize()
-    #+end_src
-*** References
-    References provided in the =Description= section of the class header files
-    should be formatted in the [[http://www.apastyle.org][APA (American
-    Psychological Association)]] style /e.g./ from =kEpsilon.H=
-    #+begin_example
-Description
-    Standard k-epsilon turbulence model for incompressible and compressible
-    flows including rapid distortion theory (RDT) based compression term.
-
-    Reference:
-    \verbatim
-        Standard model:
-            Launder, B. E., & Spalding, D. B. (1972).
-            Lectures in mathematical models of turbulence.
-
-            Launder, B. E., & Spalding, D. B. (1974).
-            The numerical computation of turbulent flows.
-            Computer methods in applied mechanics and engineering,
-            3(2), 269-289.
-
-        For the RDT-based compression term:
-            El Tahry, S. H. (1983).
-            k-epsilon equation for compressible reciprocating engine flows.
-            Journal of Energy, 7(4), 345-353.
-    \endverbatim
-    #+end_example
-    The APA style is a commonly used standard and references are available in
-    this format from many sources including
-    [[http://www.citationmachine.net/apa/cite-a-book][Citation Machine]] and
-    [[http://scholar.google.com][Google Scholar]].
diff --git a/doc/cross-compile-mingw.md b/doc/cross-compile-mingw.md
deleted file mode 100644
index 4c78d198e559202a351202b5e85c2520f625f12b..0000000000000000000000000000000000000000
--- a/doc/cross-compile-mingw.md
+++ /dev/null
@@ -1,126 +0,0 @@
-# Notes for cross-compiling with mingw
-
-## Host setup
-
-On openSUSE use the packages for compilation:
-```
-mingw64-cross-binutils
-mingw64-cross-cpp
-mingw64-cross-gcc
-mingw64-cross-gcc-c++
-mingw64-filesystem
-mingw64-headers
-mingw64-runtime
-
-mingw64-libwinpthread1
-mingw64-winpthreads-devel
-
-mingw64-libfftw3
-mingw64-fftw3-devel
-```
-This setup is missing `zlib`, so download that manually and compile as a
-*static* library.
-```
-CC="$(wmake -show-c)" CFLAGS="$(wmake -show-cflags)" ./configure --static
-make
-```
-
-The resulting output files (zconf.h zlib.h) and (libz.a) either need
-to be installed in system locations where OpenFOAM can find them, or if
-they are to be shipped directly with OpenFOAM, they can also be placed
-in the `src/OpenFOAM/include` and `platforms/XXX/lib` paths.
-
-If the header files are only needed during compilation, it can be a
-fairly convenient hack to simply place copies of them in the
-`src/OSspecific/MSwindows` directory.
-
-Flex is used in a few locations within OpenFOAM for generating code.
-The generated C++ code requires the `FlexLexer.h` header file, but
-its `/usr/include` location will be ignored by the cross-compiler.
-
-As another ugly hack, a copy of this file can be made in a standard
-project include location. For example,
-```
-ln -s /usr/include/FlexLexer.h src/OSspecific/MSwindows
-```
-
-The last point to consider when cross-compiling is the behaviour of
-the OpenFOAM tools used during compilation. These are found under
-`wmake/src`. When these are compiled they will create executables that
-work on the target platform (Windows), but *not* on the host platform.
-
-The workaround:
-
-1. Activate the native OpenFOAM environment (Linux with system gcc)
-and use that to compile the build tools
-```
-wmake/src/Allmake
-```
-This can be skipped if you already have an existing OpenFOAM build.
-
-2. Activate the OpenFOAM for cross-compiling (Linux with mingw)
-and use that to compile the build tools
-```
-wmake/src/Allmake
-```
-
-3. Copy the contents of the native platform build tools into the
-cross-compilation platform directory. For example,
-```
-cp wmake/platforms/linux64Gcc/* wmake/platforms/linux64Mingw/
-```
-
-The `wmake/platforms/linux64Mingw/` directory should now contain
-native and cross-compiled tools:
-```
-dirToString     dirToString.exe
-wmkdep          wmkdep.exe
-wmkdepend       wmkdepend.exe
-```
-
-The native tools are the one that will (automatically) be used
-throughout the balance of the cross-compilation process.
-
-The settings for cross-compilation are normally defined in the
-`etc/pref.sh` file with contents like this:
-```
-# For mingw cross-compile
-
-export WM_COMPILER=Mingw
-export WM_MPLIB=MSMPI
-
-export WM_LABEL_SIZE=32
-# other settings...
-```
-
-Additional adjustments may be required in some other places. For example
-in `etc/config.sh/FFTW`
-```
-fftw_version=fftw-system
-export FFTW_ARCH_PATH=/usr/x86_64-w64-mingw32/sys-root/mingw
-```
-
-
-## Run-time setup
-
-When using the cross-compiled executables and libraries, the
-corresponding runtime libraries will be required.
-These will need to be copied across from the Linux host system to the
-target machine.
-On openSUSE these runtime libraries are provided by the packages:
-```
-mingw64-libgcc_s_seh1
-mingw64-libstdc++6
-```
-
-When running, the `WM_PROJECT_DIR` environment must be set.
-OpenFOAM will otherwise not be able to locate its files.
-
-
-## Known limitations (2019-05-01)
-
-- kahip does not build
-- boost should build ok, but no CGAL support (ie, no foamyHexMesh)
-- no ParaView plugin, runTimePostProcessing
-- reacting EulerFoam solvers have too many interdependencies and do
-  not yet compile cleanly.
diff --git a/etc/bashrc b/etc/bashrc
index e0e3039ae3f20bbc98932afcf8c1cfb4b4f6ecab..f4268e1ff72f1f3dba1343e542dffb71c1f37f21 100644
--- a/etc/bashrc
+++ b/etc/bashrc
@@ -81,7 +81,7 @@ export WM_COMPILER=Gcc
 export WM_ARCH_OPTION=64
 
 # [WM_PRECISION_OPTION] - Floating-point precision:
-# = DP | SP
+# = DP | SP | SPDP
 export WM_PRECISION_OPTION=DP
 
 # [WM_LABEL_SIZE] - Label size in bits:
diff --git a/etc/caseDicts/annotated/runTimePostProcessingDict b/etc/caseDicts/annotated/runTimePostProcessingDict
index cbe82ec81f0a0b74bdf9bb3f4cc0fca3433b7020..92f4b2112f03e143887464c4bc8b0b58831d9385 100644
--- a/etc/caseDicts/annotated/runTimePostProcessingDict
+++ b/etc/caseDicts/annotated/runTimePostProcessingDict
@@ -19,15 +19,15 @@ FoamFile
 type            runTimePostProcessing;
 
 // Where to load it from
-libs            ("librunTimePostProcessing.so");
+libs            ("runTimePostProcessing");
 
 // Function object enabled flag
 enabled         true;
 
-// When to output the average fields
+// When to output the images
 writeControl    writeTime;
 
-//- Optionally disable parallel VTK rendering, default = true
+//- Allow parallel rendering (default: true)
 // parallel        true;
 
 //- The output characteristics
@@ -45,27 +45,24 @@ output
 //- The camera settings
 camera
 {
-    // If camera is moving, optionally provide start and end times
+    // If camera is moving, provide start and end times
     // startPosition    0.2;
     // endPosition      0.75;
 
-    // Total number of frames to generate
+    //- Total number of frames to generate (default: 1)
     nFrameTotal     1;
 
-    // Parallel projection flag
-    parallelProjection  yes;
-
-    // clipBox is optional
+    //- Parallel projection flag (default: true)
+    // parallelProjection  yes;
 
     position        (385 -560 650);
     focalPoint      (160 90 60);
     up              (0.06 0.7 0.7);
 
-    position        ( -41.95 -247.55 426.87 );
-    focalPoint      ( 146 76 40 );
-    up              ( 0.3646 0.6194 0.6953 );
-
     zoom    1.5;
+
+    // clipBox is optional
+
     // clipBox (-10 18 0)(280 160 76);
     clipBox (-30 0 0)(300 200 80);
 }
@@ -146,6 +143,9 @@ surfaces
         {
             visible     no;
         }
+
+        //- Allow parallel rendering (default: true)
+        // parallel        true;
     }
 
     patches
@@ -183,8 +183,10 @@ surfaces
             italic      yes;
             shadow      yes;
         }
-    }
 
+        //- Allow parallel rendering (default: true)
+        // parallel        true;
+    }
 
     cutting
     {
@@ -243,15 +245,6 @@ surfaces
         field           U;
         range           (0 20);
 
-        colourField     k;
-        field           k;
-        range           (0 20);
-
-        colourBy        field;
-        colourField     U;
-        field           U;
-        range           (0 20);
-
         opacity         1;
         scalarBar
         {
diff --git a/etc/config.csh/aliases b/etc/config.csh/aliases
index 6f21e8658deddf1b7df422370015e7a3a56445a6..918d4cfa13f81322240fd89432d2897759584d71 100644
--- a/etc/config.csh/aliases
+++ b/etc/config.csh/aliases
@@ -25,8 +25,9 @@
 alias wmSet 'source $WM_PROJECT_DIR/etc/cshrc'
 alias wmInt32 'wmSet WM_LABEL_SIZE=32'
 alias wmInt64 'wmSet WM_LABEL_SIZE=64'
-alias wmSP 'wmSet WM_PRECISION_OPTION=SP'
 alias wmDP 'wmSet WM_PRECISION_OPTION=DP'
+alias wmSP 'wmSet WM_PRECISION_OPTION=SP'
+alias wmSPDP 'wmSet WM_PRECISION_OPTION=SPDP'
 
 # Clear env
 alias wmUnset 'source $WM_PROJECT_DIR/etc/config.csh/unset'
diff --git a/etc/config.csh/unset b/etc/config.csh/unset
index bec9607668acc26347324fd87575abd0bee589db..26e22f9d93a0aa78f8826e3ab01db3a6b6e9a409 100644
--- a/etc/config.csh/unset
+++ b/etc/config.csh/unset
@@ -162,8 +162,9 @@ endif
 unalias wmSet
 unalias wmInt32
 unalias wmInt64
-unalias wmSP
 unalias wmDP
+unalias wmSP
+unalias wmSPDP
 
 unalias wmUnset
 
diff --git a/etc/config.sh/aliases b/etc/config.sh/aliases
index 79d8efe606da47883f03165cae2eab56da6c9d5f..9ead10e19fdb33021966bc38aadf8019001b881e 100644
--- a/etc/config.sh/aliases
+++ b/etc/config.sh/aliases
@@ -25,8 +25,9 @@
 alias wmSet='. $WM_PROJECT_DIR/etc/bashrc'
 alias wmInt32='wmSet WM_LABEL_SIZE=32'
 alias wmInt64='wmSet WM_LABEL_SIZE=64'
-alias wmSP='wmSet WM_PRECISION_OPTION=SP'
 alias wmDP='wmSet WM_PRECISION_OPTION=DP'
+alias wmSP='wmSet WM_PRECISION_OPTION=SP'
+alias wmSPDP='wmSet WM_PRECISION_OPTION=SPDP'
 
 # Clear env
 alias wmUnset='. $WM_PROJECT_DIR/etc/config.sh/unset'
diff --git a/etc/config.sh/unset b/etc/config.sh/unset
index f3bee0ee80c744fcb611f65f641ceabab33124b1..a44eaa967159aec4f8bcf00c2f521580f793a41b 100644
--- a/etc/config.sh/unset
+++ b/etc/config.sh/unset
@@ -156,8 +156,9 @@ fi
 unalias wmSet       2>/dev/null
 unalias wmInt32     2>/dev/null
 unalias wmInt64     2>/dev/null
-unalias wmSP        2>/dev/null
 unalias wmDP        2>/dev/null
+unalias wmSP        2>/dev/null
+unalias wmSPDP      2>/dev/null
 
 unalias wmUnset     2>/dev/null
 
diff --git a/etc/controlDict b/etc/controlDict
index bcc4096734edb9b0b3e008bdef5b981c7cbb9d58..223f28e3abd134e726ca73efdab2b8223782c6b3 100644
--- a/etc/controlDict
+++ b/etc/controlDict
@@ -37,6 +37,8 @@ InfoSwitches
     writePrecision  6;
 
     writeDictionaries 0;
+
+    // Report optional dictionary entries. For value > 1, treat as fatal.
     writeOptionalEntries 0;
 
     // Write lagrangian "positions" file in v1706 format (and earlier)
@@ -218,7 +220,7 @@ DebugSwitches
     FDIC                0;
     FaceCellWave        0;
     GAMG                0;
-    GAMGAgglomeration   1;
+    GAMGAgglomeration   0;
     GAMGInterface       0;
     GAMGInterfaceField  0;
     Gamma               0;
diff --git a/etc/cshrc b/etc/cshrc
index 098d8856986fc54176585c13632a63550583d45f..895513345d2ea38ee992ce7d21d93f37b08c315d 100644
--- a/etc/cshrc
+++ b/etc/cshrc
@@ -83,7 +83,7 @@ setenv WM_COMPILER Gcc
 setenv WM_ARCH_OPTION 64
 
 # [WM_PRECISION_OPTION] - Floating-point precision:
-# = DP | SP
+# = DP | SP | SPDP
 setenv WM_PRECISION_OPTION DP
 
 # [WM_LABEL_SIZE] - Label size in bits:
diff --git a/modules/cfmesh b/modules/cfmesh
index 23d46a1bc7c2b1fe854549f37c8357e3f00478d7..20ca801a3ac0b35064ad92a3aa5482c24e70c3f4 160000
--- a/modules/cfmesh
+++ b/modules/cfmesh
@@ -1 +1 @@
-Subproject commit 23d46a1bc7c2b1fe854549f37c8357e3f00478d7
+Subproject commit 20ca801a3ac0b35064ad92a3aa5482c24e70c3f4
diff --git a/src/OSspecific/MSwindows/MSwindows.C b/src/OSspecific/MSwindows/MSwindows.C
index 30fb55792f446ebd29941765b459de2cceff4e43..9ea78be68090af92e8c3770e83076232087d2f71 100644
--- a/src/OSspecific/MSwindows/MSwindows.C
+++ b/src/OSspecific/MSwindows/MSwindows.C
@@ -47,6 +47,8 @@ License
 #include <io.h>     // For _close
 #include <windows.h>
 
+#define EXT_SO  "dll"
+
 
 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
 
@@ -350,12 +352,16 @@ Foam::string Foam::getEnv(const std::string& envName)
 {
     std::string env;
 
-    const auto len = ::GetEnvironmentVariable(envName.c_str(), nullptr, 0);
+    auto len = ::GetEnvironmentVariable(envName.c_str(), nullptr, 0);
 
+    // len [return] = size with trailing nul char, or zero on failure
     if (len)
     {
-        env.resize(len+1);
-        ::GetEnvironmentVariable(envName.c_str(), &(env[0]), len+1);
+        env.resize(len);
+
+        // len [in] = size with trailing nul char
+        // len [return] = size without trailing nul char
+        len = ::GetEnvironmentVariable(envName.c_str(), &(env[0]), len);
 
         env.resize(len);
         return fileName::validate(env);
@@ -442,16 +448,18 @@ Foam::fileName Foam::home(const std::string& userName)
 Foam::fileName Foam::cwd()
 {
     string path;
-    const DWORD len = ::GetCurrentDirectory(0, nullptr);
+    auto len = ::GetCurrentDirectory(0, nullptr);
 
+    // len [return] = size with trailing nul char, or zero on failure
     if (len)
     {
-        path.resize(len+1);
+        path.resize(len);
 
-        ::GetCurrentDirectory(len+1, &(path[0]));
+        // len [in] = size with trailing nul char
+        // len [return] = size without trailing nul char
+        len = ::GetCurrentDirectory(len, &(path[0]));
 
         path.resize(len);
-
         return fileName::validate(path);
     }
 
@@ -1184,14 +1192,21 @@ void* Foam::dlOpen(const fileName& libName, const bool check)
             << " : dlopen of " << libName << std::endl;
     }
 
-    // Map "libXX.so" and "libXX" to "libXX.dll"
+    // Always remap "libXX.so" and "libXX" to "libXX.dll"
+    fileName libso(libName.lessExt().ext(EXT_SO));
 
-    fileName winLibName(libName.lessExt().ext("dll"));
-    void* handle = ::LoadLibrary(winLibName.c_str());
+    void* handle = ::LoadLibrary(libso.c_str());
+
+    if (!handle && !libso.startsWith("lib"))
+    {
+        // Try with 'lib' prefix
+        libso = "lib" + libso;
+        handle = ::LoadLibrary(libso.c_str());
+    }
 
     if (handle)
     {
-        libsLoaded[handle] = libName.lessExt();
+        libsLoaded[handle] = libso.lessExt();
     }
     else if (check)
     {
@@ -1212,6 +1227,26 @@ void* Foam::dlOpen(const fileName& libName, const bool check)
 }
 
 
+Foam::label Foam::dlOpen
+(
+    std::initializer_list<fileName> libNames,
+    const bool check
+)
+{
+    label nLoaded = 0;
+
+    for (const fileName& libName : libNames)
+    {
+        if (Foam::dlOpen(libName, check))
+        {
+            ++nLoaded;
+        }
+    }
+
+    return nLoaded;
+}
+
+
 bool Foam::dlClose(void* const handle)
 {
     if (MSwindows::debug)
diff --git a/src/OSspecific/POSIX/POSIX.C b/src/OSspecific/POSIX/POSIX.C
index 7259bee4747f5168f638adb0e8fce774e860b8b8..4b970b4a069378e2164095d64c0cab49c025552d 100644
--- a/src/OSspecific/POSIX/POSIX.C
+++ b/src/OSspecific/POSIX/POSIX.C
@@ -61,8 +61,10 @@ Description
 #include <dlfcn.h>
 
 #ifdef __APPLE__
+    #define EXT_SO  "dylib"
     #include <mach-o/dyld.h>
 #else
+    #define EXT_SO  "so"
 
     // PGI does not have __int128_t
     #ifdef __PGIC__
@@ -1653,22 +1655,40 @@ int Foam::system(const Foam::UList<Foam::string>& command, const bool bg)
 
 void* Foam::dlOpen(const fileName& libName, const bool check)
 {
+    constexpr int ldflags = (RTLD_LAZY|RTLD_GLOBAL);
+
     if (POSIX::debug)
     {
         std::cout
             << "dlOpen(const fileName&)"
             << " : dlopen of " << libName << std::endl;
     }
-    void* handle = ::dlopen(libName.c_str(), RTLD_LAZY|RTLD_GLOBAL);
 
-    #ifdef __APPLE__
-    // Re-try "libXX.so" as "libXX.dylib"
-    if (!handle && libName.hasExt("so"))
+    void* handle = ::dlopen(libName.c_str(), ldflags);
+
+    if (!handle)
     {
-        const fileName dylibName(libName.lessExt().ext("dylib"));
-        handle = ::dlopen(dylibName.c_str(), RTLD_LAZY|RTLD_GLOBAL);
+        fileName libso;
+
+        if (!libName.startsWith("lib"))
+        {
+            // Try with 'lib' prefix
+            libso = "lib" + libName;
+            handle = ::dlopen(libso.c_str(), ldflags);
+        }
+        else
+        {
+            libso = libName;
+        }
+
+        // With canonical library extension ("so" or "dylib"), which remaps
+        // "libXX" to "libXX.so" as well as "libXX.so" -> "libXX.dylib"
+        if (!handle && !libso.hasExt(EXT_SO))
+        {
+            libso = libso.lessExt().ext(EXT_SO);
+            handle = ::dlopen(libso.c_str(), ldflags);
+        }
     }
-    #endif
 
     if (!handle && check)
     {
@@ -1689,6 +1709,26 @@ void* Foam::dlOpen(const fileName& libName, const bool check)
 }
 
 
+Foam::label Foam::dlOpen
+(
+    std::initializer_list<fileName> libNames,
+    const bool check
+)
+{
+    label nLoaded = 0;
+
+    for (const fileName& libName : libNames)
+    {
+        if (Foam::dlOpen(libName, check))
+        {
+            ++nLoaded;
+        }
+    }
+
+    return nLoaded;
+}
+
+
 bool Foam::dlClose(void* handle)
 {
     if (POSIX::debug)
diff --git a/src/OSspecific/POSIX/regExp/regExp.H b/src/OSspecific/POSIX/regExp/regExp.H
index eee48c78d8c2fd7e9aa8a8df2ddfce4e783d12c2..fa85bea12e14354999f214b4045013e4d77340a3 100644
--- a/src/OSspecific/POSIX/regExp/regExp.H
+++ b/src/OSspecific/POSIX/regExp/regExp.H
@@ -32,6 +32,7 @@ Description
 #ifndef regExp_H
 #define regExp_H
 
+#include "regExpCxx.H"
 #include "regExpPosix.H"
 #include "regExpFwd.H"
 
diff --git a/src/OSspecific/POSIX/regExp/regExpFwd.H b/src/OSspecific/POSIX/regExp/regExpFwd.H
index 47e8c268cf0bf7e53e23003ca320a659280747a4..09838222809090471328619885d61589307ad795 100644
--- a/src/OSspecific/POSIX/regExp/regExpFwd.H
+++ b/src/OSspecific/POSIX/regExp/regExpFwd.H
@@ -39,7 +39,12 @@ namespace Foam
     class regExpCxx;
     class regExpPosix;
 
+    // Newer compilers support regex directly
+    #if (_GLIBCXX_RELEASE >= 7) || (__clang_major__ >= 7)
+    typedef regExpCxx regExp;
+    #else
     typedef regExpPosix regExp;
+    #endif
 }
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
diff --git a/src/OSspecific/POSIX/regExp/regExpPosix.H b/src/OSspecific/POSIX/regExp/regExpPosix.H
index dbed07a4dc619fa532f1164f30c5ed308e2e2c79..86c6147538dfd427c47e2c799b9ca1b23d86cf8d 100644
--- a/src/OSspecific/POSIX/regExp/regExpPosix.H
+++ b/src/OSspecific/POSIX/regExp/regExpPosix.H
@@ -120,7 +120,7 @@ public:
     inline ~regExpPosix();
 
 
-    // Member functions
+    // Member Functions
 
     // Access
 
diff --git a/src/OpenFOAM/Make/files b/src/OpenFOAM/Make/files
index bc6680fc53b3d464f5aed8444b03a62b8d4bc446..8fee47ce9a7c63597b3529a95744aff48ac68d2c 100644
--- a/src/OpenFOAM/Make/files
+++ b/src/OpenFOAM/Make/files
@@ -79,7 +79,7 @@ primitives/Vector/complexVector/complexVector.C
 primitives/Vector/doubleVector/doubleVector.C
 primitives/Tensor/doubleTensor/doubleTensor.C
 #endif
-#if !defined(WM_SP)
+#if !defined(WM_SP) && !defined(WM_SPDP)
 primitives/Vector/floatVector/floatVector.C
 primitives/Tensor/floatTensor/floatTensor.C
 #endif
diff --git a/src/OpenFOAM/Make/options b/src/OpenFOAM/Make/options
index d9e7cdaf889421347961153743b7ca916d10e083..d12d74d12bbb7d8dc8f3f96a3b9b45c0b75d17e8 100644
--- a/src/OpenFOAM/Make/options
+++ b/src/OpenFOAM/Make/options
@@ -5,11 +5,13 @@ EXE_INC = \
     -I$(OBJECTS_DIR)
 
 LIB_LIBS = \
-    $(FOAM_LIBBIN)/libOSspecific.o \
-    -lz
+    $(FOAM_LIBBIN)/libOSspecific.o
 
 ifeq ($(FOAM_LINK_DUMMY_PSTREAM),libo)
     LIB_LIBS += $(FOAM_LIBBIN)/dummy/libPstream.o
 else
     LIB_LIBS += -L$(FOAM_LIBBIN)/dummy -lPstream
 endif
+
+LIB_LIBS += \
+    -lz
diff --git a/src/OpenFOAM/containers/LinkedLists/linkTypes/DLListBase/DLListBase.H b/src/OpenFOAM/containers/LinkedLists/linkTypes/DLListBase/DLListBase.H
index 24c0b5bd8b6e7abb503313ea5bfffec878f86c28..e6bb07cd9f897032dc1cc7df7eb1baa6abb11453 100644
--- a/src/OpenFOAM/containers/LinkedLists/linkTypes/DLListBase/DLListBase.H
+++ b/src/OpenFOAM/containers/LinkedLists/linkTypes/DLListBase/DLListBase.H
@@ -243,8 +243,7 @@ public:
 
             //- Deprecated(2019-01) Pointing at a valid storage node
             //  \deprecated(2019-01) - use good() method
-            inline bool found() const
-            FOAM_DEPRECATED_FOR(2019-01, "good() method")
+            bool FOAM_DEPRECATED_FOR(2019-01, "good() method") found() const
             {
                 return this->good();
             }
@@ -297,8 +296,7 @@ public:
 
             //- Deprecated(2019-01) Pointing at a valid storage node
             //  \deprecated(2019-01) - use good() method
-            inline bool found() const
-            FOAM_DEPRECATED_FOR(2019-01, "good() method")
+            bool FOAM_DEPRECATED_FOR(2019-01, "good() method") found() const
             {
                 return this->good();
             }
diff --git a/src/OpenFOAM/containers/LinkedLists/linkTypes/SLListBase/SLListBase.H b/src/OpenFOAM/containers/LinkedLists/linkTypes/SLListBase/SLListBase.H
index 066cce1b86a3cea36093f70baab31c3990a79acb..c48913e39916e9e20ac1097f06c7495cf28d8d3f 100644
--- a/src/OpenFOAM/containers/LinkedLists/linkTypes/SLListBase/SLListBase.H
+++ b/src/OpenFOAM/containers/LinkedLists/linkTypes/SLListBase/SLListBase.H
@@ -219,8 +219,7 @@ public:
 
             //- Deprecated(2019-01) Pointing at a valid storage node
             //  \deprecated(2019-01) - use good() method
-            inline bool found() const
-            FOAM_DEPRECATED_FOR(2019-01, "good() method")
+            bool FOAM_DEPRECATED_FOR(2019-01, "good() method") found() const
             {
                 return this->good();
             }
@@ -271,8 +270,7 @@ public:
 
             //- Deprecated(2019-01) Pointing at a valid storage node
             //  \deprecated(2019-01) - use good() method
-            inline bool found() const
-            FOAM_DEPRECATED_FOR(2019-01, "good() method")
+            bool FOAM_DEPRECATED_FOR(2019-01, "good() method") found() const
             {
                 return this->good();
             }
diff --git a/src/OpenFOAM/db/IOobject/IOobject.C b/src/OpenFOAM/db/IOobject/IOobject.C
index f6354f2a5dc383c319e4af09352f16da5db36a0e..79bb51634fec2741eb0ba3e06de9512fbbc0e450 100644
--- a/src/OpenFOAM/db/IOobject/IOobject.C
+++ b/src/OpenFOAM/db/IOobject/IOobject.C
@@ -160,10 +160,10 @@ bool Foam::IOobject::fileNameComponents
         #endif
     )
     {
-        // Absolute path (starts with '/')
+        // Absolute path (starts with '/' or 'd:/')
         // => no local
 
-        instance = path.substr(first, last);
+        instance = path.substr(0, last);
 
         const std::string ending = path.substr(last+1);
         nameLen = ending.size();  // The raw length of name
diff --git a/src/OpenFOAM/db/dictionary/dictionary.C b/src/OpenFOAM/db/dictionary/dictionary.C
index 775d90ea5974dfa24ac1a26253ead15859cf3305..a15a73c8559f8734a6b6c289969acf96aa2122f3 100644
--- a/src/OpenFOAM/db/dictionary/dictionary.C
+++ b/src/OpenFOAM/db/dictionary/dictionary.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2015-2018 OpenCFD Ltd.
+    \\  /    A nd           | Copyright (C) 2015-2019 OpenCFD Ltd.
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
                             | Copyright (C) 2011-2017 OpenFOAM Foundation
@@ -42,13 +42,12 @@ namespace Foam
 
 const Foam::dictionary Foam::dictionary::null;
 
-bool Foam::dictionary::writeOptionalEntries
+int Foam::dictionary::writeOptionalEntries
 (
     Foam::debug::infoSwitch("writeOptionalEntries", 0)
 );
 
 
-
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
 Foam::dictionary::dictionary()
@@ -311,13 +310,30 @@ void Foam::dictionary::checkITstream
 }
 
 
+void Foam::dictionary::raiseBadInput(const word& keyword) const
+{
+    // Can use FatalIOError instead of SafeFatalIOError
+    // since predicate checks are not used at the earliest stages
+    FatalIOError
+    (
+        "",                 // functionName
+        "",                 // sourceFileName
+        0,                  // sourceFileLineNumber
+        *this               // ios
+    )
+        << "Entry '" << keyword << "' with invalid input in dictionary "
+        << name() << nl << nl
+        << exit(FatalIOError);
+}
+
+
 bool Foam::dictionary::found
 (
     const word& keyword,
     enum keyType::option matchOpt
 ) const
 {
-    return csearch(keyword, matchOpt).found();
+    return csearch(keyword, matchOpt).good();
 }
 
 
@@ -359,11 +375,11 @@ const Foam::entry& Foam::dictionary::lookupEntry
 {
     const const_searcher finder(csearch(keyword, matchOpt));
 
-    if (!finder.found())
+    if (!finder.good())
     {
         FatalIOErrorInFunction(*this)
             << "Entry '" << keyword << "' not found in dictionary "
-            << name()
+            << name() << nl
             << exit(FatalIOError);
     }
 
@@ -395,7 +411,7 @@ bool Foam::dictionary::substituteKeyword(const word& keyword, bool mergeEntry)
     const const_searcher finder(csearch(varName, keyType::REGEX_RECURSIVE));
 
     // If defined insert its entries into this dictionary
-    if (finder.found())
+    if (finder.good())
     {
         for (const entry& e : finder.dict())
         {
@@ -427,7 +443,7 @@ bool Foam::dictionary::substituteScopedKeyword
     const auto finder(csearchScoped(varName, keyType::REGEX_RECURSIVE));
 
     // If defined insert its entries into this dictionary
-    if (finder.found())
+    if (finder.good())
     {
         for (const entry& e : finder.dict())
         {
@@ -473,11 +489,11 @@ const Foam::dictionary& Foam::dictionary::subDict(const word& keyword) const
     // Allow patterns, non-recursive
     const const_searcher finder(csearch(keyword, keyType::REGEX));
 
-    if (!finder.found())
+    if (!finder.good())
     {
         FatalIOErrorInFunction(*this)
             << "Entry '" << keyword << "' not found in dictionary "
-            << name()
+            << name() << nl
             << exit(FatalIOError);
     }
 
@@ -490,11 +506,11 @@ Foam::dictionary& Foam::dictionary::subDict(const word& keyword)
     // Allow patterns, non-recursive
     searcher finder(search(keyword, keyType::REGEX));
 
-    if (!finder.found())
+    if (!finder.good())
     {
         FatalIOErrorInFunction(*this)
             << "Entry '" << keyword << "' not found in dictionary "
-            << name()
+            << name() << nl
             << exit(FatalIOError);
     }
 
@@ -526,7 +542,7 @@ Foam::dictionary Foam::dictionary::subOrEmptyDict
             << exit(FatalIOError);
     }
 
-    if (finder.found())
+    if (finder.good())
     {
         IOWarningInFunction(*this)
             << "Entry '" << keyword
@@ -552,7 +568,7 @@ const Foam::dictionary& Foam::dictionary::optionalSubDict
         return finder.dict();
     }
 
-    if (finder.found())
+    if (finder.good())
     {
         IOWarningInFunction(*this)
             << "Entry '" << keyword
@@ -611,7 +627,7 @@ Foam::entry* Foam::dictionary::add(entry* entryPtr, bool mergeEntry)
 
     auto iter = hashedEntries_.find(entryPtr->keyword());
 
-    if (mergeEntry && iter.found())
+    if (mergeEntry && iter.good())
     {
         // Merge dictionary with dictionary
         if (iter()->isDict() && entryPtr->isDict())
@@ -786,7 +802,7 @@ bool Foam::dictionary::merge(const dictionary& dict)
     {
         auto fnd = hashedEntries_.find(e.keyword());
 
-        if (fnd.found())
+        if (fnd.good())
         {
             // Recursively merge sub-dictionaries
             // TODO: merge without copying
diff --git a/src/OpenFOAM/db/dictionary/dictionary.H b/src/OpenFOAM/db/dictionary/dictionary.H
index 33dc695cd55c589cef6f2a103da688883b0276f4..7200a507edbd536fb5b10bbeae99f3b401225d32 100644
--- a/src/OpenFOAM/db/dictionary/dictionary.H
+++ b/src/OpenFOAM/db/dictionary/dictionary.H
@@ -62,8 +62,8 @@ Note
         key2        $..key1; // use key1 value from parent
         subdict2
         {
-            key2        val2;
-            key3        $...key1; // use key1 value from grandparent
+            key2    val2;
+            key3    $...key1; // use key1 value from grandparent
         }
     }
 
@@ -285,8 +285,9 @@ private:
     // Private Data
 
         //- Report optional keywords and values if not present in dictionary
+        //  For value greater than 1: fatal.
         //  Set/unset via an InfoSwitch
-        static bool writeOptionalEntries;
+        static int writeOptionalEntries;
 
         //- The dictionary name
         fileName name_;
@@ -359,6 +360,10 @@ private:
         ) const;
 
 
+        //- Emit IOError about bad input for the entry
+        void raiseBadInput(const word& keyword) const;
+
+
 public:
 
     // Declare name of the class and its debug switch
@@ -532,7 +537,6 @@ public:
             enum keyType::option matchOpt = keyType::REGEX
         );
 
-        //- Search for an entry (const access) with the given keyword.
         //- Find and return a sub-dictionary pointer if present
         //  (and a sub-dictionary) otherwise return nullptr.
         //
@@ -543,6 +547,7 @@ public:
             enum keyType::option matchOpt = keyType::REGEX
         ) const;
 
+        //- Search for an entry (const access) with the given keyword.
         //
         //  \param matchOpt the default search is non-recursive with patterns
         //
@@ -553,22 +558,22 @@ public:
             enum keyType::option matchOpt
         ) const;
 
-        //- Find and return a T.
+        //- Find and return an entry data stream.
         //- FatalIOError if not found, or if the number of tokens is incorrect.
         //
         //  \param matchOpt the default search is non-recursive with patterns
-        template<class T>
-        T get
+        ITstream& lookup
         (
             const word& keyword,
             enum keyType::option matchOpt = keyType::REGEX
         ) const;
 
-        //- Find and return an entry data stream.
+        //- Find and return a T.
         //- FatalIOError if not found, or if the number of tokens is incorrect.
         //
         //  \param matchOpt the default search is non-recursive with patterns
-        ITstream& lookup
+        template<class T>
+        T get
         (
             const word& keyword,
             enum keyType::option matchOpt = keyType::REGEX
@@ -579,7 +584,7 @@ public:
         //
         //  \param matchOpt the default search is non-recursive with patterns
         template<class T>
-        T lookupOrDefault
+        T getOrDefault
         (
             const word& keyword,
             const T& deflt,
@@ -592,7 +597,7 @@ public:
         //
         //  \param matchOpt the default search is non-recursive with patterns
         template<class T>
-        T lookupOrAddDefault
+        T getOrAdd
         (
             const word& keyword,
             const T& deflt,
@@ -633,6 +638,86 @@ public:
             enum keyType::option matchOpt = keyType::REGEX
         ) const;
 
+        //- Find and return a T with additional checking
+        //- FatalIOError if not found, or if the number of tokens is incorrect.
+        //
+        //  \param pred the value check predicate
+        //  \param matchOpt the default search is non-recursive with patterns
+        template<class T, class Predicate>
+        T getCheck
+        (
+            const word& keyword,
+            const Predicate& pred,
+            enum keyType::option matchOpt = keyType::REGEX
+        ) const;
+
+        //- Find and return a T, or return the given default value.
+        //- FatalIOError if it is found and the number of tokens is incorrect.
+        //
+        //  \param pred the value check predicate
+        //  \param matchOpt the default search is non-recursive with patterns
+        template<class T, class Predicate>
+        T getCheckOrDefault
+        (
+            const word& keyword,
+            const T& deflt,
+            const Predicate& pred,
+            enum keyType::option matchOpt = keyType::REGEX
+        ) const;
+
+        //- Find and return a T, or return the given default value
+        //- and add it to dictionary.
+        //- FatalIOError if it is found and the number of tokens is incorrect.
+        //
+        //  \param pred the value check predicate
+        //  \param matchOpt the default search is non-recursive with patterns
+        template<class T, class Predicate>
+        T getCheckOrAdd
+        (
+            const word& keyword,
+            const T& deflt,
+            const Predicate& pred,
+            enum keyType::option matchOpt = keyType::REGEX
+        );
+
+        //- Find entry and assign to T val.
+        //- FatalIOError if it is found and the number of tokens is incorrect,
+        //- or it is mandatory and not found.
+        //
+        //  \param val the value to read into
+        //  \param pred the value check predicate
+        //  \param matchOpt the default search is non-recursive with patterns
+        //  \param mandatory the keyword is mandatory
+        //
+        //  \return true if the entry was found.
+        template<class T, class Predicate>
+        bool readCheck
+        (
+            const word& keyword,
+            T& val,
+            const Predicate& pred,
+            enum keyType::option matchOpt = keyType::REGEX,
+            bool mandatory = true
+        ) const;
+
+        //- Find an entry if present, and assign to T val.
+        //- FatalIOError if it is found and the number of tokens is incorrect.
+        //  Default search: non-recursive with patterns.
+        //
+        //  \param val the value to read into
+        //  \param pred the value check predicate
+        //  \param matchOpt the default search is non-recursive with patterns
+        //
+        //  \return true if the entry was found.
+        template<class T, class Predicate>
+        bool readCheckIfPresent
+        (
+            const word& keyword,
+            T& val,
+            const Predicate& pred,
+            enum keyType::option matchOpt = keyType::REGEX
+        ) const;
+
         //- Check if entry is found and and is a sub-dictionary.
         //
         //  Search type: non-recursive with patterns.
@@ -983,32 +1068,32 @@ public:
             enum keyType::option
         ) const;
 
-        //- Find and return a T
+        //- Find and return an entry data stream,
         //- using any compatibility names if needed.
-        //- FatalIOError if not found, or if there are excess tokens.
         //  Default search: non-recursive with patterns.
         //
         //  \param compat list of old compatibility keywords and the last
         //      OpenFOAM version for which they were used.
         //  \param recursive search parent dictionaries
         //  \param patternMatch use regular expressions
-        template<class T>
-        T getCompat
+        ITstream& lookupCompat
         (
             const word& keyword,
             std::initializer_list<std::pair<const char*,int>> compat,
             enum keyType::option = keyType::REGEX
         ) const;
 
-        //- Find and return an entry data stream,
+        //- Find and return a T
         //- using any compatibility names if needed.
+        //- FatalIOError if not found, or if there are excess tokens.
         //  Default search: non-recursive with patterns.
         //
         //  \param compat list of old compatibility keywords and the last
         //      OpenFOAM version for which they were used.
         //  \param recursive search parent dictionaries
         //  \param patternMatch use regular expressions
-        ITstream& lookupCompat
+        template<class T>
+        T getCompat
         (
             const word& keyword,
             std::initializer_list<std::pair<const char*,int>> compat,
@@ -1024,7 +1109,7 @@ public:
         //  \param recursive search parent dictionaries
         //  \param patternMatch use regular expressions
         template<class T>
-        T lookupOrDefaultCompat
+        T getOrDefaultCompat
         (
             const word& keyword,
             std::initializer_list<std::pair<const char*,int>> compat,
@@ -1105,10 +1190,63 @@ public:
 
     // Housekeeping
 
+        //- Find and return a T, or return the given default value.
+        //- FatalIOError if it is found and the number of tokens is incorrect.
+        //
+        //  \param matchOpt the default search is non-recursive with patterns
+        template<class T>
+        T lookupOrDefault
+        (
+            const word& keyword,
+            const T& deflt,
+            enum keyType::option matchOpt = keyType::REGEX
+        ) const
+        {
+            return getOrDefault<T>(keyword, deflt, matchOpt);
+        }
+
+
+        //- Find and return a T, or return the given default value
+        //- and add it to dictionary.
+        //- FatalIOError if it is found and the number of tokens is incorrect.
+        //
+        //  \param matchOpt the default search is non-recursive with patterns
+        template<class T>
+        T lookupOrAddDefault
+        (
+            const word& keyword,
+            const T& deflt,
+            enum keyType::option matchOpt = keyType::REGEX
+        )
+        {
+            return getOrAdd<T>(keyword, deflt, matchOpt);
+        }
+
+        //- Find and return a T, or return the given default value
+        //- using any compatibility names if needed.
+        //  Default search: non-recursive with patterns.
+        //
+        //  \param compat list of old compatibility keywords and the last
+        //      OpenFOAM version for which they were used.
+        //  \param recursive search parent dictionaries
+        //  \param patternMatch use regular expressions
+        template<class T>
+        T lookupOrDefaultCompat
+        (
+            const word& keyword,
+            std::initializer_list<std::pair<const char*,int>> compat,
+            const T& deflt,
+            enum keyType::option matchOpt = keyType::REGEX
+        ) const
+        {
+            return getOrDefaultCompat<T>(keyword, compat, deflt, matchOpt);
+        }
+
         //- Deprecated(2018-07) find and return an entry data stream
         //
         //  \deprecated(2018-07) - use lookup() method
-        ITstream& operator[](const word& keyword) const
+        ITstream& FOAM_DEPRECATED_FOR(2018-07, "lookup() method")
+        operator[](const word& keyword) const
         {
             return lookup(keyword);
         }
@@ -1116,7 +1254,8 @@ public:
         //- Deprecated(2018-10) find and return a T.
         //  \deprecated(2018-10) - use get() method
         template<class T>
-        T lookupType
+        T FOAM_DEPRECATED_FOR(2018-10, "get() method")
+        lookupType
         (
             const word& keyword,
             bool recursive = false,
@@ -1128,7 +1267,8 @@ public:
 
         //- Deprecated(2018-10)
         //  \deprecated(2018-10) - use keyType::option version
-        bool found
+        bool FOAM_DEPRECATED_FOR(2018-10, "found(keyType::option)")
+        found
         (
             const word& keyword,
             bool recursive,
@@ -1140,7 +1280,9 @@ public:
 
         //- Deprecated(2018-10)
         //  \deprecated(2018-10) - use keyType::option version
-        entry* lookupEntryPtr
+        entry*
+        FOAM_DEPRECATED_FOR(2018-10, "lookupEntryPtr(keyType::option)")
+        lookupEntryPtr
         (
             const word& keyword,
             bool recursive,
@@ -1152,7 +1294,9 @@ public:
 
         //- Deprecated(2018-10)
         //  \deprecated(2018-10) - use keyType::option version
-        const entry* lookupEntryPtr
+        const entry*
+        FOAM_DEPRECATED_FOR(2018-10, "lookupEntryPtr(keyType::option)")
+        lookupEntryPtr
         (
             const word& keyword,
             bool recursive,
@@ -1164,7 +1308,9 @@ public:
 
         //- Deprecated(2018-10)
         //  \deprecated(2018-10) - use keyType::option version
-        const entry* lookupScopedEntryPtr
+        const entry*
+        FOAM_DEPRECATED_FOR(2018-10, "lookupScopedEntryPtr(keyType::option)")
+        lookupScopedEntryPtr
         (
             const word& keyword,
             bool recursive,
@@ -1180,7 +1326,9 @@ public:
         //
         //  Search type: non-recursive with patterns.
         //  \deprecated(2018-10) - use findDict() method
-        const dictionary* subDictPtr(const word& keyword) const
+        const dictionary*
+        FOAM_DEPRECATED_FOR(2018-10, "findDict() method")
+        subDictPtr(const word& keyword) const
         {
             return findDict(keyword, keyType::REGEX);
         }
@@ -1191,14 +1339,18 @@ public:
         //
         //  Search type: non-recursive with patterns.
         //  \deprecated(2018-10) - use findDict() method
-        dictionary* subDictPtr(const word& keyword)
+        dictionary*
+        FOAM_DEPRECATED_FOR(2018-10, "findDict() method")
+        subDictPtr(const word& keyword)
         {
             return findDict(keyword, keyType::REGEX);
         }
 
         //- Deprecated(2018-10)
         //  \deprecated(2018-10) - use keyType::option version
-        const entry& lookupEntry
+        const entry&
+        FOAM_DEPRECATED_FOR(2018-10, "lookupEntry(keyType::option)")
+        lookupEntry
         (
             const word& keyword,
             bool recursive,
@@ -1210,7 +1362,9 @@ public:
 
         //- Deprecated(2018-10)
         //  \deprecated(2018-10) - use keyType::option version
-        ITstream& lookup
+        ITstream&
+        FOAM_DEPRECATED_FOR(2018-10, "lookup(keyType::option)")
+        lookup
         (
             const word& keyword,
             bool recursive,
@@ -1223,7 +1377,8 @@ public:
         //- Deprecated(2018-10)
         //  \deprecated(2018-10) - use keyType::option version
         template<class T>
-        T lookupOrDefault
+        T FOAM_DEPRECATED_FOR(2018-10, "lookupOrDefault(keyType::option)")
+        lookupOrDefault
         (
             const word& keyword,
             const T& deflt,
@@ -1239,7 +1394,8 @@ public:
         //- Deprecated(2018-10)
         //  \deprecated(2018-10) - use keyType::option version
         template<class T>
-        T lookupOrAddDefault
+        T FOAM_DEPRECATED_FOR(2018-10, "lookupOrAddDefault(keyType::option)")
+        lookupOrAddDefault
         (
             const word& keyword,
             const T& deflt,
@@ -1255,7 +1411,9 @@ public:
         //- Deprecated(2018-10)
         //  \deprecated(2018-10) - use keyType::option version
         template<class T>
-        bool readIfPresent
+        bool
+        FOAM_DEPRECATED_FOR(2018-10, "readIfPresent(keyType::option)")
+        readIfPresent
         (
             const word& keyword,
             T& val,
diff --git a/src/OpenFOAM/db/dictionary/dictionaryCompat.C b/src/OpenFOAM/db/dictionary/dictionaryCompat.C
index c35d7f6b2344ed2cf1ab76ed3395c00f08fdd1f0..ca4a9a7cbb8f2578377e50962a98df59f769c15a 100644
--- a/src/OpenFOAM/db/dictionary/dictionaryCompat.C
+++ b/src/OpenFOAM/db/dictionary/dictionaryCompat.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2017-2018 OpenCFD Ltd.
+    \\  /    A nd           | Copyright (C) 2017-2019 OpenCFD Ltd.
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -54,7 +54,7 @@ Foam::dictionary::const_searcher Foam::dictionary::csearchCompat
 {
     const_searcher finder(csearch(keyword, matchOpt));
 
-    if (finder.found())
+    if (finder.good())
     {
         return finder;
     }
@@ -63,7 +63,7 @@ Foam::dictionary::const_searcher Foam::dictionary::csearchCompat
     {
         finder = csearch(word::validate(iter.first), matchOpt);
 
-        if (finder.found())
+        if (finder.good())
         {
             // Only want a single warning (on master), but guard with a
             // parRun check to avoid Pstream::master() when Pstream has not
@@ -101,7 +101,7 @@ bool Foam::dictionary::foundCompat
     enum keyType::option matchOpt
 ) const
 {
-    return csearchCompat(keyword, compat, matchOpt).found();
+    return csearchCompat(keyword, compat, matchOpt).good();
 }
 
 
@@ -125,7 +125,7 @@ const Foam::entry& Foam::dictionary::lookupEntryCompat
 {
     const const_searcher finder(csearchCompat(keyword, compat, matchOpt));
 
-    if (!finder.found())
+    if (!finder.good())
     {
         FatalIOErrorInFunction(*this)
             << "Entry '" << keyword << "' not found in dictionary "
diff --git a/src/OpenFOAM/db/dictionary/dictionarySearch.C b/src/OpenFOAM/db/dictionary/dictionarySearch.C
index d3fcee91c452fac581ab959a6759946ad0d0bb3a..59cebc461dd4fe684760f598124680b21b077b86 100644
--- a/src/OpenFOAM/db/dictionary/dictionarySearch.C
+++ b/src/OpenFOAM/db/dictionary/dictionarySearch.C
@@ -130,7 +130,7 @@ Foam::dictionary::const_searcher Foam::dictionary::csearchDotScoped
     // a.b.c.d it would try
     // a.b, a.b.c, a.b.c.d
 
-    if (!finder.found())
+    if (!finder.good())
     {
         while (!finder.isDict())
         {
@@ -225,7 +225,7 @@ Foam::dictionary::const_searcher Foam::dictionary::csearchSlashScoped
 
             auto finder = dictPtr->csearch(key, matchOpt);
 
-            if (finder.found())
+            if (finder.good())
             {
                 if (remaining)
                 {
@@ -269,7 +269,7 @@ Foam::dictionary::const_searcher Foam::dictionary::csearch
 
     auto iter = hashedEntries_.cfind(keyword);
 
-    if (iter.found())
+    if (iter.good())
     {
         finder.set(iter.val());
         return finder;
@@ -425,7 +425,7 @@ const Foam::dictionary* Foam::dictionary::cfindScopedDict
 
             auto iter = dictPtr->hashedEntries_.cfind(cmpt);
 
-            if (iter.found())
+            if (iter.good())
             {
                 const entry *eptr = iter.val();
 
@@ -532,7 +532,7 @@ Foam::dictionary* Foam::dictionary::makeScopedDict(const fileName& dictPath)
 
             auto iter = dictPtr->hashedEntries_.find(cmptName);
 
-            if (iter.found())
+            if (iter.good())
             {
                 entry *eptr = iter.val();
 
@@ -581,7 +581,7 @@ bool Foam::dictionary::remove(const word& keyword)
 {
     auto iter = hashedEntries_.find(keyword);
 
-    if (iter.found())
+    if (iter.good())
     {
         // Delete from patterns
         auto wcLink = patterns_.begin();
@@ -621,7 +621,7 @@ bool Foam::dictionary::changeKeyword
     // Check that oldKeyword exists and can be changed
     auto iter = hashedEntries_.find(oldKeyword);
 
-    if (!iter.found())
+    if (!iter.good())
     {
         return false;
     }
@@ -638,7 +638,7 @@ bool Foam::dictionary::changeKeyword
     auto iter2 = hashedEntries_.find(newKeyword);
 
     // newKeyword already exists
-    if (iter2.found())
+    if (iter2.good())
     {
         if (overwrite)
         {
diff --git a/src/OpenFOAM/db/dictionary/dictionaryTemplates.C b/src/OpenFOAM/db/dictionary/dictionaryTemplates.C
index 31737707232bfa40d8edf83d937104c40b84815c..1ae164b5ecabc2d280ff2db87d7fb3a3f8d25e2b 100644
--- a/src/OpenFOAM/db/dictionary/dictionaryTemplates.C
+++ b/src/OpenFOAM/db/dictionary/dictionaryTemplates.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2017-2018 OpenCFD Ltd.
+    \\  /    A nd           | Copyright (C) 2017-2019 OpenCFD Ltd.
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
                             | Copyright (C) 2011-2017 OpenFOAM Foundation
@@ -64,6 +64,20 @@ T Foam::dictionary::get
 }
 
 
+template<class T, class Predicate>
+T Foam::dictionary::getCheck
+(
+    const word& keyword,
+    const Predicate& pred,
+    enum keyType::option matchOpt
+) const
+{
+    T val;
+    readCheck<T, Predicate>(keyword, val, pred, matchOpt);
+    return val;
+}
+
+
 template<class T>
 T Foam::dictionary::getCompat
 (
@@ -79,49 +93,111 @@ T Foam::dictionary::getCompat
 
 
 template<class T>
-bool Foam::dictionary::readCompat
+T Foam::dictionary::getOrDefault
 (
     const word& keyword,
-    std::initializer_list<std::pair<const char*,int>> compat,
-    T& val,
-    enum keyType::option matchOpt,
-    bool mandatory
+    const T& deflt,
+    enum keyType::option matchOpt
 ) const
 {
-    const const_searcher finder(csearchCompat(keyword, compat, matchOpt));
+    const const_searcher finder(csearch(keyword, matchOpt));
 
-    if (finder.found())
+    if (finder.good())
     {
+        T val;
+
         ITstream& is = finder.ptr()->stream();
         is >> val;
 
         checkITstream(is, keyword);
 
-        return true;
+        return val;
     }
-    else if (mandatory)
+    else if (writeOptionalEntries)
     {
-        FatalIOErrorInFunction(*this)
-            << "Entry '" << keyword << "' not found in dictionary "
-            << name()
-            << exit(FatalIOError);
+        if (writeOptionalEntries > 1)
+        {
+            FatalIOErrorInFunction(*this)
+                << "Optional entry '" << keyword
+                << "' not found. Default '" << deflt << "' ignored" << nl
+                << exit(FatalIOError);
+        }
+        else
+        {
+            IOInfoInFunction(*this)
+                << "Optional entry '" << keyword
+                << "' not found. Using default '" << deflt << "'" << nl;
+        }
     }
 
-    return false;
+    return deflt;
 }
 
 
 template<class T>
-T Foam::dictionary::lookupOrDefault
+T Foam::dictionary::getOrAdd
+(
+    const word& keyword,
+    const T& deflt,
+    enum keyType::option matchOpt
+)
+{
+    const const_searcher finder(csearch(keyword, matchOpt));
+
+    if (finder.good())
+    {
+        T val;
+
+        ITstream& is = finder.ptr()->stream();
+        is >> val;
+
+        checkITstream(is, keyword);
+
+        return val;
+    }
+    else if (writeOptionalEntries)
+    {
+        if (writeOptionalEntries > 1)
+        {
+            FatalIOErrorInFunction(*this)
+                << "Optional entry '" << keyword
+                << "' not found. Default '" << deflt << "' ignored" << nl
+                << exit(FatalIOError);
+        }
+        else
+        {
+            IOInfoInFunction(*this)
+                << "Optional entry '" << keyword
+                << "' not found. Adding default '" << deflt << "'" << nl;
+        }
+    }
+
+    add(new primitiveEntry(keyword, deflt));
+    return deflt;
+}
+
+
+template<class T, class Predicate>
+T Foam::dictionary::getCheckOrDefault
 (
     const word& keyword,
     const T& deflt,
+    const Predicate& pred,
     enum keyType::option matchOpt
 ) const
 {
+    if (!pred(deflt))
+    {
+        // Could be as FULLDEBUG instead?
+        FatalIOErrorInFunction(*this)
+            << "Entry '" << keyword << "' with invalid default in dictionary "
+            << name()
+            << exit(FatalIOError);
+    }
+
     const const_searcher finder(csearch(keyword, matchOpt));
 
-    if (finder.found())
+    if (finder.good())
     {
         T val;
 
@@ -130,31 +206,55 @@ T Foam::dictionary::lookupOrDefault
 
         checkITstream(is, keyword);
 
+        if (!pred(val))
+        {
+            raiseBadInput(keyword);
+        }
+
         return val;
     }
     else if (writeOptionalEntries)
     {
-        IOInfoInFunction(*this)
-            << "Optional entry '" << keyword
-            << "' not found, using default value '" << deflt << "'"
-            << nl;
+        if (writeOptionalEntries > 1)
+        {
+            FatalIOErrorInFunction(*this)
+                << "Optional entry '" << keyword
+                << "' not found. Default '" << deflt << "' ignored" << nl
+                << exit(FatalIOError);
+        }
+        else
+        {
+            IOInfoInFunction(*this)
+                << "Optional entry '" << keyword
+                << "' not found. Using default '" << deflt << "'" << nl;
+        }
     }
 
     return deflt;
 }
 
 
-template<class T>
-T Foam::dictionary::lookupOrAddDefault
+template<class T, class Predicate>
+T Foam::dictionary::getCheckOrAdd
 (
     const word& keyword,
     const T& deflt,
+    const Predicate& pred,
     enum keyType::option matchOpt
 )
 {
+    if (!pred(deflt))
+    {
+        // Could be as FULLDEBUG instead?
+        FatalIOErrorInFunction(*this)
+            << "Entry '" << keyword << "' with invalid default in dictionary "
+            << name()
+            << exit(FatalIOError);
+    }
+
     const const_searcher finder(csearch(keyword, matchOpt));
 
-    if (finder.found())
+    if (finder.good())
     {
         T val;
 
@@ -163,14 +263,28 @@ T Foam::dictionary::lookupOrAddDefault
 
         checkITstream(is, keyword);
 
+        if (!pred(val))
+        {
+            raiseBadInput(keyword);
+        }
+
         return val;
     }
     else if (writeOptionalEntries)
     {
-        IOInfoInFunction(*this)
-            << "Optional entry '" << keyword
-            << "' not found, adding default value '" << deflt << "'"
-            << nl;
+        if (writeOptionalEntries > 1)
+        {
+            FatalIOErrorInFunction(*this)
+                << "Optional entry '" << keyword
+                << "' not found. Default '" << deflt << "' ignored" << nl
+                << exit(FatalIOError);
+        }
+        else
+        {
+            IOInfoInFunction(*this)
+                << "Optional entry '" << keyword
+                << "' not found. Adding default '" << deflt << "'" << nl;
+        }
     }
 
     add(new primitiveEntry(keyword, deflt));
@@ -189,7 +303,7 @@ bool Foam::dictionary::readEntry
 {
     const const_searcher finder(csearch(keyword, matchOpt));
 
-    if (finder.found())
+    if (finder.good())
     {
         ITstream& is = finder.ptr()->stream();
         is >> val;
@@ -202,7 +316,78 @@ bool Foam::dictionary::readEntry
     {
         FatalIOErrorInFunction(*this)
             << "Entry '" << keyword << "' not found in dictionary "
-            << name()
+            << name() << nl
+            << exit(FatalIOError);
+    }
+
+    return false;
+}
+
+
+template<class T, class Predicate>
+bool Foam::dictionary::readCheck
+(
+    const word& keyword,
+    T& val,
+    const Predicate& pred,
+    enum keyType::option matchOpt,
+    bool mandatory
+) const
+{
+    const const_searcher finder(csearch(keyword, matchOpt));
+
+    if (finder.good())
+    {
+        ITstream& is = finder.ptr()->stream();
+        is >> val;
+
+        checkITstream(is, keyword);
+
+        if (!pred(val))
+        {
+            raiseBadInput(keyword);
+        }
+
+        return true;
+    }
+    else if (mandatory)
+    {
+        FatalIOErrorInFunction(*this)
+            << "Entry '" << keyword << "' not found in dictionary "
+            << name() << nl
+            << exit(FatalIOError);
+    }
+
+    return false;
+}
+
+
+template<class T>
+bool Foam::dictionary::readCompat
+(
+    const word& keyword,
+    std::initializer_list<std::pair<const char*,int>> compat,
+    T& val,
+    enum keyType::option matchOpt,
+    bool mandatory
+) const
+{
+    const const_searcher finder(csearchCompat(keyword, compat, matchOpt));
+
+    if (finder.good())
+    {
+        ITstream& is = finder.ptr()->stream();
+        is >> val;
+
+        checkITstream(is, keyword);
+
+        return true;
+    }
+    else if (mandatory)
+    {
+        FatalIOErrorInFunction(*this)
+            << "Entry '" << keyword << "' not found in dictionary "
+            << name() << nl
             << exit(FatalIOError);
     }
 
@@ -223,8 +408,22 @@ bool Foam::dictionary::readIfPresent
 }
 
 
+template<class T, class Predicate>
+bool Foam::dictionary::readCheckIfPresent
+(
+    const word& keyword,
+    T& val,
+    const Predicate& pred,
+    enum keyType::option matchOpt
+) const
+{
+    // Read is non-mandatory
+    return readCheck<T, Predicate>(keyword, val, pred, matchOpt, false);
+}
+
+
 template<class T>
-T Foam::dictionary::lookupOrDefaultCompat
+T Foam::dictionary::getOrDefaultCompat
 (
     const word& keyword,
     std::initializer_list<std::pair<const char*,int>> compat,
@@ -234,7 +433,7 @@ T Foam::dictionary::lookupOrDefaultCompat
 {
     const const_searcher finder(csearchCompat(keyword, compat, matchOpt));
 
-    if (finder.found())
+    if (finder.good())
     {
         T val;
 
@@ -247,10 +446,19 @@ T Foam::dictionary::lookupOrDefaultCompat
     }
     else if (writeOptionalEntries)
     {
-        IOInfoInFunction(*this)
-            << "Optional entry '" << keyword << "' not found,"
-            << " using default value '" << deflt << "'"
-            << nl;
+        if (writeOptionalEntries > 1)
+        {
+            FatalIOErrorInFunction(*this)
+                << "Optional entry '" << keyword
+                << "' not found. Default '" << deflt << "' ignored" << nl
+                << exit(FatalIOError);
+        }
+        else
+        {
+            IOInfoInFunction(*this)
+                << "Optional entry '" << keyword
+                << "' not found. Using default '" << deflt << "'" << nl;
+        }
     }
 
     return deflt;
diff --git a/src/OpenFOAM/db/dictionary/entry/entry.C b/src/OpenFOAM/db/dictionary/entry/entry.C
index 9bd55a3e050587d76bf1417993e63ea0faa1546a..7583c7bc81f873ab7326a494750e5fec90a3f2ad 100644
--- a/src/OpenFOAM/db/dictionary/entry/entry.C
+++ b/src/OpenFOAM/db/dictionary/entry/entry.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           |
+    \\  /    A nd           | Copyright (C) 2017-2019 OpenCFD Ltd.
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
                             | Copyright (C) 2011-2015 OpenFOAM Foundation
@@ -73,6 +73,25 @@ Foam::autoPtr<Foam::entry> Foam::entry::clone() const
 
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
+void Foam::entry::raiseBadInput(const ITstream& is) const
+{
+    const word& keyword = keyword_;
+
+    // Can use FatalIOError instead of SafeFatalIOError
+    // since predicate checks are not used at the earliest stages
+    FatalIOError
+    (
+        "",                 // functionName
+        "",                 // sourceFileName
+        0,                  // sourceFileLineNumber
+        this->name(),       // ioFileName
+        is.lineNumber()     // ioStartLineNumber
+    )
+        << "Entry '" << keyword << "' with invalid input" << nl << nl
+        << exit(FatalIOError);
+}
+
+
 void Foam::entry::checkITstream(const ITstream& is) const
 {
     const word& keyword = keyword_;
diff --git a/src/OpenFOAM/db/dictionary/entry/entry.H b/src/OpenFOAM/db/dictionary/entry/entry.H
index 1fe2e6b2d840b301392bf0b78f7e66a898a00613..58180f5955bdc7224357ea616cb438a785db1d6a 100644
--- a/src/OpenFOAM/db/dictionary/entry/entry.H
+++ b/src/OpenFOAM/db/dictionary/entry/entry.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2017-2018 OpenCFD Ltd.
+    \\  /    A nd           | Copyright (C) 2017-2019 OpenCFD Ltd.
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
                             | Copyright (C) 2011-2016 OpenFOAM Foundation
@@ -109,6 +109,9 @@ private:
         //  \return True if it is a valid keyType.
         static bool getKeyword(keyType& keyword, Istream& is);
 
+        //- Emit IOError about bad input for the entry
+        void raiseBadInput(const ITstream& is) const;
+
 
 public:
 
@@ -272,6 +275,37 @@ public:
             checkITstream(is);
         }
 
+        //- Get a T from the stream,
+        //- FatalIOError if the number of tokens is incorrect.
+        //
+        //  \param pred the value check predicate
+        template<class T, class Predicate>
+        T getCheck(const Predicate& pred) const
+        {
+            T val;
+            readCheck<T>(val, pred);
+            return val;
+        }
+
+        //- Assign to T val,
+        //- FatalIOError if the number of tokens is incorrect.
+        //
+        //  \param val the value to read into
+        //  \param pred the value check predicate
+        template<class T, class Predicate>
+        void readCheck(T& val, const Predicate& pred) const
+        {
+            ITstream& is = this->stream();
+            is >> val;
+
+            checkITstream(is);
+            if (!pred(val))
+            {
+                raiseBadInput(is);
+            }
+        }
+
+
     // Write
 
         //- Write
diff --git a/src/OpenFOAM/db/dictionary/entry/entryIO.C b/src/OpenFOAM/db/dictionary/entry/entryIO.C
index 60b62f60d01180dfd4a2e0cdafdea90aa0ab604c..fbd297882890921e52b22b12dcafbc91b8024cc8 100644
--- a/src/OpenFOAM/db/dictionary/entry/entryIO.C
+++ b/src/OpenFOAM/db/dictionary/entry/entryIO.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2018 OpenCFD Ltd.
+    \\  /    A nd           | Copyright (C) 2018-2019 OpenCFD Ltd.
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
                             | Copyright (C) 2011-2016 OpenFOAM Foundation
@@ -246,7 +246,7 @@ bool Foam::entry::New
             const auto finder =
                 parentDict.csearchScoped(varName, keyType::REGEX_RECURSIVE);
 
-            if (finder.found())
+            if (finder.good())
             {
                 // Read as primitiveEntry
                 const keyType newKeyword(finder.ptr()->stream());
@@ -311,7 +311,7 @@ bool Foam::entry::New
         // How to manage duplicate entries
         bool mergeEntry = false;
 
-        if (finder.found())
+        if (finder.good())
         {
             // Use keyword from the found entry (ie, eliminate scoping chars)
             const keyType key = finder.ref().keyword();
diff --git a/src/OpenFOAM/db/dictionary/functionEntries/removeEntry/removeEntry.C b/src/OpenFOAM/db/dictionary/functionEntries/removeEntry/removeEntry.C
index 6ab5618fa7dd66614e0b33a99ee394a5e308461a..b067fb76c48bd9ef98bfe9d9de4ce8014d852fc7 100644
--- a/src/OpenFOAM/db/dictionary/functionEntries/removeEntry/removeEntry.C
+++ b/src/OpenFOAM/db/dictionary/functionEntries/removeEntry/removeEntry.C
@@ -65,7 +65,7 @@ bool Foam::functionEntries::removeEntry::execute
             // Remove scoped keyword, or keyword in the local scope
             auto finder(parentDict.searchScoped(key, keyType::LITERAL));
 
-            if (finder.found())
+            if (finder.good())
             {
                 finder.context().remove(finder.ptr()->keyword());
             }
diff --git a/src/OpenFOAM/db/dynamicLibrary/dynamicCode/dynamicCode.C b/src/OpenFOAM/db/dynamicLibrary/dynamicCode/dynamicCode.C
index bbc7efd87ff1d4735582eb6a65c8bcf9a9f7c47f..6feac2f065f32bc8f54728e7f85b2e7772b4d1b6 100644
--- a/src/OpenFOAM/db/dynamicLibrary/dynamicCode/dynamicCode.C
+++ b/src/OpenFOAM/db/dynamicLibrary/dynamicCode/dynamicCode.C
@@ -36,7 +36,6 @@ License
 #include "dictionary.H"
 #include "foamVersion.H"
 
-#undef EXT_SO
 #ifdef __APPLE__
     #define EXT_SO  ".dylib"
 #elif defined _WIN32
diff --git a/src/OpenFOAM/db/functionObjects/timeControl/timeControlFunctionObject.C b/src/OpenFOAM/db/functionObjects/timeControl/timeControlFunctionObject.C
index 1ec6bf8f4ed3bfff7f093dcd0621e9b58b8f3a77..dd076e3b60f7018e5e6e92096275a8a25cc69cfe 100644
--- a/src/OpenFOAM/db/functionObjects/timeControl/timeControlFunctionObject.C
+++ b/src/OpenFOAM/db/functionObjects/timeControl/timeControlFunctionObject.C
@@ -42,12 +42,12 @@ namespace functionObjects
 
 const Foam::Enum<Foam::functionObjects::timeControl::controlMode>
 Foam::functionObjects::timeControl::controlModeNames_
-{
+({
     { controlMode::TIME, "time" },
     { controlMode::TRIGGER, "trigger" },
     { controlMode::TIME_OR_TRIGGER, "timeOrTrigger" },
     { controlMode::TIME_AND_TRIGGER, "timeAndTrigger" }
-};
+});
 
 
 // * * * * * * * * * * * * * * * Private Members * * * * * * * * * * * * * * //
diff --git a/src/OpenFOAM/db/objectRegistry/objectRegistry.C b/src/OpenFOAM/db/objectRegistry/objectRegistry.C
index 264add34cd42350385f16ede15923900f09bb37a..fe9cdb2a9e4a2ce36cd0ce041126d2158daafe30 100644
--- a/src/OpenFOAM/db/objectRegistry/objectRegistry.C
+++ b/src/OpenFOAM/db/objectRegistry/objectRegistry.C
@@ -333,22 +333,23 @@ bool Foam::objectRegistry::checkOut(const word& key) const
 
 void Foam::objectRegistry::clear()
 {
-    // Free anything owned by the registry
+    // Free anything owned by the registry, but first unset both
+    // 'ownedByRegistry' and 'registered' flags to ensure that the
+    // regIOobject destructor will not affect the registry
+
     for (iterator iter = begin(); iter != end(); ++iter)
     {
         regIOobject* ptr = iter.val();
 
         if (ptr && ptr->ownedByRegistry())
         {
-            // TBD: may wish to have ptr->clearWatches();
-
             if (objectRegistry::debug)
             {
-                Pout<< "objectRegistry::clear : " << ptr->name()
-                    <<  " watches :" << flatOutput(ptr->watchIndices()) << nl;
-
+                Pout<< "objectRegistry::clear : " << ptr->name() << nl;
             }
-            delete ptr;
+
+            ptr->release(true);     // Relinquish ownership and registration
+            delete ptr;             // Delete also clears fileHandler watches
         }
     }
 
@@ -365,18 +366,18 @@ void Foam::objectRegistry::clearStorage()
 
 bool Foam::objectRegistry::erase(const iterator& iter)
 {
-    // Free anything owned by the registry
+    // Remove from registry - see notes in objectRegistry::clear()
 
     if (iter.found())
     {
         regIOobject* ptr = iter.val();
 
-        bool ok = HashTable<regIOobject*>::erase(iter);
+        const bool ok = HashTable<regIOobject*>::erase(iter);
 
         if (ptr && ptr->ownedByRegistry())
         {
-            // TBD: may wish to have ptr->clearWatches();
-            delete ptr;
+            ptr->release(true);     // Relinquish ownership and registration
+            delete ptr;             // Delete also clears fileHandler watches
         }
 
         return ok;
diff --git a/src/OpenFOAM/db/regIOobject/regIOobject.C b/src/OpenFOAM/db/regIOobject/regIOobject.C
index a933fd799d8c2d5130b420af37d3ab032ac8fbbd..b9abc11951b3378353a9464ea5638ffaeb4ad972 100644
--- a/src/OpenFOAM/db/regIOobject/regIOobject.C
+++ b/src/OpenFOAM/db/regIOobject/regIOobject.C
@@ -156,19 +156,36 @@ Foam::regIOobject::~regIOobject()
 {
     if (objectRegistry::debug)
     {
-        Pout<< "Destroying regIOobject called " << name()
-            << " of type " << type()
-            << " registered " << registered_
-            << " owned " << ownedByRegistry_
-            << " in directory " << path()
+        Pout<< "Destroy regIOobject: " << name()
+            << " type=" << type()
+            << " registered=" << registered_
+            << " owned=" << ownedByRegistry_
+            << " directory=" << path()
             << endl;
     }
 
-    // Check out of objectRegistry if not owned by the registry
-    if (!ownedByRegistry_)
-    {
-        checkOut();
-    }
+    // Deletion of a regIOobject should remove itself from its registry
+    // (ie, checkOut), but there are different paths for destruction to occur.
+    // The complications are only when the object is ownedByRegistry.
+    //
+    // 1. The objectRegistry clear()/erase() is called (and object is
+    //    'ownedByRegistry').
+    //
+    //  - Mark as unowned/unregistered prior to deletion.
+    //    This ensures that this checkOut() only clears file watches and
+    //    does nothing else.
+    //
+    // 2. The regIOobject is deleted directly (and also 'ownedByRegistry').
+    //
+    //  - Mark as unowned (but keep as registered) prior to triggering
+    //    checkOut(). By being 'unowned', the registry will not attempt a
+    //    second deletion when the object name is removed from the registry.
+
+    // Revoke any registry ownership: we are already deleting
+    ownedByRegistry_ = false;
+
+    // Remove registered object from objectRegistry
+    checkOut();
 }
 
 
@@ -212,15 +229,16 @@ bool Foam::regIOobject::checkIn()
 
 bool Foam::regIOobject::checkOut()
 {
+    forAllReverse(watchIndices_, i)
+    {
+        fileHandler().removeWatch(watchIndices_[i]);
+    }
+    watchIndices_.clear();
+
     if (registered_)
     {
         registered_ = false;
 
-        forAllReverse(watchIndices_, i)
-        {
-            fileHandler().removeWatch(watchIndices_[i]);
-        }
-        watchIndices_.clear();
         return db().checkOut(*this);
     }
 
diff --git a/src/OpenFOAM/db/regIOobject/regIOobject.H b/src/OpenFOAM/db/regIOobject/regIOobject.H
index 9f60d99eb3c9816ba6dcf1113706da4c3a66811d..d4505e6cc847c210868d891c257e7af42c3ec349 100644
--- a/src/OpenFOAM/db/regIOobject/regIOobject.H
+++ b/src/OpenFOAM/db/regIOobject/regIOobject.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2018 OpenCFD Ltd.
+    \\  /    A nd           | Copyright (C) 2018-2019 OpenCFD Ltd.
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
                             | Copyright (C) 2011-2017 OpenFOAM Foundation
@@ -133,19 +133,19 @@ public:
 
     // Constructors
 
-        //- Construct from IOobject. Optional flag for if IOobject is the
-        //  top level regIOobject.
+        //- Construct from IOobject with optional flag if IOobject is the
+        //- top-level regIOobject.
         regIOobject(const IOobject&, const bool isTime = false);
 
-        //- Construct as copy
+        //- Copy construct
         regIOobject(const regIOobject&);
 
-        //- Construct as copy, transferring registry registration to copy
-        //  if registerCopy is true
+        //- Copy construct, transferring registry registration to the copy
+        //- if registerCopy is true
         regIOobject(const regIOobject&, bool registerCopy);
 
-        //- Construct as copy with new name, transferring registry registration
-        //  to copy as specified
+        //- Copy construct with new name, transferring registry registration
+        //- to the copy f registerCopy is true
         regIOobject(const word& newName, const regIOobject&, bool registerCopy);
 
         //- Construct as copy with new IO parameters
@@ -163,7 +163,8 @@ public:
             //- Add object to registry
             bool checkIn();
 
-            //- Remove object from registry
+            //- Remove all file watches and remove object from registry
+            //  \return true if object was registered and was removed
             bool checkOut();
 
             //- Add file watch on object (if registered and READ_IF_MODIFIED)
@@ -191,7 +192,8 @@ public:
             inline static Type& store(autoPtr<Type>&& aptr);
 
             //- Release ownership of this object from its registry
-            inline void release();
+            //  \param unregister optionally set as non-registered
+            inline void release(const bool unregister = false);
 
 
         // Dependency checking
diff --git a/src/OpenFOAM/db/regIOobject/regIOobjectI.H b/src/OpenFOAM/db/regIOobject/regIOobjectI.H
index 1f9e82f9739c9a0f5d842d8665db81dfa4cb7f28..3418a60888041ca5aad3558b19f9357d45cf4971 100644
--- a/src/OpenFOAM/db/regIOobject/regIOobjectI.H
+++ b/src/OpenFOAM/db/regIOobject/regIOobjectI.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2018 OpenCFD Ltd.
+    \\  /    A nd           | Copyright (C) 2018-2019 OpenCFD Ltd.
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
                             | Copyright (C) 2011-2015 OpenFOAM Foundation
@@ -69,9 +69,13 @@ inline Type& Foam::regIOobject::store(autoPtr<Type>&& aptr)
 }
 
 
-inline void Foam::regIOobject::release()
+inline void Foam::regIOobject::release(const bool unregister)
 {
     ownedByRegistry_ = false;
+    if (unregister)
+    {
+        registered_ = false;
+    }
 }
 
 
diff --git a/src/OpenFOAM/dimensionedTypes/dimensionedType/dimensionedType.C b/src/OpenFOAM/dimensionedTypes/dimensionedType/dimensionedType.C
index 20487de8c9566d048c78f0598befa2ae3bf7588c..cc0240be0ba1c2f3b2f8585b3ec60155afe5253e 100644
--- a/src/OpenFOAM/dimensionedTypes/dimensionedType/dimensionedType.C
+++ b/src/OpenFOAM/dimensionedTypes/dimensionedType/dimensionedType.C
@@ -274,38 +274,38 @@ Foam::dimensioned<Type>::dimensioned
 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
 
 template<class Type>
-Foam::dimensioned<Type> Foam::dimensioned<Type>::lookupOrDefault
+Foam::dimensioned<Type> Foam::dimensioned<Type>::getOrDefault
 (
     const word& name,
     const dictionary& dict,
     const dimensionSet& dims,
-    const Type& defaultValue
+    const Type& deflt
 )
 {
     // checkDims = true
-    return dimensioned<Type>(name, dims, defaultValue, dict);
+    return dimensioned<Type>(name, dims, deflt, dict);
 }
 
 
 template<class Type>
-Foam::dimensioned<Type> Foam::dimensioned<Type>::lookupOrDefault
+Foam::dimensioned<Type> Foam::dimensioned<Type>::getOrDefault
 (
     const word& name,
     const dictionary& dict,
-    const Type& defaultValue
+    const Type& deflt
 )
 {
-    return dimensioned<Type>(name, dimless, defaultValue, dict);
+    return dimensioned<Type>(name, dimless, deflt, dict);
 }
 
 
 template<class Type>
-Foam::dimensioned<Type> Foam::dimensioned<Type>::lookupOrAddToDict
+Foam::dimensioned<Type> Foam::dimensioned<Type>::getOrAddToDict
 (
     const word& name,
     dictionary& dict,
     const dimensionSet& dims,
-    const Type& defaultValue
+    const Type& deflt
 )
 {
     if (dict.found(name))
@@ -313,20 +313,20 @@ Foam::dimensioned<Type> Foam::dimensioned<Type>::lookupOrAddToDict
         return dimensioned<Type>(name, dims, dict);
     }
 
-    (void) dict.add(name, defaultValue);
-    return dimensioned<Type>(name, dims, defaultValue);
+    (void) dict.add(name, deflt);
+    return dimensioned<Type>(name, dims, deflt);
 }
 
 
 template<class Type>
-Foam::dimensioned<Type> Foam::dimensioned<Type>::lookupOrAddToDict
+Foam::dimensioned<Type> Foam::dimensioned<Type>::getOrAddToDict
 (
     const word& name,
     dictionary& dict,
-    const Type& defaultValue
+    const Type& deflt
 )
 {
-    return lookupOrAddToDict(name, dict, dimless, defaultValue);
+    return getOrAddToDict(name, dict, dimless, deflt);
 }
 
 
diff --git a/src/OpenFOAM/dimensionedTypes/dimensionedType/dimensionedType.H b/src/OpenFOAM/dimensionedTypes/dimensionedType/dimensionedType.H
index 982ab31c7df32cffcbe9b5d81119a79567844a3e..2e768cbda56c5fb7dabff8334324b0ef12aa815b 100644
--- a/src/OpenFOAM/dimensionedTypes/dimensionedType/dimensionedType.H
+++ b/src/OpenFOAM/dimensionedTypes/dimensionedType/dimensionedType.H
@@ -207,42 +207,42 @@ public:
 
         //- Construct dimensioned from dictionary, with default value.
         //- FatalIOError if there are excess tokens.
-        static dimensioned<Type> lookupOrDefault
+        static dimensioned<Type> getOrDefault
         (
             const word& name,
             const dictionary& dict,
             const dimensionSet& dims = dimless,
-            const Type& defaultValue = Type(Zero)
+            const Type& deflt = Type(Zero)
         );
 
         //- Construct dimensionless from dictionary, with default value.
         //  FatalIOError if it is found and there are excess tokens.
-        static dimensioned<Type> lookupOrDefault
+        static dimensioned<Type> getOrDefault
         (
             const word& name,
             const dictionary& dict,
-            const Type& defaultValue = Type(Zero)
+            const Type& deflt = Type(Zero)
         );
 
         //- Construct dimensioned from dictionary, with default value.
         //  If the value is not found, it is added into the dictionary.
         //  FatalIOError if it is found and there are excess tokens.
-        static dimensioned<Type> lookupOrAddToDict
+        static dimensioned<Type> getOrAddToDict
         (
             const word& name,
             dictionary& dict,
             const dimensionSet& dims = dimless,
-            const Type& defaultValue = Type(Zero)
+            const Type& deflt = Type(Zero)
         );
 
         //- Construct dimensionless from dictionary, with default value.
         //  If the value is not found, it is added into the dictionary.
         //  FatalIOError if it is found and there are excess tokens.
-        static dimensioned<Type> lookupOrAddToDict
+        static dimensioned<Type> getOrAddToDict
         (
             const word& name,
             dictionary& dict,
-            const Type& defaultValue = Type(Zero)
+            const Type& deflt = Type(Zero)
         );
 
 
@@ -361,6 +361,59 @@ public:
         //      dictionary instead (additional checks on the input stream).
         dimensioned(const word& name, const dimensionSet& dims, Istream& is)
         FOAM_DEPRECATED(2018-11);
+
+
+        //- Construct dimensioned from dictionary, with default value.
+        //- FatalIOError if there are excess tokens.
+        static dimensioned<Type> lookupOrDefault
+        (
+            const word& name,
+            const dictionary& dict,
+            const dimensionSet& dims = dimless,
+            const Type& deflt = Type(Zero)
+        )
+        {
+            return getOrDefault(name, dict, dims, deflt);
+        }
+
+        //- Construct dimensionless from dictionary, with default value.
+        //  FatalIOError if it is found and there are excess tokens.
+        static dimensioned<Type> lookupOrDefault
+        (
+            const word& name,
+            const dictionary& dict,
+            const Type& deflt = Type(Zero)
+        )
+        {
+            return getOrDefault(name, dict, deflt);
+        }
+
+        //- Construct dimensioned from dictionary, with default value.
+        //  If the value is not found, it is added into the dictionary.
+        //  FatalIOError if it is found and there are excess tokens.
+        static dimensioned<Type> lookupOrAddToDict
+        (
+            const word& name,
+            dictionary& dict,
+            const dimensionSet& dims = dimless,
+            const Type& deflt = Type(Zero)
+        )
+        {
+            return getOrAddToDict(name, dict, dims, deflt);
+        }
+
+        //- Construct dimensionless from dictionary, with default value.
+        //  If the value is not found, it is added into the dictionary.
+        //  FatalIOError if it is found and there are excess tokens.
+        static dimensioned<Type> lookupOrAddToDict
+        (
+            const word& name,
+            dictionary& dict,
+            const Type& deflt = Type(Zero)
+        )
+        {
+            return getOrAddToDict(name, dict, deflt);
+        }
 };
 
 
diff --git a/src/OpenFOAM/fields/DimensionedFields/DimensionedField/DimensionedFieldFunctions.C b/src/OpenFOAM/fields/DimensionedFields/DimensionedField/DimensionedFieldFunctions.C
index 603c78c5743afa4165fd722c5897264cdbcf0f71..2573a39afb2c2775048ddb8ec0b2bd668a325b7e 100644
--- a/src/OpenFOAM/fields/DimensionedFields/DimensionedField/DimensionedFieldFunctions.C
+++ b/src/OpenFOAM/fields/DimensionedFields/DimensionedField/DimensionedFieldFunctions.C
@@ -324,12 +324,13 @@ dimensioned<returnType> func                                                   \
 UNARY_REDUCTION_FUNCTION(Type, max, gMax)
 UNARY_REDUCTION_FUNCTION(Type, min, gMin)
 UNARY_REDUCTION_FUNCTION(Type, sum, gSum)
-UNARY_REDUCTION_FUNCTION(scalar, sumMag, gSumMag)
 UNARY_REDUCTION_FUNCTION(Type, average, gAverage)
 
 UNARY_REDUCTION_FUNCTION(MinMax<Type>, minMax, gMinMax)
 UNARY_REDUCTION_FUNCTION(scalarMinMax, minMaxMag, gMinMaxMag)
 
+UNARY_REDUCTION_FUNCTION(scalar, sumMag, gSumMag)
+
 #undef UNARY_REDUCTION_FUNCTION
 
 
diff --git a/src/OpenFOAM/fields/DimensionedFields/DimensionedField/DimensionedFieldFunctions.H b/src/OpenFOAM/fields/DimensionedFields/DimensionedField/DimensionedFieldFunctions.H
index cebb4ada3e5cad0b8f21c2de62dfbfea07fbe97f..198aa981eb6a749e2cd2a0dda67f87b5fe779fa3 100644
--- a/src/OpenFOAM/fields/DimensionedFields/DimensionedField/DimensionedFieldFunctions.H
+++ b/src/OpenFOAM/fields/DimensionedFields/DimensionedField/DimensionedFieldFunctions.H
@@ -102,6 +102,7 @@ tmp
 cmptAv(const tmp<DimensionedField<Type, GeoMesh>>& tdf);
 
 
+// Forward to FieldFunction via dfunc()
 #define UNARY_REDUCTION_FUNCTION(returnType, func, dfunc)                      \
                                                                                \
 template<class Type, class GeoMesh>                                            \
@@ -118,12 +119,12 @@ dimensioned<returnType> func                                                   \
 UNARY_REDUCTION_FUNCTION(Type, max, gMax)
 UNARY_REDUCTION_FUNCTION(Type, min, gMin)
 UNARY_REDUCTION_FUNCTION(Type, sum, gSum)
-UNARY_REDUCTION_FUNCTION(scalar, sumMag, gSumMag)
 UNARY_REDUCTION_FUNCTION(Type, average, gAverage)
-
 UNARY_REDUCTION_FUNCTION(MinMax<Type>, minMax, gMinMax)
 UNARY_REDUCTION_FUNCTION(scalarMinMax, minMaxMag, gMinMaxMag)
 
+UNARY_REDUCTION_FUNCTION(scalar, sumMag, gSumMag)
+
 #undef UNARY_REDUCTION_FUNCTION
 
 
diff --git a/src/OpenFOAM/fields/FieldFields/FieldField/FieldFieldFunctions.C b/src/OpenFOAM/fields/FieldFields/FieldField/FieldFieldFunctions.C
index 146ae1193c714f9e7a17dcbb7529f52892c18b16..159c223198bbdd3f1289743ba0093ce2a5772d77 100644
--- a/src/OpenFOAM/fields/FieldFields/FieldField/FieldFieldFunctions.C
+++ b/src/OpenFOAM/fields/FieldFields/FieldField/FieldFieldFunctions.C
@@ -554,13 +554,14 @@ scalarMinMax minMaxMag(const FieldField<Field, Type>& f)
 TMP_UNARY_FUNCTION(scalarMinMax, minMaxMag)
 
 
+// With reduction on ReturnType
 #define G_UNARY_FUNCTION(returnType, gFunc, func, rFunc)                       \
                                                                                \
 template<template<class> class Field, class Type>                              \
 returnType gFunc(const FieldField<Field, Type>& f)                             \
 {                                                                              \
     returnType res = func(f);                                                  \
-    reduce(res, rFunc##Op<Type>());                                            \
+    reduce(res, rFunc##Op<returnType>());                                      \
     return res;                                                                \
 }                                                                              \
 TMP_UNARY_FUNCTION(returnType, gFunc)
@@ -568,10 +569,11 @@ TMP_UNARY_FUNCTION(returnType, gFunc)
 G_UNARY_FUNCTION(Type, gMax, max, max)
 G_UNARY_FUNCTION(Type, gMin, min, min)
 G_UNARY_FUNCTION(Type, gSum, sum, sum)
-G_UNARY_FUNCTION(scalar, gSumMag, sumMag, sum)
 
-G_UNARY_FUNCTION(MinMax<Type>, gMinMax, minMax, minMax)
-G_UNARY_FUNCTION(scalarMinMax, gMinMaxMag, minMaxMag, minMaxMag)
+G_UNARY_FUNCTION(MinMax<Type>, gMinMax, minMax, sum)
+G_UNARY_FUNCTION(scalarMinMax, gMinMaxMag, minMaxMag, sum)
+
+G_UNARY_FUNCTION(scalar, gSumMag, sumMag, sum)
 
 #undef G_UNARY_FUNCTION
 
diff --git a/src/OpenFOAM/fields/FieldFields/FieldField/FieldFieldFunctions.H b/src/OpenFOAM/fields/FieldFields/FieldField/FieldFieldFunctions.H
index 206b2fbeab3039be18c2446eb043e98f25e9b202..18be310352ce226375154977c8980659c2bb9121 100644
--- a/src/OpenFOAM/fields/FieldFields/FieldField/FieldFieldFunctions.H
+++ b/src/OpenFOAM/fields/FieldFields/FieldField/FieldFieldFunctions.H
@@ -238,6 +238,7 @@ scalarMinMax minMaxMag(const FieldField<Field, Type>& f);
 TMP_UNARY_FUNCTION(scalarMinMax, minMaxMag)
 
 
+// With reduction on ReturnType
 #define G_UNARY_FUNCTION(returnType, gFunc, func, rFunc)                       \
                                                                                \
 template<template<class> class Field, class Type>                              \
@@ -247,10 +248,11 @@ TMP_UNARY_FUNCTION(returnType, gFunc)
 G_UNARY_FUNCTION(Type, gMax, max, max)
 G_UNARY_FUNCTION(Type, gMin, min, min)
 G_UNARY_FUNCTION(Type, gSum, sum, sum)
-G_UNARY_FUNCTION(scalar, gSumMag, sumMag, sum)
 
-G_UNARY_FUNCTION(MinMax<Type>, gMinMax, minMax, minMax)
-G_UNARY_FUNCTION(scalarMinMax, gMinMaxMag, minMaxMag, minMaxMag)
+G_UNARY_FUNCTION(MinMax<Type>, gMinMax, minMax, sum)
+G_UNARY_FUNCTION(scalarMinMax, gMinMaxMag, minMaxMag, sum)
+
+G_UNARY_FUNCTION(scalar, gSumMag, sumMag, sum)
 
 #undef G_UNARY_FUNCTION
 
diff --git a/src/OpenFOAM/fields/Fields/Field/Field.H b/src/OpenFOAM/fields/Fields/Field/Field.H
index af44f279c9f97d2f667d04cf440b397a524bfc8e..33b54ce345392e2dcbff48b88b70e7fb5bbd4fde 100644
--- a/src/OpenFOAM/fields/Fields/Field/Field.H
+++ b/src/OpenFOAM/fields/Fields/Field/Field.H
@@ -199,7 +199,7 @@ public:
         );
 
         //- Construct by mapping from the given tmp field. Supplied uniform
-        //  value for unmapped items
+        //- value for unmapped items
         Field
         (
             const tmp<Field<Type>>& tmapF,
@@ -209,7 +209,7 @@ public:
         );
 
         //- Construct by mapping from the given tmp field. Supplied values
-        //  for unmapped items
+        //- for unmapped items
         Field
         (
             const tmp<Field<Type>>& tmapF,
@@ -233,6 +233,12 @@ public:
         //- Clone
         inline tmp<Field<Type>> clone() const;
 
+        //- Return a pointer to a new Field created on freestore
+        static autoPtr<Field<Type>> New(Istream& is)
+        {
+            return autoPtr<Field<Type>>(new Field<Type>(is));
+        }
+
         //- Return a pointer to a new calculatedFvPatchFieldField created on
         //  freestore without setting patchField values
         template<class Type2>
diff --git a/src/OpenFOAM/fields/Fields/Field/FieldFunctions.C b/src/OpenFOAM/fields/Fields/Field/FieldFunctions.C
index aa2ad4bc8f48dc4269392064e2af259306576b13..9404946e0721e1580eb753c42937f01437c3dae3 100644
--- a/src/OpenFOAM/fields/Fields/Field/FieldFunctions.C
+++ b/src/OpenFOAM/fields/Fields/Field/FieldFunctions.C
@@ -317,10 +317,8 @@ Type max(const UList<Type>& f)
         TFOR_ALL_S_OP_FUNC_F_S(Type, Max, =, max, Type, f, Type, Max)
         return Max;
     }
-    else
-    {
-        return pTraits<Type>::min;
-    }
+
+    return pTraits<Type>::min;
 }
 
 TMP_UNARY_FUNCTION(Type, max)
@@ -334,10 +332,8 @@ Type min(const UList<Type>& f)
         TFOR_ALL_S_OP_FUNC_F_S(Type, Min, =, min, Type, f, Type, Min)
         return Min;
     }
-    else
-    {
-        return pTraits<Type>::max;
-    }
+
+    return pTraits<Type>::max;
 }
 
 TMP_UNARY_FUNCTION(Type, min)
@@ -351,10 +347,8 @@ Type sum(const UList<Type>& f)
         TFOR_ALL_S_OP_F(Type, Sum, +=, Type, f)
         return Sum;
     }
-    else
-    {
-        return Zero;
-    }
+
+    return Zero;
 }
 
 TMP_UNARY_FUNCTION(Type, sum)
@@ -387,10 +381,8 @@ Type maxMagSqr(const UList<Type>& f)
         )
         return Max;
     }
-    else
-    {
-        return Zero;
-    }
+
+    return Zero;
 }
 
 TMP_UNARY_FUNCTION(Type, maxMagSqr)
@@ -414,23 +406,24 @@ Type minMagSqr(const UList<Type>& f)
         )
         return Min;
     }
-    else
-    {
-        return pTraits<Type>::rootMax;
-    }
+
+    return pTraits<Type>::rootMax;
 }
 
 TMP_UNARY_FUNCTION(Type, minMagSqr)
 
 template<class Type>
-scalar sumProd(const UList<Type>& f1, const UList<Type>& f2)
+typename pTraits<Type>::cmptType
+sumProd(const UList<Type>& f1, const UList<Type>& f2)
 {
-    scalar SumProd = 0;
+    typedef typename pTraits<Type>::cmptType outType;
+
+    outType result = Zero;
     if (f1.size() && (f1.size() == f2.size()))
     {
-        TFOR_ALL_S_OP_F_OP_F(scalar, SumProd, +=, Type, f1, &&, Type, f2)
+        TFOR_ALL_S_OP_F_OP_F(outType, result, +=, Type, f1, &&, Type, f2)
     }
-    return SumProd;
+    return result;
 }
 
 
@@ -505,25 +498,24 @@ Type average(const UList<Type>& f)
 
         return avrg;
     }
-    else
-    {
-        WarningInFunction
-            << "empty field, returning zero" << endl;
 
-        return Zero;
-    }
+    WarningInFunction
+        << "empty field, returning zero" << endl;
+
+    return Zero;
 }
 
 TMP_UNARY_FUNCTION(Type, average)
 
 
+// With reduction on ReturnType
 #define G_UNARY_FUNCTION(ReturnType, gFunc, Func, rFunc)                       \
                                                                                \
 template<class Type>                                                           \
 ReturnType gFunc(const UList<Type>& f, const label comm)                       \
 {                                                                              \
     ReturnType res = Func(f);                                                  \
-    reduce(res, rFunc##Op<Type>(), Pstream::msgType(), comm);                  \
+    reduce(res, rFunc##Op<ReturnType>(), Pstream::msgType(), comm);            \
     return res;                                                                \
 }                                                                              \
 TMP_UNARY_FUNCTION(ReturnType, gFunc)
@@ -533,27 +525,30 @@ G_UNARY_FUNCTION(Type, gMin, min, min)
 G_UNARY_FUNCTION(Type, gSum, sum, sum)
 G_UNARY_FUNCTION(Type, gMaxMagSqr, maxMagSqr, maxMagSqr)
 G_UNARY_FUNCTION(Type, gMinMagSqr, minMagSqr, minMagSqr)
-G_UNARY_FUNCTION(scalar, gSumSqr, sumSqr, sum)
-G_UNARY_FUNCTION(scalar, gSumMag, sumMag, sum)
 G_UNARY_FUNCTION(Type, gSumCmptMag, sumCmptMag, sum)
 
-G_UNARY_FUNCTION(MinMax<Type>, gMinMax, minMax, minMax)
-G_UNARY_FUNCTION(scalarMinMax, gMinMaxMag, minMaxMag, minMaxMag)
+G_UNARY_FUNCTION(MinMax<Type>, gMinMax, minMax, sum)
+G_UNARY_FUNCTION(scalarMinMax, gMinMaxMag, minMaxMag, sum)
+
+G_UNARY_FUNCTION(scalar, gSumSqr, sumSqr, sum)
+G_UNARY_FUNCTION(scalar, gSumMag, sumMag, sum)
 
 #undef G_UNARY_FUNCTION
 
 
 template<class Type>
-scalar gSumProd
+typename pTraits<Type>::cmptType gSumProd
 (
     const UList<Type>& f1,
     const UList<Type>& f2,
     const label comm
 )
 {
-    scalar SumProd = sumProd(f1, f2);
-    reduce(SumProd, sumOp<scalar>(), Pstream::msgType(), comm);
-    return SumProd;
+    typedef typename pTraits<Type>::cmptType outType;
+
+    outType result = sumProd(f1, f2);
+    reduce(result, sumOp<outType>(), Pstream::msgType(), comm);
+    return result;
 }
 
 template<class Type>
@@ -586,13 +581,11 @@ Type gAverage
 
         return avrg;
     }
-    else
-    {
-        WarningInFunction
-            << "empty field, returning zero." << endl;
 
-        return Zero;
-    }
+    WarningInFunction
+        << "empty field, returning zero." << endl;
+
+    return Zero;
 }
 
 TMP_UNARY_FUNCTION(Type, gAverage)
@@ -658,7 +651,7 @@ tmp<Field<typename product<Type1, Type2>::type>>                               \
 operator Op(const UList<Type1>& f1, const tmp<Field<Type2>>& tf2)              \
 {                                                                              \
     typedef typename product<Type1, Type2>::type productType;                  \
-    auto tres = reuseTmp<productType, Type2>::New(tf2);     \
+    auto tres = reuseTmp<productType, Type2>::New(tf2);                        \
     OpFunc(tres.ref(), f1, tf2());                                             \
     tf2.clear();                                                               \
     return tres;                                                               \
@@ -669,7 +662,7 @@ tmp<Field<typename product<Type1, Type2>::type>>                               \
 operator Op(const tmp<Field<Type1>>& tf1, const UList<Type2>& f2)              \
 {                                                                              \
     typedef typename product<Type1, Type2>::type productType;                  \
-    auto tres = reuseTmp<productType, Type1>::New(tf1);     \
+    auto tres = reuseTmp<productType, Type1>::New(tf1);                        \
     OpFunc(tres.ref(), tf1(), f2);                                             \
     tf1.clear();                                                               \
     return tres;                                                               \
diff --git a/src/OpenFOAM/fields/Fields/Field/FieldFunctions.H b/src/OpenFOAM/fields/Fields/Field/FieldFunctions.H
index 78e5db2a0c40c47d9a55e326e85fb9acae1f939b..c64aa4798a9468a467f80a93fe52f0c93f36bfe8 100644
--- a/src/OpenFOAM/fields/Fields/Field/FieldFunctions.H
+++ b/src/OpenFOAM/fields/Fields/Field/FieldFunctions.H
@@ -197,7 +197,11 @@ TMP_UNARY_FUNCTION(Type, minMagSqr)
 
 
 template<class Type>
-scalar sumProd(const UList<Type>& f1, const UList<Type>& f2);
+typename pTraits<Type>::cmptType sumProd
+(
+    const UList<Type>& f1,
+    const UList<Type>& f2
+);
 
 template<class Type>
 Type sumCmptProd(const UList<Type>& f1, const UList<Type>& f2);
@@ -223,6 +227,7 @@ Type average(const UList<Type>& f);
 TMP_UNARY_FUNCTION(Type, average)
 
 
+// With reduction on ReturnType
 #define G_UNARY_FUNCTION(ReturnType, gFunc, Func, rFunc)                       \
                                                                                \
 template<class Type>                                                           \
@@ -234,17 +239,18 @@ G_UNARY_FUNCTION(Type, gMin, min, min)
 G_UNARY_FUNCTION(Type, gSum, sum, sum)
 G_UNARY_FUNCTION(Type, gMaxMagSqr, maxMagSqr, maxMagSqr)
 G_UNARY_FUNCTION(Type, gMinMagSqr, minMagSqr, minMagSqr)
-G_UNARY_FUNCTION(scalar, gSumSqr, sumSqr, sum)
-G_UNARY_FUNCTION(scalar, gSumMag, sumMag, sum)
 G_UNARY_FUNCTION(Type, gSumCmptMag, sumCmptMag, sum)
 
-G_UNARY_FUNCTION(MinMax<Type>, gMinMax, minMax, minMax)
-G_UNARY_FUNCTION(scalarMinMax, gMinMaxMag, minMaxMag, minMaxMag)
+G_UNARY_FUNCTION(MinMax<Type>, gMinMax, minMax, sum)
+G_UNARY_FUNCTION(scalarMinMax, gMinMaxMag, minMaxMag, sum)
+
+G_UNARY_FUNCTION(scalar, gSumSqr, sumSqr, sum)
+G_UNARY_FUNCTION(scalar, gSumMag, sumMag, sum)
 
 #undef G_UNARY_FUNCTION
 
 template<class Type>
-scalar gSumProd
+typename pTraits<Type>::cmptType gSumProd
 (
     const UList<Type>& f1,
     const UList<Type>& f2,
diff --git a/src/OpenFOAM/fields/Fields/Field/PrecisionAdaptor/PrecisionAdaptor.H b/src/OpenFOAM/fields/Fields/Field/PrecisionAdaptor/PrecisionAdaptor.H
new file mode 100644
index 0000000000000000000000000000000000000000..80f7dbc464f4f2768c7a7a3522f081406b5cce68
--- /dev/null
+++ b/src/OpenFOAM/fields/Fields/Field/PrecisionAdaptor/PrecisionAdaptor.H
@@ -0,0 +1,154 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2019 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 <http://www.gnu.org/licenses/>.
+
+Class
+    Foam::PrecisionAdaptor
+
+Description
+    Conversion adaptor for Field that either wraps as a tmp reference
+    or creates the necessary tmp and copies the values on construction
+    and destruction.
+    This provides automatic conversion between (scalar) types for use
+    with linear solvers able to run mixed precision.
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef PrecisionAdaptor_H
+#define PrecisionAdaptor_H
+
+#include "Field.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+//- A const Field wrapper with possible data conversion
+template<class Type, class InputType>
+class ConstPrecisionAdaptor
+:
+    public tmp<Field<Type>>
+{
+public:
+
+    // Constructors
+
+        //- Construct from InputType
+        ConstPrecisionAdaptor(const Field<InputType>& input)
+        :
+            tmp<Field<Type>>()
+        {
+            if (std::is_same<Type, InputType>::value)
+            {
+                // Set reference - cast for compiler to handle different types
+                this->cref(reinterpret_cast<const Field<Type>&>(input));
+            }
+            else
+            {
+                this->reset(new Field<Type>(input.size()));
+                std::copy(input.cbegin(), input.cend(), this->ref().begin());
+            }
+        }
+
+
+    // Member Functions
+
+        //- Return the field
+        static const Field<Type>& get
+        (
+            const Field<InputType>& input,
+            Field<Type>& dst
+        )
+        {
+            if (std::is_same<Type, InputType>::value)
+            {
+                return reinterpret_cast<const Field<Type>&>(input);
+            }
+            else
+            {
+                dst.resize(input.size());
+                std::copy(input.cbegin(), input.cend(), dst.begin());
+                return dst;
+            }
+        }
+};
+
+
+//- A Field wrapper with possible data conversion
+template<class Type, class InputType>
+class PrecisionAdaptor
+:
+    public tmp<Field<Type>>
+{
+    // Private Data
+
+        //- Reference to underlying field
+        Field<InputType>& ref_;
+
+
+public:
+
+    // Constructors
+
+        //- Construct from Field<InputType>, copying on input as required
+        PrecisionAdaptor(Field<InputType>& input)
+        :
+            tmp<Field<Type>>(),
+            ref_(input)
+        {
+            if (std::is_same<Type, InputType>::value)
+            {
+                // Set reference - cast for compiler to handle different types
+                this->cref(reinterpret_cast<const Field<Type>&>(input));
+            }
+            else
+            {
+                this->reset(new Field<Type>(input.size()));
+                std::copy(input.cbegin(), input.cend(), this->ref().begin());
+            }
+        }
+
+
+    //- Destructor, copying on destroy
+    ~PrecisionAdaptor()
+    {
+        if (this->isTmp())
+        {
+            const Field<Type>& store = this->cref();
+            ref_.resize(store.size());
+            std::copy(store.cbegin(), store.cend(), ref_.begin());
+        }
+    }
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/fields/Fields/complex/complexField.C b/src/OpenFOAM/fields/Fields/complex/complexField.C
index 5662ab40763d26425db2041d6bf1eb9b5f9c857f..881745b4abf358b00ac798b280922cf6a87b08b6 100644
--- a/src/OpenFOAM/fields/Fields/complex/complexField.C
+++ b/src/OpenFOAM/fields/Fields/complex/complexField.C
@@ -132,6 +132,18 @@ Foam::scalarField Foam::Im(const UList<complex>& cf)
 namespace Foam
 {
 
+template<>
+complex sumProd(const UList<complex>& f1, const UList<complex>& f2)
+{
+    complex result = Zero;
+    if (f1.size() && (f1.size() == f2.size()))
+    {
+        TFOR_ALL_S_OP_F_OP_F(complex, result, +=, complex, f1, *, complex, f2)
+    }
+    return result;
+}
+
+
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
 UNARY_FUNCTION(complex, complex, pow3)
diff --git a/src/OpenFOAM/fields/Fields/complex/complexField.H b/src/OpenFOAM/fields/Fields/complex/complexField.H
index c9b9351364f672d9a133159619638b9a4a408978..51b147263c1345775751214e7a08f0155fc6ef18 100644
--- a/src/OpenFOAM/fields/Fields/complex/complexField.H
+++ b/src/OpenFOAM/fields/Fields/complex/complexField.H
@@ -74,6 +74,12 @@ scalarField Im(const UList<complex>& cf);
 //- Sum real and imag components
 scalarField ReImSum(const UList<complex>& cf);
 
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+//- Sum product
+template<>
+complex sumProd(const UList<complex>& f1, const UList<complex>& f2);
+
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
diff --git a/src/OpenFOAM/fields/Fields/primitiveFieldsFwd.H b/src/OpenFOAM/fields/Fields/primitiveFieldsFwd.H
index db1f60d379412e7e4634eef34d0101e1b08c60fa..484aa120bdcab36c15d2884bc44a5df7b1468d07 100644
--- a/src/OpenFOAM/fields/Fields/primitiveFieldsFwd.H
+++ b/src/OpenFOAM/fields/Fields/primitiveFieldsFwd.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) 2011 OpenFOAM Foundation
@@ -48,6 +48,7 @@ template<class Type> class Field;
 
 typedef Field<label> labelField;
 typedef Field<scalar> scalarField;
+typedef Field<solveScalar> solveScalarField;
 typedef Field<vector> vectorField;
 typedef Field<sphericalTensor> sphericalTensorField;
 typedef Field<symmTensor> symmTensorField;
diff --git a/src/OpenFOAM/fields/Fields/scalarField/scalarField.C b/src/OpenFOAM/fields/Fields/scalarField/scalarField.C
index c7f151c90dc9dce36ebff0e105123c59ba1557a4..97433f1c91b52952163621d6270184796b3eb58a 100644
--- a/src/OpenFOAM/fields/Fields/scalarField/scalarField.C
+++ b/src/OpenFOAM/fields/Fields/scalarField/scalarField.C
@@ -92,14 +92,26 @@ tmp<scalarField> stabilise(const tmp<scalarField>& tsf, const scalar s)
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
 template<>
-scalar sumProd(const UList<scalar>& f1, const UList<scalar>& f2)
+float sumProd(const UList<float>& f1, const UList<float>& f2)
 {
-    scalar SumProd = 0.0;
+    float result = 0.0;
     if (f1.size() && (f1.size() == f2.size()))
     {
-        TFOR_ALL_S_OP_F_OP_F(scalar, SumProd, +=, scalar, f1, *, scalar, f2)
+        TFOR_ALL_S_OP_F_OP_F(float, result, +=, float, f1, *, float, f2)
     }
-    return SumProd;
+    return result;
+}
+
+
+template<>
+double sumProd(const UList<double>& f1, const UList<double>& f2)
+{
+    double result = 0.0;
+    if (f1.size() && (f1.size() == f2.size()))
+    {
+        TFOR_ALL_S_OP_F_OP_F(double, result, +=, double, f1, *, double, f2)
+    }
+    return result;
 }
 
 
diff --git a/src/OpenFOAM/fields/Fields/scalarField/scalarField.H b/src/OpenFOAM/fields/Fields/scalarField/scalarField.H
index db6e2e98bae31e0742b2a75cedafa049176c5b51..aa6c5adc263d95411b60648ba3fad66fa317661d 100644
--- a/src/OpenFOAM/fields/Fields/scalarField/scalarField.H
+++ b/src/OpenFOAM/fields/Fields/scalarField/scalarField.H
@@ -76,8 +76,13 @@ tmp<scalarField> stabilise(const tmp<scalarField>&, const scalar s);
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
+//- Sum product for float
 template<>
-scalar sumProd(const UList<scalar>& f1, const UList<scalar>& f2);
+float sumProd(const UList<float>& f1, const UList<float>& f2);
+
+//- Sum product for double
+template<>
+double sumProd(const UList<double>& f1, const UList<double>& f2);
 
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
diff --git a/src/OpenFOAM/fields/GeometricFields/GeometricField/GeometricFieldFunctions.C b/src/OpenFOAM/fields/GeometricFields/GeometricField/GeometricFieldFunctions.C
index 24349196d40cda7a71847d689522a4e14d1f5eed..6c2a4d3b0c875e126c69d047cb7fb9e149a319aa 100644
--- a/src/OpenFOAM/fields/GeometricFields/GeometricField/GeometricFieldFunctions.C
+++ b/src/OpenFOAM/fields/GeometricFields/GeometricField/GeometricFieldFunctions.C
@@ -506,7 +506,7 @@ dimensioned<returnType> func                                                   \
                 Foam::func(gf.primitiveField()),                               \
                 Foam::func(gf.boundaryField())                                 \
             ),                                                                 \
-            binaryOp<Type>()                                                   \
+            binaryOp<returnType>()                                             \
         )                                                                      \
     );                                                                         \
 }                                                                              \
@@ -558,8 +558,8 @@ dimensioned<returnType> func                                                   \
 }
 
 UNARY_REDUCTION_FUNCTION(Type, sum, gSum)
-UNARY_REDUCTION_FUNCTION(scalar, sumMag, gSumMag)
 UNARY_REDUCTION_FUNCTION(Type, average, gAverage)
+UNARY_REDUCTION_FUNCTION(scalar, sumMag, gSumMag)
 
 #undef UNARY_REDUCTION_FUNCTION
 
diff --git a/src/OpenFOAM/fields/GeometricFields/GeometricField/GeometricFieldFunctions.H b/src/OpenFOAM/fields/GeometricFields/GeometricField/GeometricFieldFunctions.H
index 24b701326bf103cf0d4abc621be5ba0986d4bceb..142ffbee1fa9a2065938633ccad9ceecebc6f6b5 100644
--- a/src/OpenFOAM/fields/GeometricFields/GeometricField/GeometricFieldFunctions.H
+++ b/src/OpenFOAM/fields/GeometricFields/GeometricField/GeometricFieldFunctions.H
@@ -230,10 +230,8 @@ dimensioned<returnType> func                                                   \
 
 UNARY_REDUCTION_FUNCTION_WITH_BOUNDARY(Type, max, maxOp)
 UNARY_REDUCTION_FUNCTION_WITH_BOUNDARY(Type, min, minOp)
-
-// Same signature, but different implementation
-UNARY_REDUCTION_FUNCTION_WITH_BOUNDARY(MinMax<Type>, minMax, unused)
-UNARY_REDUCTION_FUNCTION_WITH_BOUNDARY(scalarMinMax, minMaxMag, unused)
+UNARY_REDUCTION_FUNCTION_WITH_BOUNDARY(MinMax<Type>, minMax, minMaxOp)
+UNARY_REDUCTION_FUNCTION_WITH_BOUNDARY(scalarMinMax, minMaxMag, minMaxMagOp)
 
 #undef UNARY_REDUCTION_FUNCTION_WITH_BOUNDARY
 
@@ -253,8 +251,8 @@ dimensioned<returnType> func                                                   \
 );
 
 UNARY_REDUCTION_FUNCTION(Type, sum, gSum)
-UNARY_REDUCTION_FUNCTION(scalar, sumMag, gSumMag)
 UNARY_REDUCTION_FUNCTION(Type, average, gAverage)
+UNARY_REDUCTION_FUNCTION(scalar, sumMag, gSumMag)
 
 #undef UNARY_REDUCTION_FUNCTION
 
diff --git a/src/OpenFOAM/fields/cloud/cloud.C b/src/OpenFOAM/fields/cloud/cloud.C
index 91cdfbfd2610e5edd3243250dc6344128ddec49d..1f9cfdc37af845229d288a88fe8df185ea7f8226 100644
--- a/src/OpenFOAM/fields/cloud/cloud.C
+++ b/src/OpenFOAM/fields/cloud/cloud.C
@@ -40,10 +40,10 @@ Foam::word Foam::cloud::defaultName("defaultCloud");
 
 const Foam::Enum<Foam::cloud::geometryType>
 Foam::cloud::geometryTypeNames
-{
+({
     { geometryType::COORDINATES, "coordinates" },
     { geometryType::POSITIONS, "positions" }
-};
+});
 
 
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
diff --git a/src/OpenFOAM/global/argList/argList.C b/src/OpenFOAM/global/argList/argList.C
index f9daf29dc8b9702c37222aaba57d986ab15a4b18..2ac39189fe8b9a943ef0cd540fa51f1818cae652 100644
--- a/src/OpenFOAM/global/argList/argList.C
+++ b/src/OpenFOAM/global/argList/argList.C
@@ -1168,7 +1168,7 @@ void Foam::argList::parse
 
                 decompDict.readEntry("numberOfSubdomains", dictNProcs);
 
-                if (decompDict.lookupOrDefault("distributed", false))
+                if (decompDict.getOrDefault("distributed", false))
                 {
                     parRunControl_.distributed(true);
                     decompDict.readEntry("roots", roots);
diff --git a/src/OpenFOAM/global/argList/argList.H b/src/OpenFOAM/global/argList/argList.H
index d505a534aef1bb1f2ada9f127edb6f383f6417e8..422818c5a28d4e4a7d519cdbc505777d91cdcdf4 100644
--- a/src/OpenFOAM/global/argList/argList.H
+++ b/src/OpenFOAM/global/argList/argList.H
@@ -124,7 +124,7 @@ namespace Foam
 
 class argList
 {
-    // Private data
+    // Private Data
 
         //- Track if command arguments are mandatory/optional
         static bool argsMandatory_;
@@ -383,7 +383,7 @@ public:
         inline T opt(const word& optName) const;
 
         //- Get a value from the named option if present, or return default.
-        //  Identical to lookupOrDefault().
+        //  Identical to getOrDefault().
         template<class T>
         inline T opt(const word& optName, const T& deflt) const;
 
@@ -405,7 +405,7 @@ public:
 
         //- Get a value from the named option if present, or return default.
         template<class T>
-        inline T lookupOrDefault
+        inline T getOrDefault
         (
             const word& optName,
             const T& deflt
@@ -590,6 +590,16 @@ public:
         inline const string& operator[](const word& optName) const;
 
 
+    // Housekeeping
+
+        //- Get a value from the named option if present, or return default.
+        template<class T>
+        T lookupOrDefault(const word& optName, const T& deflt) const
+        {
+            return getOrDefault<T>(optName, deflt);
+        }
+
+
     // Older style access (including 1712 release)
 
     #ifdef Foam_argList_1712
@@ -598,7 +608,8 @@ public:
         //  Index 1 is the first (non-option) argument.
         //  \deprecated(2018-08) - use get() method
         template<class T>
-        inline T read(const label index) const
+        T FOAM_DEPRECATED_FOR(2018-08, "get() method")
+        read(const label index) const
         {
             return this->get<T>(index);
         }
@@ -607,21 +618,24 @@ public:
         //  Index 1 is the first (non-option) argument.
         //  \deprecated(2018-01) - use get() method
         template<class T>
-        inline T argRead(const label index) const
+        T FOAM_DEPRECATED_FOR(2018-01, "get() method")
+        argRead(const label index) const
         {
             return this->get<T>(index);
         }
 
         //- Deprecated(2018-01) return true if the named option is found
         //  \deprecated(2018-01) - use found() method
-        inline bool optionFound(const word& optName) const
+        bool FOAM_DEPRECATED_FOR(2018-01, "found() method")
+        optionFound(const word& optName) const
         {
             return found(optName);
         }
 
         //- Deprecated(2018-01) return an input stream from the named option
         //  \deprecated(2018-01) - use lookup() method
-        inline ITstream optionLookup(const word& optName) const
+        ITstream FOAM_DEPRECATED_FOR(2018-01, "lookup() method")
+        optionLookup(const word& optName) const
         {
             return lookup(optName);
         }
@@ -629,7 +643,8 @@ public:
         //- Deprecated(2018-01) read a value from the named option
         //  \deprecated(2018-01) - use opt() method
         template<class T>
-        inline T optionRead(const word& optName) const
+        T FOAM_DEPRECATED_FOR(2018-01, "opt() method")
+        optionRead(const word& optName) const
         {
             return opt<T>(optName);
         }
@@ -638,7 +653,8 @@ public:
         //  Return true if the named option was found.
         //  \deprecated(2018-01) - use readIfPresent() method
         template<class T>
-        inline bool optionReadIfPresent
+        bool FOAM_DEPRECATED_FOR(2018-01, "readIfPresent() method")
+        optionReadIfPresent
         (
             const word& optName,
             T& val
@@ -652,7 +668,8 @@ public:
         //  use the supplied default and return false.
         //  \deprecated(2018-01) - use readIfPresent() method
         template<class T>
-        inline bool optionReadIfPresent
+        bool FOAM_DEPRECATED_FOR(2018-01, "readIfPresent() method")
+        optionReadIfPresent
         (
             const word& optName,
             T& val,
@@ -664,21 +681,23 @@ public:
 
         //- Deprecated(2018-01) read a value from the named option if present.
         //  Return supplied default otherwise.
-        //  \deprecated(2018-01) - use lookupOrDefault() method
+        //  \deprecated(2018-01) - use getOrDefault() method
         template<class T>
-        inline T optionLookupOrDefault
+        T FOAM_DEPRECATED_FOR(2018-01, "getOrDefault() method")
+        optionLookupOrDefault
         (
             const word& optName,
             const T& deflt
         ) const
         {
-            return lookupOrDefault<T>(optName, deflt);
+            return getOrDefault<T>(optName, deflt);
         }
 
         //- Deprecated(2018-01) read a List of values from the named option
         //  \deprecated(2018-01) - use getList() method
         template<class T>
-        inline List<T> optionReadList(const word& optName) const
+        List<T> FOAM_DEPRECATED_FOR(2018-01, "getList() method")
+        optionReadList(const word& optName) const
         {
             return this->getList<T>(optName);
         }
diff --git a/src/OpenFOAM/global/argList/argListI.H b/src/OpenFOAM/global/argList/argListI.H
index 4186d6e4af8e8b4652b0ba43b95acac01c5f9f32..54e4ac9d8e25c7062eb4a356248471d777d5e6b5 100644
--- a/src/OpenFOAM/global/argList/argListI.H
+++ b/src/OpenFOAM/global/argList/argListI.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2017-2018 OpenCFD Ltd.
+    \\  /    A nd           | Copyright (C) 2017-2019 OpenCFD Ltd.
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
                             | Copyright (C) 2011-2013 OpenFOAM Foundation
@@ -316,7 +316,7 @@ inline bool Foam::argList::readIfPresent
 
 
 template<class T>
-inline T Foam::argList::lookupOrDefault
+inline T Foam::argList::getOrDefault
 (
     const word& optName,
     const T& deflt
diff --git a/src/OpenFOAM/global/global.Cver b/src/OpenFOAM/global/global.Cver
index cf03f6aad4d8ec80035e6e555d35e6efb1ac5ad1..a17064c5fb3902be40b2081306cf39666658987b 100644
--- a/src/OpenFOAM/global/global.Cver
+++ b/src/OpenFOAM/global/global.Cver
@@ -98,6 +98,9 @@ const std::string Foam::foamVersion::buildArch
 #endif
     ";label="  + std::to_string(8*sizeof(Foam::label))
   + ";scalar=" + std::to_string(8*sizeof(Foam::scalar))
+#ifdef WM_SPDP
+  + ";solveScalar=" + std::to_string(8*sizeof(Foam::solveScalar))
+#endif
 );
 
 
diff --git a/src/OpenFOAM/include/OSspecific.H b/src/OpenFOAM/include/OSspecific.H
index cd70db35e8faf868df4364d71bffcfc85effd002..4e9e0ae4c8f1f8d2df4cc1be97c57d05f801b847 100644
--- a/src/OpenFOAM/include/OSspecific.H
+++ b/src/OpenFOAM/include/OSspecific.H
@@ -253,8 +253,14 @@ int system(const UList<string>& command, const bool bg = false);
 int system(const CStringList& command, const bool bg = false);
 
 //- Open a shared library and return handle to library.
-//  Print error message if library cannot be loaded (suppress with check=true)
-void* dlOpen(const fileName& lib, const bool check = true);
+//  A leading "lib" and ".so" suffix are added silently as required.
+//  Prints warning if a library cannot be loaded (suppress with check=false)
+void* dlOpen(const fileName& libName, const bool check=true);
+
+//- Open shared libraries and return number of libraries loaded.
+//  A leading "lib" and ".so" suffix are added silently as required.
+//  Prints warning if a library cannot be loaded (suppress with check=false)
+label dlOpen(std::initializer_list<fileName> libNames, const bool check=true);
 
 //- Close a dlopened library using handle. Return true if successful
 bool dlClose(void* handle);
diff --git a/src/OpenFOAM/include/foamDlOpenLibs.H b/src/OpenFOAM/include/foamDlOpenLibs.H
new file mode 100644
index 0000000000000000000000000000000000000000..27ee219943d9adcbf568f62f2fce0a111d87526c
--- /dev/null
+++ b/src/OpenFOAM/include/foamDlOpenLibs.H
@@ -0,0 +1,12 @@
+// Force dlOpen of FOAM_DLOPEN_LIBS,
+// which is a comma-separated list of quoted library names
+// (eg, "finiteVolume","fvOptions","meshTools")
+//
+// Principally for Windows applications where library loading may otherwise
+// be incomplete.
+
+#ifdef FOAM_DLOPEN_LIBS
+
+Foam::dlOpen({ FOAM_DLOPEN_LIBS }, false);  // Silent on errors
+
+#endif
diff --git a/src/OpenFOAM/include/setRootCase.H b/src/OpenFOAM/include/setRootCase.H
index 6205697d9549c6a164b86d20560c72e82d53c079..e90a7410c690c65f9f58dd1126ae0cb5fea5d802 100644
--- a/src/OpenFOAM/include/setRootCase.H
+++ b/src/OpenFOAM/include/setRootCase.H
@@ -15,3 +15,6 @@ if (!args.checkRootCase())
 //  {
 //      Foam::FatalError.exit();
 //  }
+
+// Force dlOpen of FOAM_DLOPEN_LIBS (principally for Windows applications)
+#include "foamDlOpenLibs.H"
diff --git a/src/OpenFOAM/interpolations/interpolationWeights/interpolationWeights/interpolationWeights.C b/src/OpenFOAM/interpolations/interpolationWeights/interpolationWeights/interpolationWeights.C
index afb3f343fbf7e02160460aae36643396c3a9f878..cb6fa4db59950ca09d27f55a8771affed5607c1e 100644
--- a/src/OpenFOAM/interpolations/interpolationWeights/interpolationWeights/interpolationWeights.C
+++ b/src/OpenFOAM/interpolations/interpolationWeights/interpolationWeights/interpolationWeights.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-2015 OpenFOAM Foundation
@@ -33,9 +33,9 @@ License
 
 namespace Foam
 {
-defineTypeNameAndDebug(interpolationWeights, 0);
-defineRunTimeSelectionTable(interpolationWeights, word);
-}
+    defineTypeNameAndDebug(interpolationWeights, 0);
+    defineRunTimeSelectionTable(interpolationWeights, word);
+} // End namespace Foam
 
 
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
@@ -77,10 +77,4 @@ Foam::autoPtr<Foam::interpolationWeights> Foam::interpolationWeights::New
 }
 
 
-// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
-
-Foam::interpolationWeights::~interpolationWeights()
-{}
-
-
 // ************************************************************************* //
diff --git a/src/OpenFOAM/interpolations/interpolationWeights/interpolationWeights/interpolationWeights.H b/src/OpenFOAM/interpolations/interpolationWeights/interpolationWeights/interpolationWeights.H
index e3a428a492e812f60e62505f441ec382a4ee3f06..3a43a12306b0aeaa4e3035401d9363442607c38e 100644
--- a/src/OpenFOAM/interpolations/interpolationWeights/interpolationWeights/interpolationWeights.H
+++ b/src/OpenFOAM/interpolations/interpolationWeights/interpolationWeights/interpolationWeights.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
@@ -57,10 +57,14 @@ class objectRegistry;
 
 class interpolationWeights
 {
+protected:
+
+    // Protected Data
+
+        const scalarField& samples_;
 
-private:
 
-    // Private Member Functions
+    // Protected Member Functions
 
         //- No copy construct
         interpolationWeights(const interpolationWeights&) = delete;
@@ -68,9 +72,6 @@ private:
         //- No copy assignment
         void operator=(const interpolationWeights&) = delete;
 
-protected:
-
-        const scalarField& samples_;
 
 public:
 
@@ -95,7 +96,7 @@ public:
     // Constructors
 
         //- Construct from components
-        interpolationWeights(const scalarField& samples);
+        explicit interpolationWeights(const scalarField& samples);
 
 
     // Selectors
@@ -109,7 +110,7 @@ public:
 
 
     //- Destructor
-    virtual ~interpolationWeights();
+    virtual ~interpolationWeights() = default;
 
 
     // Member Functions
diff --git a/src/OpenFOAM/interpolations/interpolationWeights/interpolationWeights/interpolationWeightsTemplates.C b/src/OpenFOAM/interpolations/interpolationWeights/interpolationWeights/interpolationWeightsTemplates.C
index aaab57f8670406431cdb17d7a3ac5a7228801c0a..301faeee07e8e0eaeab724db65bcb85520ba339d 100644
--- a/src/OpenFOAM/interpolations/interpolationWeights/interpolationWeights/interpolationWeightsTemplates.C
+++ b/src/OpenFOAM/interpolations/interpolationWeights/interpolationWeights/interpolationWeightsTemplates.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
@@ -26,15 +26,7 @@ License
 \*---------------------------------------------------------------------------*/
 
 #include "interpolationWeights.H"
-#include "ListOps.H"
-#include "IOobject.H"
-#include "HashSet.H"
-#include "objectRegistry.H"
-
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
-namespace Foam
-{
+#include "products.H"
 
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
@@ -56,24 +48,19 @@ Foam::interpolationWeights::weightedSum
         typename ListType2::value_type
     >::type returnType;
 
-    if (f1.size())
+    const label len = f1.size();
+    if (len)
     {
         returnType SumProd = f1[0]*f2[0];
-        for (label i = 1; i < f1.size(); ++i)
+        for (label i = 1; i < len; ++i)
         {
             SumProd += f1[i]*f2[i];
         }
         return SumProd;
     }
-    else
-    {
-        return Zero;
-    }
-}
 
+    return Zero;
+}
 
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
-} // End namespace Foam
 
 // ************************************************************************* //
diff --git a/src/OpenFOAM/interpolations/interpolationWeights/linearInterpolationWeights/linearInterpolationWeights.C b/src/OpenFOAM/interpolations/interpolationWeights/linearInterpolationWeights/linearInterpolationWeights.C
index b9a2586bf478452c2a09a64a6352d91f72edc0cd..7c482631c265f5b2f13cae579cf06cd2c19c890d 100644
--- a/src/OpenFOAM/interpolations/interpolationWeights/linearInterpolationWeights/linearInterpolationWeights.C
+++ b/src/OpenFOAM/interpolations/interpolationWeights/linearInterpolationWeights/linearInterpolationWeights.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-2015 OpenFOAM Foundation
@@ -30,25 +30,23 @@ License
 #include "ListOps.H"
 #include "Pair.H"
 
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
 
 namespace Foam
 {
-
-// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
-
-defineTypeNameAndDebug(linearInterpolationWeights, 0);
-addToRunTimeSelectionTable
-(
-    interpolationWeights,
-    linearInterpolationWeights,
-    word
-);
+    defineTypeNameAndDebug(linearInterpolationWeights, 0);
+    addToRunTimeSelectionTable
+    (
+        interpolationWeights,
+        linearInterpolationWeights,
+        word
+    );
+} // End namespace Foam
 
 
 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
 
-Foam::Pair<Foam::scalar> linearInterpolationWeights::integrationWeights
+Foam::Pair<Foam::scalar> Foam::linearInterpolationWeights::integrationWeights
 (
     const label i,
     const scalar t
@@ -56,7 +54,7 @@ Foam::Pair<Foam::scalar> linearInterpolationWeights::integrationWeights
 {
     // t is in range samples_[i] .. samples_[i+1]
 
-    scalar s = (t-samples_[i])/(samples_[i+1]-samples_[i]);
+    const scalar s = (t-samples_[i])/(samples_[i+1]-samples_[i]);
 
     if (s < -SMALL || s > 1+SMALL)
     {
@@ -66,7 +64,7 @@ Foam::Pair<Foam::scalar> linearInterpolationWeights::integrationWeights
             << exit(FatalError);
     }
 
-    scalar d = samples_[i+1]-t;
+    const scalar d = samples_[i+1]-t;
 
     return Pair<scalar>(d*0.5*(1-s), d*0.5*(1+s));
 }
@@ -74,7 +72,7 @@ Foam::Pair<Foam::scalar> linearInterpolationWeights::integrationWeights
 
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
-linearInterpolationWeights::linearInterpolationWeights
+Foam::linearInterpolationWeights::linearInterpolationWeights
 (
     const scalarField& samples
 )
@@ -86,7 +84,7 @@ linearInterpolationWeights::linearInterpolationWeights
 
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
-bool linearInterpolationWeights::valueWeights
+bool Foam::linearInterpolationWeights::valueWeights
 (
     const scalar t,
     labelList& indices,
@@ -153,7 +151,7 @@ bool linearInterpolationWeights::valueWeights
 }
 
 
-bool linearInterpolationWeights::integrationWeights
+bool Foam::linearInterpolationWeights::integrationWeights
 (
     const scalar t1,
     const scalar t2,
@@ -172,9 +170,10 @@ bool linearInterpolationWeights::integrationWeights
     // Currently no fancy logic on cached index like in value
 
     //- Find lower or equal index
-    label i1 = findLower(samples_, t1, 0, lessEqOp<scalar>());
+    const label i1 = findLower(samples_, t1, 0, lessEqOp<scalar>());
+
     //- Find lower index
-    label i2 = findLower(samples_, t2);
+    const label i2 = findLower(samples_, t2);
 
     // For now just fail if any outside table
     if (i1 == -1 || i2 == samples_.size()-1)
@@ -185,7 +184,7 @@ bool linearInterpolationWeights::integrationWeights
             << " t1:" << t1 << " t2:" << t2 << exit(FatalError);
     }
 
-    label nIndices = i2-i1+2;
+    const label nIndices = i2-i1+2;
 
 
     // Determine if indices already correct
@@ -218,7 +217,7 @@ bool linearInterpolationWeights::integrationWeights
     // Sum from i1+1 to i2+1
     for (label i = i1+1; i <= i2; i++)
     {
-        scalar d = samples_[i+1]-samples_[i];
+        const scalar d = samples_[i+1]-samples_[i];
         indices[i-i1] = i;
         weights[i-i1] += 0.5*d;
         indices[i+1-i1] = i+1;
@@ -227,19 +226,19 @@ bool linearInterpolationWeights::integrationWeights
 
     // Add from i1 to t1
     {
-        Pair<scalar> i1Tot1 = integrationWeights(i1, t1);
+        const Pair<scalar> i1Tot1 = integrationWeights(i1, t1);
         indices[0] = i1;
-        weights[0] += i1Tot1.first();
         indices[1] = i1+1;
+        weights[0] += i1Tot1.first();
         weights[1] += i1Tot1.second();
     }
 
     // Subtract from t2 to i2+1
     {
-        Pair<scalar> wghts = integrationWeights(i2, t2);
+        const Pair<scalar> wghts = integrationWeights(i2, t2);
         indices[i2-i1] = i2;
-        weights[i2-i1] += -wghts.first();
         indices[i2-i1+1] = i2+1;
+        weights[i2-i1] += -wghts.first();
         weights[i2-i1+1] += -wghts.second();
     }
 
@@ -247,8 +246,4 @@ bool linearInterpolationWeights::integrationWeights
 }
 
 
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
-} // End namespace Foam
-
 // ************************************************************************* //
diff --git a/src/OpenFOAM/interpolations/interpolationWeights/linearInterpolationWeights/linearInterpolationWeights.H b/src/OpenFOAM/interpolations/interpolationWeights/linearInterpolationWeights/linearInterpolationWeights.H
index 3d25aaccceaa65d85f1343977ef2cb1450471a52..6de0a21d181f7645751c676fb0202f0a66d9eca0 100644
--- a/src/OpenFOAM/interpolations/interpolationWeights/linearInterpolationWeights/linearInterpolationWeights.H
+++ b/src/OpenFOAM/interpolations/interpolationWeights/linearInterpolationWeights/linearInterpolationWeights.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 OpenFOAM Foundation
@@ -51,47 +51,39 @@ class linearInterpolationWeights
 :
     public interpolationWeights
 {
-
-private:
-
-    // Private data
+    // Private Data
 
         //- Cached index in samples from previous invocation
         mutable label index_;
 
+
     // Private Member Functions
 
         //- Get weights of i and i+1 to calculate integration from t to
-        //  samples_[i+1]
-        Pair<scalar> integrationWeights
-        (
-            const label i,
-            const scalar t
-        ) const;
+        //- samples_[i+1]
+        Pair<scalar> integrationWeights(const label i, const scalar t) const;
+
 
 public:
 
     //- Runtime type information
     TypeName("linear");
 
+
     // Constructors
 
         //- Construct from components
-        linearInterpolationWeights
-        (
-            const scalarField& samples
-        );
+        explicit linearInterpolationWeights(const scalarField& samples);
 
 
     //- Destructor
-    virtual ~linearInterpolationWeights()
-    {}
+    virtual ~linearInterpolationWeights() = default;
 
 
     // Member Functions
 
         //- Calculate weights and indices to calculate t from samples.
-        //  Returns true if indices changed.
+        //  \return true if indices changed.
         virtual bool valueWeights
         (
             const scalar t,
@@ -100,7 +92,8 @@ public:
         ) const;
 
         //- Calculate weights and indices to calculate integrand of t1..t2
-        //  from samples. Returns true if indices changed.
+        //- from samples.
+        //  \return true if indices changed.
         virtual bool integrationWeights
         (
             const scalar t1,
diff --git a/src/OpenFOAM/interpolations/interpolationWeights/splineInterpolationWeights/splineInterpolationWeights.C b/src/OpenFOAM/interpolations/interpolationWeights/splineInterpolationWeights/splineInterpolationWeights.C
index 5d2bb88d1b874f6554fc6f60048b7083ec47e79b..060aa33cc536a02c1964988ef979c6a1201d96b5 100644
--- a/src/OpenFOAM/interpolations/interpolationWeights/splineInterpolationWeights/splineInterpolationWeights.C
+++ b/src/OpenFOAM/interpolations/interpolationWeights/splineInterpolationWeights/splineInterpolationWeights.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-2015 OpenFOAM Foundation
@@ -30,25 +30,23 @@ License
 #include "ListOps.H"
 #include "linearInterpolationWeights.H"
 
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
 
 namespace Foam
 {
-
-// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
-
-defineTypeNameAndDebug(splineInterpolationWeights, 0);
-addToRunTimeSelectionTable
-(
-    interpolationWeights,
-    splineInterpolationWeights,
-    word
-);
+    defineTypeNameAndDebug(splineInterpolationWeights, 0);
+    addToRunTimeSelectionTable
+    (
+        interpolationWeights,
+        splineInterpolationWeights,
+        word
+    );
+} // End namespace Foam
 
 
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
-splineInterpolationWeights::splineInterpolationWeights
+Foam::splineInterpolationWeights::splineInterpolationWeights
 (
     const scalarField& samples,
     const bool checkEqualDistance
@@ -80,7 +78,7 @@ splineInterpolationWeights::splineInterpolationWeights
 
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
-bool splineInterpolationWeights::valueWeights
+bool Foam::splineInterpolationWeights::valueWeights
 (
     const scalar t,
     labelList& indices,
@@ -220,8 +218,4 @@ bool splineInterpolationWeights::valueWeights
 }
 
 
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
-} // End namespace Foam
-
 // ************************************************************************* //
diff --git a/src/OpenFOAM/interpolations/interpolationWeights/splineInterpolationWeights/splineInterpolationWeights.H b/src/OpenFOAM/interpolations/interpolationWeights/splineInterpolationWeights/splineInterpolationWeights.H
index 0c08b9e9a37e41f2ea744ac32cc723f1651527ae..e65c706402f6682b46caed4d4c7bd4f3fdd270f1 100644
--- a/src/OpenFOAM/interpolations/interpolationWeights/splineInterpolationWeights/splineInterpolationWeights.H
+++ b/src/OpenFOAM/interpolations/interpolationWeights/splineInterpolationWeights/splineInterpolationWeights.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-2015 OpenFOAM Foundation
@@ -52,24 +52,23 @@ class splineInterpolationWeights
 :
     public interpolationWeights
 {
-
-private:
-
-    // Private data
+    // Private Data
 
         //- Cached index in samples from previous invocation
         mutable label index_;
 
+
 public:
 
     //- Runtime type information
     TypeName("spline");
 
+
     // Constructors
 
         //- Construct from components. By default make sure samples are
         //  equidistant.
-        splineInterpolationWeights
+        explicit splineInterpolationWeights
         (
             const scalarField& samples,
             const bool checkEqualDistance = true
@@ -77,14 +76,13 @@ public:
 
 
     //- Destructor
-    virtual ~splineInterpolationWeights()
-    {}
+    virtual ~splineInterpolationWeights() = default;
 
 
     // Member Functions
 
         //- Calculate weights and indices to calculate t from samples.
-        //  Returns true if indices changed.
+        //  \return true if indices changed.
         virtual bool valueWeights
         (
             const scalar t,
@@ -93,7 +91,8 @@ public:
         ) const;
 
         //- Calculate weights and indices to calculate integrand of t1..t2
-        //  from samples. Returns true if indices changed.
+        //- from samples.
+        //  \return true if indices changed.
         virtual bool integrationWeights
         (
             const scalar t1,
diff --git a/src/OpenFOAM/matrices/DiagonalMatrix/DiagonalMatrix.C b/src/OpenFOAM/matrices/DiagonalMatrix/DiagonalMatrix.C
index 6e4dad4b56fea3a3eb7f7acb02ad57d03e972b42..f05aede75013a069d48f42e045469ea049cd25b5 100644
--- a/src/OpenFOAM/matrices/DiagonalMatrix/DiagonalMatrix.C
+++ b/src/OpenFOAM/matrices/DiagonalMatrix/DiagonalMatrix.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) 2011-2016 OpenFOAM Foundation
@@ -37,45 +37,54 @@ inline Foam::DiagonalMatrix<Type>::DiagonalMatrix()
 
 
 template<class Type>
-template<class Form>
-Foam::DiagonalMatrix<Type>::DiagonalMatrix(const Matrix<Form, Type>& a)
+Foam::DiagonalMatrix<Type>::DiagonalMatrix(const label n)
 :
-    List<Type>(min(a.m(), a.n()))
-{
-    forAll(*this, i)
-    {
-        this->operator[](i) = a(i, i);
-    }
-}
+    List<Type>(n)
+{}
 
 
 template<class Type>
-Foam::DiagonalMatrix<Type>::DiagonalMatrix(const label size)
+Foam::DiagonalMatrix<Type>::DiagonalMatrix(const label n, const zero)
 :
-    List<Type>(size)
+    List<Type>(n, Zero)
 {}
 
 
 template<class Type>
-Foam::DiagonalMatrix<Type>::DiagonalMatrix(const label size, const Type& val)
+Foam::DiagonalMatrix<Type>::DiagonalMatrix(const label n, const Type& val)
 :
-    List<Type>(size, val)
+    List<Type>(n, val)
 {}
 
 
+template<class Type>
+template<class Form>
+Foam::DiagonalMatrix<Type>::DiagonalMatrix(const Matrix<Form, Type>& mat)
+:
+    List<Type>(min(mat.m(), mat.n()))
+{
+    label i = 0;
+
+    for (Type& val : *this)
+    {
+        val = mat(i, i);
+        ++i;
+    }
+}
+
+
 template<class Type>
 Foam::DiagonalMatrix<Type>& Foam::DiagonalMatrix<Type>::invert()
 {
-    forAll(*this, i)
+    for (Type& val : *this)
     {
-        Type x = this->operator[](i);
-        if (mag(x) < VSMALL)
+        if (mag(val) < VSMALL)
         {
-            this->operator[](i) = Type(0);
+            val = Zero;
         }
         else
         {
-            this->operator[](i) = Type(1)/x;
+            val = Type(1)/val;
         }
     }
 
@@ -84,21 +93,24 @@ Foam::DiagonalMatrix<Type>& Foam::DiagonalMatrix<Type>::invert()
 
 
 template<class Type>
-Foam::DiagonalMatrix<Type> Foam::inv(const DiagonalMatrix<Type>& A)
+Foam::DiagonalMatrix<Type> Foam::inv(const DiagonalMatrix<Type>& mat)
 {
-    DiagonalMatrix<Type> Ainv = A;
+    DiagonalMatrix<Type> Ainv(mat.size());
 
-    forAll(A, i)
+    Type* iter = Ainv.begin();
+
+    for (const Type& val : mat)
     {
-        Type x = A[i];
-        if (mag(x) < VSMALL)
+        if (mag(val) < VSMALL)
         {
-            Ainv[i] = Type(0);
+            *iter = Zero;
         }
         else
         {
-            Ainv[i] = Type(1)/x;
+            *iter = Type(1)/val;
         }
+
+        ++iter;
     }
 
     return Ainv;
diff --git a/src/OpenFOAM/matrices/DiagonalMatrix/DiagonalMatrix.H b/src/OpenFOAM/matrices/DiagonalMatrix/DiagonalMatrix.H
index 2521693d1ff835196c229bbf460a27a333f5c9c7..a7ba834b9af38d73fa2758649351e7f950e33d3f 100644
--- a/src/OpenFOAM/matrices/DiagonalMatrix/DiagonalMatrix.H
+++ b/src/OpenFOAM/matrices/DiagonalMatrix/DiagonalMatrix.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) 2011-2016 OpenFOAM Foundation
@@ -27,8 +27,7 @@ Class
     Foam::DiagonalMatrix
 
 Description
-    DiagonalMatrix<Type> is a 2D diagonal matrix of objects
-    of type Type, size nxn
+    A 2D diagonal matrix of objects of type \<Type\>, size (N x N)
 
 SourceFiles
     DiagonalMatrix.C
@@ -45,12 +44,11 @@ SourceFiles
 namespace Foam
 {
 
-// * * * * * *  * * * * * * Class Forward declaration  * * * * * * * * * * * //
-
+// Forward Declarations
 template<class Form, class Type> class Matrix;
 
 /*---------------------------------------------------------------------------*\
-                           Class DiagonalMatrix Declaration
+                       Class DiagonalMatrix Declaration
 \*---------------------------------------------------------------------------*/
 
 template<class Type>
@@ -62,24 +60,29 @@ public:
 
     // Constructors
 
-        //- Null constructor.
+        //- Construct null.
         DiagonalMatrix<Type>();
 
-        //- Construct from diagonal component of a Matrix
-        template<class Form>
-        DiagonalMatrix<Type>(const Matrix<Form, Type>&);
-
         //- Construct empty from size
-        DiagonalMatrix<Type>(const label size);
+        explicit DiagonalMatrix<Type>(const label n);
+
+        //- Construct from size
+        //- initializing all elements to the given value
+        DiagonalMatrix<Type>(const label n, const zero);
 
         //- Construct from size and a value
-        DiagonalMatrix<Type>(const label, const Type&);
+        DiagonalMatrix<Type>(const label n, const Type& val);
+
+        //- Construct from the diagonal of a Matrix
+        template<class Form>
+        DiagonalMatrix<Type>(const Matrix<Form, Type>& mat);
 
 
-    // Member functions
+    // Member Functions
 
         //- Invert the diagonal matrix and return itself
         DiagonalMatrix<Type>& invert();
+
 };
 
 
@@ -87,7 +90,7 @@ public:
 
 //- Return the diagonal Matrix inverse
 template<class Type>
-DiagonalMatrix<Type> inv(const DiagonalMatrix<Type>&);
+DiagonalMatrix<Type> inv(const DiagonalMatrix<Type>& mat);
 
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
diff --git a/src/OpenFOAM/matrices/LLTMatrix/LLTMatrix.C b/src/OpenFOAM/matrices/LLTMatrix/LLTMatrix.C
index c18bbe5c519179d51dc523c6ef64536f0d02084d..9f0422ca432d826f398cfff29a5fb435a45c59f5 100644
--- a/src/OpenFOAM/matrices/LLTMatrix/LLTMatrix.C
+++ b/src/OpenFOAM/matrices/LLTMatrix/LLTMatrix.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) 2016 OpenFOAM Foundation
@@ -35,27 +35,27 @@ Foam::LLTMatrix<Type>::LLTMatrix()
 
 
 template<class Type>
-Foam::LLTMatrix<Type>::LLTMatrix(const SquareMatrix<Type>& M)
+Foam::LLTMatrix<Type>::LLTMatrix(const SquareMatrix<Type>& mat)
 {
-    decompose(M);
+    decompose(mat);
 }
 
 
 // * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * * //
 
 template<class Type>
-void Foam::LLTMatrix<Type>::decompose(const SquareMatrix<Type>& M)
+void Foam::LLTMatrix<Type>::decompose(const SquareMatrix<Type>& mat)
 {
     SquareMatrix<Type>& LLT = *this;
 
     // Initialize the LLT decomposition matrix to M
-    LLT = M;
+    LLT = mat;
 
     const label m = LLT.m();
 
-    for (label i=0; i<m; i++)
+    for (label i = 0; i < m; ++i)
     {
-        for (label j=0; j<m; j++)
+        for (label j = 0; j < m; ++j)
         {
             if (j > i)
             {
@@ -65,7 +65,7 @@ void Foam::LLTMatrix<Type>::decompose(const SquareMatrix<Type>& M)
 
             Type sum = LLT(i, j);
 
-            for (label k=0; k<j; k++)
+            for (label k = 0; k < j; ++k)
             {
                 sum -= LLT(i, k)*LLT(j, k);
             }
@@ -91,13 +91,14 @@ void Foam::LLTMatrix<Type>::decompose(const SquareMatrix<Type>& M)
 
 
 template<class Type>
-void Foam::LLTMatrix<Type>::solve
+template<template<typename> class ListContainer>
+void Foam::LLTMatrix<Type>::solveImpl
 (
-    Field<Type>& x,
-    const Field<Type>& source
+    List<Type>& x,
+    const ListContainer<Type>& source
 ) const
 {
-    // If x and source are different initialize x = source
+    // If x and source are different, copy initialize x = source
     if (&x != &source)
     {
         x = source;
@@ -106,11 +107,11 @@ void Foam::LLTMatrix<Type>::solve
     const SquareMatrix<Type>& LLT = *this;
     const label m = LLT.m();
 
-    for (label i=0; i<m; i++)
+    for (label i = 0; i < m; ++i)
     {
         Type sum = source[i];
 
-        for (label j=0; j<i; j++)
+        for (label j = 0; j < i; ++j)
         {
             sum = sum - LLT(i, j)*x[j];
         }
@@ -118,33 +119,68 @@ void Foam::LLTMatrix<Type>::solve
         x[i] = sum/LLT(i, i);
     }
 
-    for (int i=m - 1; i >= 0; i--)
+    for (label i = m - 1; i >= 0; --i)
     {
         Type sum = x[i];
 
-        for (label j=i + 1; j<m; j++)
+        for (label j = i + 1; j < m; ++j)
         {
             sum = sum - LLT(j, i)*x[j];
         }
 
         x[i] = sum/LLT(i, i);
     }
+}
+
+
+template<class Type>
+void Foam::LLTMatrix<Type>::solve
+(
+    List<Type>& x,
+    const UList<Type>& source
+) const
+{
+    solveImpl(x, source);
+}
+
+
+template<class Type>
+template<class Addr>
+void Foam::LLTMatrix<Type>::solve
+(
+    List<Type>& x,
+    const IndirectListBase<Type, Addr>& source
+) const
+{
+    solveImpl(x, source);
+}
+
+template<class Type>
+Foam::tmp<Foam::Field<Type>> Foam::LLTMatrix<Type>::solve
+(
+    const UList<Type>& source
+) const
+{
+    auto tresult(tmp<Field<Type>>::New(source.size()));
+
+    solve(tresult.ref(), source);
 
+    return tresult;
 }
 
 
 template<class Type>
+template<class Addr>
 Foam::tmp<Foam::Field<Type>> Foam::LLTMatrix<Type>::solve
 (
-    const Field<Type>& source
+    const IndirectListBase<Type, Addr>& source
 ) const
 {
-    tmp<Field<Type>> tx(new Field<Type>(this->m()));
-    Field<Type>& x = tx.ref();
+    auto tresult(tmp<Field<Type>>::New(source.size()));
 
-    solve(x, source);
+    solve(tresult.ref(), source);
 
-    return tx;
+    return tresult;
 }
 
 
diff --git a/src/OpenFOAM/matrices/LLTMatrix/LLTMatrix.H b/src/OpenFOAM/matrices/LLTMatrix/LLTMatrix.H
index 80d42c23b22e20143bdca8b36fd2ae8adc7c3ebc..ac7753ddd6b0e32557e59f49efb6bf9a2f20fecb 100644
--- a/src/OpenFOAM/matrices/LLTMatrix/LLTMatrix.H
+++ b/src/OpenFOAM/matrices/LLTMatrix/LLTMatrix.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) 2016 OpenFOAM Foundation
@@ -59,6 +59,19 @@ class LLTMatrix
     public SquareMatrix<Type>
 {
 
+    // Private Member Functions
+
+        //- Solve the linear system with the given source
+        //- and return the solution in x
+        //  This function may be called with the same field for x and source.
+        template<template<typename> class ListContainer>
+        void solveImpl
+        (
+            List<Type>& x,
+            const ListContainer<Type>& source
+        ) const;
+
+
 public:
 
     // Constructors
@@ -66,23 +79,48 @@ public:
         //- Construct null
         LLTMatrix();
 
-        //- Construct from a square matrix and perform the decomposition
-        LLTMatrix(const SquareMatrix<Type>& M);
+        //- Construct and perform the decomposition on input square matrix
+        LLTMatrix(const SquareMatrix<Type>& mat);
 
 
     // Member Functions
 
-        //- Perform the Cholesky decomposition of the matrix
-        void decompose(const SquareMatrix<Type>& M);
+        //- Copy matrix and perform Cholesky decomposition
+        void decompose(const SquareMatrix<Type>& mat);
 
         //- Solve the linear system with the given source
-        //  and returning the solution in the Field argument x.
+        //- and return the solution in the argument x.
         //  This function may be called with the same field for x and source.
-        void solve(Field<Type>& x, const Field<Type>& source) const;
+        void solve
+        (
+            List<Type>& x,
+            const UList<Type>& source
+        ) const;
+
+        //- Solve the linear system with the given source
+        //- and return the solution in the argument x.
+        //  This function may be called with the same field for x and source.
+        template<class Addr>
+        void solve
+        (
+            List<Type>& x,
+            const IndirectListBase<Type, Addr>& source
+        ) const;
+
+        //- Solve the linear system with the given source
+        //- return the solution
+        tmp<Field<Type>> solve
+        (
+            const UList<Type>& source
+        ) const;
 
         //- Solve the linear system with the given source
-        //  returning the solution
-        tmp<Field<Type>> solve(const Field<Type>& source) const;
+        //- return the solution
+        template<class Addr>
+        tmp<Field<Type>> solve
+        (
+            const IndirectListBase<Type, Addr>& source
+        ) const;
 };
 
 
diff --git a/src/OpenFOAM/matrices/LUscalarMatrix/LUscalarMatrix.C b/src/OpenFOAM/matrices/LUscalarMatrix/LUscalarMatrix.C
index 0c0c6b1f1bec72aad4fea712ca98ec56d068a6fd..8c39029e4e5bc25b369fc7f5564598c18039e288 100644
--- a/src/OpenFOAM/matrices/LUscalarMatrix/LUscalarMatrix.C
+++ b/src/OpenFOAM/matrices/LUscalarMatrix/LUscalarMatrix.C
@@ -145,7 +145,7 @@ Foam::LUscalarMatrix::LUscalarMatrix
     else
     {
         label nCells = ldum.lduAddr().size();
-        scalarSquareMatrix m(nCells, 0.0);
+        scalarSquareMatrix m(nCells, Zero);
         transfer(m);
         convert(ldum, interfaceCoeffs, interfaces);
     }
diff --git a/src/OpenFOAM/matrices/LUscalarMatrix/LUscalarMatrix.H b/src/OpenFOAM/matrices/LUscalarMatrix/LUscalarMatrix.H
index 006ec01f6b25e97a3241cf0bcae6f063a7385c2a..10b2e41b68c8868455524c54fa9699618ad2351d 100644
--- a/src/OpenFOAM/matrices/LUscalarMatrix/LUscalarMatrix.H
+++ b/src/OpenFOAM/matrices/LUscalarMatrix/LUscalarMatrix.H
@@ -107,7 +107,7 @@ public:
         //- Construct from lduMatrix and perform LU decomposition
         LUscalarMatrix
         (
-            const lduMatrix&,
+            const lduMatrix& ldum,
             const FieldField<Field, scalar>& interfaceCoeffs,
             const lduInterfaceFieldPtrsList& interfaces
         );
@@ -122,12 +122,12 @@ public:
         //  and returning the solution in the Field argument x.
         //  This function may be called with the same field for x and source.
         template<class Type>
-        void solve(Field<Type>& x, const Field<Type>& source) const;
+        void solve(List<Type>& x, const UList<Type>& source) const;
 
         //- Solve the linear system with the given source
         //  returning the solution
         template<class Type>
-        tmp<Field<Type>> solve(const Field<Type>& source) const;
+        tmp<Field<Type>> solve(const UList<Type>& source) const;
 
         //- Set M to the inverse of this square matrix
         void inv(scalarSquareMatrix& M) const;
diff --git a/src/OpenFOAM/matrices/LUscalarMatrix/LUscalarMatrixTemplates.C b/src/OpenFOAM/matrices/LUscalarMatrix/LUscalarMatrixTemplates.C
index f9329df0c76c7d42e10de945c450ae381906db71..584a86593af35930d34a3f8c65a8d06868c864a4 100644
--- a/src/OpenFOAM/matrices/LUscalarMatrix/LUscalarMatrixTemplates.C
+++ b/src/OpenFOAM/matrices/LUscalarMatrix/LUscalarMatrixTemplates.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) 2011-2017 OpenFOAM Foundation
@@ -26,15 +26,15 @@ License
 \*---------------------------------------------------------------------------*/
 
 #include "LUscalarMatrix.H"
-#include "SubField.H"
+#include "SubList.H"
 
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
 template<class Type>
 void Foam::LUscalarMatrix::solve
 (
-    Field<Type>& x,
-    const Field<Type>& source
+    List<Type>& x,
+    const UList<Type>& source
 ) const
 {
     // If x and source are different initialize x = source
@@ -45,15 +45,13 @@ void Foam::LUscalarMatrix::solve
 
     if (Pstream::parRun())
     {
-        Field<Type> X(m());
+        List<Type> X; // scratch space (on master)
 
         if (Pstream::master(comm_))
         {
-            typename Field<Type>::subField
-            (
-                X,
-                x.size()
-            ) = x;
+            X.resize(m());
+
+            SubList<Type>(X, x.size()) = x;
 
             for
             (
@@ -82,7 +80,7 @@ void Foam::LUscalarMatrix::solve
             (
                 Pstream::commsTypes::scheduled,
                 Pstream::masterNo(),
-                reinterpret_cast<const char*>(x.begin()),
+                reinterpret_cast<const char*>(x.cdata()),
                 x.byteSize(),
                 Pstream::msgType(),
                 comm_
@@ -93,11 +91,7 @@ void Foam::LUscalarMatrix::solve
         {
             LUBacksubstitute(*this, pivotIndices_, X);
 
-            x = typename Field<Type>::subField
-            (
-                X,
-                x.size()
-            );
+            x = SubList<Type>(X, x.size());
 
             for
             (
@@ -114,7 +108,7 @@ void Foam::LUscalarMatrix::solve
                     (
                         &(X[procOffsets_[slave]])
                     ),
-                    (procOffsets_[slave + 1]-procOffsets_[slave])*sizeof(Type),
+                    (procOffsets_[slave+1]-procOffsets_[slave])*sizeof(Type),
                     Pstream::msgType(),
                     comm_
                 );
@@ -126,7 +120,7 @@ void Foam::LUscalarMatrix::solve
             (
                 Pstream::commsTypes::scheduled,
                 Pstream::masterNo(),
-                reinterpret_cast<char*>(x.begin()),
+                reinterpret_cast<char*>(x.data()),
                 x.byteSize(),
                 Pstream::msgType(),
                 comm_
@@ -143,13 +137,12 @@ void Foam::LUscalarMatrix::solve
 template<class Type>
 Foam::tmp<Foam::Field<Type>> Foam::LUscalarMatrix::solve
 (
-    const Field<Type>& source
+    const UList<Type>& source
 ) const
 {
-    tmp<Field<Type>> tx(new Field<Type>(m()));
-    Field<Type>& x = tx.ref();
+    auto tx(tmp<Field<Type>>::New(m()));
 
-    solve(x, source);
+    solve(tx.ref(), source);
 
     return tx;
 }
diff --git a/src/OpenFOAM/matrices/Matrix/Matrix.C b/src/OpenFOAM/matrices/Matrix/Matrix.C
index d9dbc580bd15a967ee3e939e8fce27c53a7379d6..072c78ffe7e51fa0e97cf1583c8d7f4978271096 100644
--- a/src/OpenFOAM/matrices/Matrix/Matrix.C
+++ b/src/OpenFOAM/matrices/Matrix/Matrix.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) 2011-2017 OpenFOAM Foundation
@@ -26,16 +26,79 @@ License
 \*---------------------------------------------------------------------------*/
 
 #include "Matrix.H"
+#include <functional>
+#include <algorithm>
 
-// * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * * //
+// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
 
 template<class Form, class Type>
-void Foam::Matrix<Form, Type>::allocate()
+template<class ListType>
+Foam::tmp<Foam::Field<Type>> Foam::Matrix<Form, Type>::AmulImpl
+(
+    const ListType& x
+) const
 {
-    if (mRows_ && nCols_)
+    const Matrix<Form, Type>& mat = *this;
+
+    #ifdef FULLDEBUG
+    if (mat.n() != x.size())
     {
-        v_ = new Type[size()];
+        FatalErrorInFunction
+            << "Attempt to multiply incompatible Matrix and Vector:" << nl
+            << "Matrix : (" << mat.m() << ", " << mat.n() << ')' << nl
+            << "Matrix columns != Vector size (" << x.size() << ')' << nl
+            << abort(FatalError);
     }
+    #endif
+
+    auto tresult = tmp<Field<Type>>::New(mat.m(), Zero);
+    auto& result = tresult.ref();
+
+    for (label i = 0; i < mat.m(); ++i)
+    {
+        for (label j = 0; j < mat.n(); ++j)
+        {
+            result[i] += mat(i, j)*x[j];
+        }
+    }
+
+    return tresult;
+}
+
+
+template<class Form, class Type>
+template<class ListType>
+Foam::tmp<Foam::Field<Type>> Foam::Matrix<Form, Type>::TmulImpl
+(
+    const ListType& x
+) const
+{
+    const Matrix<Form, Type>& mat = *this;
+
+    #ifdef FULLDEBUG
+    if (mat.m() != x.size())
+    {
+        FatalErrorInFunction
+            << "Attempt to multiply incompatible Matrix and Vector:" << nl
+            << "Matrix : (" << mat.m() << ", " << mat.n() << ')' << nl
+            << "Matrix rows != Vector size (" << x.size() << ')' << nl
+            << abort(FatalError);
+    }
+    #endif
+
+    auto tresult = tmp<Field<Type>>::New(mat.n(), Zero);
+    auto& result = tresult.ref();
+
+    for (label i = 0; i < mat.m(); ++i)
+    {
+        const Type& val = x[i];
+        for (label j = 0; j < mat.n(); ++j)
+        {
+            result[j] += val*mat(i, j);
+        }
+    }
+
+    return tresult;
 }
 
 
@@ -48,14 +111,9 @@ Foam::Matrix<Form, Type>::Matrix(const label m, const label n)
     nCols_(n),
     v_(nullptr)
 {
-    if (mRows_ < 0 || nCols_ < 0)
-    {
-        FatalErrorInFunction
-            << "Incorrect m, n " << mRows_ << ", " << nCols_
-            << abort(FatalError);
-    }
+    checkSize();
 
-    allocate();
+    doAlloc();
 }
 
 
@@ -66,90 +124,71 @@ Foam::Matrix<Form, Type>::Matrix(const label m, const label n, const zero)
     nCols_(n),
     v_(nullptr)
 {
-    if (mRows_ < 0 || nCols_ < 0)
-    {
-        FatalErrorInFunction
-            << "Incorrect m, n " << mRows_ << ", " << nCols_
-            << abort(FatalError);
-    }
+    checkSize();
 
-    allocate();
+    doAlloc();
 
-    if (v_)
-    {
-        const label mn = size();
-        for (label i=0; i<mn; i++)
-        {
-            v_[i] = Zero;
-        }
-    }
+    std::fill(begin(), end(), Zero);
 }
 
 
 template<class Form, class Type>
-Foam::Matrix<Form, Type>::Matrix(const label m, const label n, const Type& s)
+Foam::Matrix<Form, Type>::Matrix(const label m, const label n, const Type& val)
 :
     mRows_(m),
     nCols_(n),
     v_(nullptr)
 {
-    if (mRows_ < 0 || nCols_ < 0)
-    {
-        FatalErrorInFunction
-            << "Incorrect m, n " << mRows_ << ", " << nCols_
-            << abort(FatalError);
-    }
+    checkSize();
 
-    allocate();
+    doAlloc();
 
-    if (v_)
-    {
-        const label mn = size();
-        for (label i=0; i<mn; i++)
-        {
-            v_[i] = s;
-        }
-    }
+    std::fill(begin(), end(), val);
 }
 
 
 template<class Form, class Type>
-Foam::Matrix<Form, Type>::Matrix(const Matrix<Form, Type>& M)
+Foam::Matrix<Form, Type>::Matrix(const Matrix<Form, Type>& mat)
 :
-    mRows_(M.mRows_),
-    nCols_(M.nCols_),
+    mRows_(mat.mRows_),
+    nCols_(mat.nCols_),
     v_(nullptr)
 {
-    if (M.v_)
+    if (mat.cdata())
     {
-        allocate();
+        doAlloc();
 
-        const label mn = size();
-        for (label i=0; i<mn; i++)
-        {
-            v_[i] = M.v_[i];
-        }
+        std::copy(mat.cbegin(), mat.cend(), v_);
     }
 }
 
 
+template<class Form, class Type>
+Foam::Matrix<Form, Type>::Matrix(Matrix<Form, Type>&& mat)
+:
+    mRows_(mat.mRows_),
+    nCols_(mat.nCols_),
+    v_(mat.v_)
+{
+    mat.mRows_ = 0;
+    mat.nCols_ = 0;
+    mat.v_ = nullptr;
+}
+
+
 template<class Form, class Type>
 template<class Form2>
-Foam::Matrix<Form, Type>::Matrix(const Matrix<Form2, Type>& M)
+Foam::Matrix<Form, Type>::Matrix(const Matrix<Form2, Type>& mat)
 :
-    mRows_(M.m()),
-    nCols_(M.n()),
+    mRows_(mat.m()),
+    nCols_(mat.n()),
     v_(nullptr)
 {
-    if (M.v())
+    if (mat.cdata())
     {
-        allocate();
+        doAlloc();
 
-        const label mn = size();
-        for (label i=0; i<mn; i++)
-        {
-            v_[i] = M.v()[i];
-        }
+        std::copy(mat.cbegin(), mat.cend(), v_);
     }
 }
 
@@ -164,13 +203,13 @@ inline Foam::Matrix<Form, Type>::Matrix
     mRows_(Mb.m()),
     nCols_(Mb.n())
 {
-    allocate();
+    doAlloc();
 
-    for (label i=0; i<mRows_; i++)
+    for (label i = 0; i < mRows_; ++i)
     {
-        for (label j=0; j<nCols_; j++)
+        for (label j = 0; j < nCols_; ++j)
         {
-            (*this)(i,j) = Mb(i,j);
+            (*this)(i, j) = Mb(i,j);
         }
     }
 }
@@ -186,13 +225,13 @@ inline Foam::Matrix<Form, Type>::Matrix
     mRows_(Mb.m()),
     nCols_(Mb.n())
 {
-    allocate();
+    doAlloc();
 
-    for (label i=0; i<mRows_; i++)
+    for (label i = 0; i < mRows_; ++i)
     {
-        for (label j=0; j<nCols_; j++)
+        for (label j = 0; j < nCols_; ++j)
         {
-            (*this)(i,j) = Mb(i,j);
+            (*this)(i, j) = Mb(i, j);
         }
     }
 }
@@ -227,32 +266,65 @@ void Foam::Matrix<Form, Type>::clear()
 
 
 template<class Form, class Type>
-void Foam::Matrix<Form, Type>::transfer(Matrix<Form, Type>& M)
+Foam::List<Type> Foam::Matrix<Form, Type>::release()
 {
+    List<Type> list;
+
+    const label len = size();
+
+    if (v_ && len)
+    {
+        UList<Type> storage(v_, len);
+        list.swap(storage);
+
+        v_ = nullptr;
+    }
     clear();
 
-    mRows_ = M.mRows_;
-    M.mRows_ = 0;
+    return list;
+}
 
-    nCols_ = M.nCols_;
-    M.nCols_ = 0;
 
-    v_ = M.v_;
-    M.v_ = nullptr;
+template<class Form, class Type>
+void Foam::Matrix<Form, Type>::swap(Matrix<Form, Type>& mat)
+{
+    Foam::Swap(mRows_, mat.mRows_);
+    Foam::Swap(nCols_, mat.nCols_);
+    Foam::Swap(v_, mat.v_);
 }
 
 
 template<class Form, class Type>
-void Foam::Matrix<Form, Type>::setSize(const label m, const label n)
+void Foam::Matrix<Form, Type>::transfer(Matrix<Form, Type>& mat)
 {
-    mType newMatrix(m, n, Zero);
+    clear();
 
-    label minM = min(m, mRows_);
-    label minN = min(n, nCols_);
+    mRows_ = mat.mRows_;
+    nCols_ = mat.nCols_;
+    v_ = mat.v_;
 
-    for (label i=0; i<minM; i++)
+    mat.mRows_ = 0;
+    mat.nCols_ = 0;
+    mat.v_ = nullptr;
+}
+
+
+template<class Form, class Type>
+void Foam::Matrix<Form, Type>::resize(const label m, const label n)
+{
+    if (m == mRows_ && n == nCols_)
     {
-        for (label j=0; j<minN; j++)
+        return;
+    }
+
+    Matrix<Form, Type> newMatrix(m, n, Zero);
+
+    const label mrow = min(m, mRows_);
+    const label ncol = min(n, nCols_);
+
+    for (label i = 0; i < mrow; ++i)
+    {
+        for (label j = 0; j < ncol; ++j)
         {
             newMatrix(i, j) = (*this)(i, j);
         }
@@ -262,17 +334,29 @@ void Foam::Matrix<Form, Type>::setSize(const label m, const label n)
 }
 
 
+template<class Form, class Type>
+void Foam::Matrix<Form, Type>::round(const scalar tol)
+{
+    for (Type& val : *this)
+    {
+        if (mag(val) < tol)
+        {
+            val = Zero;
+        }
+    }
+}
+
+
 template<class Form, class Type>
 Form Foam::Matrix<Form, Type>::T() const
 {
-    const Matrix<Form, Type>& A = *this;
-    Form At(n(), m());
+    Form At(labelPair{n(), m()});
 
-    for (label i=0; i<m(); i++)
+    for (label i = 0; i < m(); ++i)
     {
-        for (label j=0; j<n(); j++)
+        for (label j = 0; j < n(); ++j)
         {
-            At(j, i) = A(i, j);
+            At(j, i) = Detail::conj((*this)(i, j));
         }
     }
 
@@ -280,37 +364,132 @@ Form Foam::Matrix<Form, Type>::T() const
 }
 
 
+template<class Form, class Type>
+Foam::List<Type> Foam::Matrix<Form, Type>::diag() const
+{
+    const label len = Foam::min(mRows_, nCols_);
+
+    List<Type> result(len);
+
+    for (label i=0; i < len; ++i)
+    {
+        result[i] = (*this)(i, i);
+    }
+
+    return result;
+}
+
+
+template<class Form, class Type>
+void Foam::Matrix<Form, Type>::diag(const UList<Type>& list)
+{
+    const label len = Foam::min(mRows_, nCols_);
+
+    #ifdef FULLDEBUG
+    if (list.size() != len)
+    {
+        FatalErrorInFunction
+            << "List size (" << list.size()
+            << ") incompatible with Matrix diagonal" << abort(FatalError);
+    }
+    #endif
+
+    for (label i=0; i < len; ++i)
+    {
+        (*this)(i, i) = list[i];
+    }
+}
+
+
+template<class Form, class Type>
+Type Foam::Matrix<Form, Type>::trace() const
+{
+    const label len = Foam::min(mRows_, nCols_);
+
+    Type val = Zero;
+
+    for (label i=0; i < len; ++i)
+    {
+        val += (*this)(i, i);
+    }
+
+    return val;
+}
+
+
+template<class Form, class Type>
+Foam::scalar Foam::Matrix<Form, Type>::columnNorm
+(
+    const label colIndex,
+    const bool noSqrt
+) const
+{
+    scalar result = Zero;
+
+    for (label i=0; i < mRows_; ++i)
+    {
+        result += magSqr((*this)(i, colIndex));
+    }
+
+    return noSqrt ? result : Foam::sqrt(result);
+}
+
+
+template<class Form, class Type>
+Foam::scalar Foam::Matrix<Form, Type>::norm(const bool noSqrt) const
+{
+    scalar result = Zero;
+
+    for (const Type& val : *this)
+    {
+        result += magSqr(val);
+    }
+
+    return noSqrt ? result : Foam::sqrt(result);
+}
+
+
 // * * * * * * * * * * * * * * * Member Operators  * * * * * * * * * * * * * //
 
 template<class Form, class Type>
-void Foam::Matrix<Form, Type>::operator=(const Matrix<Form, Type>& M)
+void Foam::Matrix<Form, Type>::operator=(const Matrix<Form, Type>& mat)
 {
-    if (this == &M)
+    if (this == &mat)
     {
         FatalErrorInFunction
             << "Attempted assignment to self"
             << abort(FatalError);
     }
 
-    if (mRows_ != M.mRows_ || nCols_ != M.nCols_)
+    if (mRows_ != mat.mRows_ || nCols_ != mat.nCols_)
     {
         clear();
-        mRows_ = M.mRows_;
-        nCols_ = M.nCols_;
-        allocate();
+        mRows_ = mat.mRows_;
+        nCols_ = mat.nCols_;
+        doAlloc();
     }
 
     if (v_)
     {
-        const label mn = size();
-        for (label i=0; i<mn; i++)
-        {
-            v_[i] = M.v_[i];
-        }
+        std::copy(mat.cbegin(), mat.cend(), v_);
     }
 }
 
 
+template<class Form, class Type>
+void Foam::Matrix<Form, Type>::operator=(Matrix<Form, Type>&& mat)
+{
+    if (this == &mat)
+    {
+        FatalErrorInFunction
+            << "Attempted assignment to self"
+            << abort(FatalError);
+    }
+
+    this->transfer(mat);
+}
+
+
 template<class Form, class Type>
 template<class MatrixType>
 void Foam::Matrix<Form, Type>::operator=
@@ -318,11 +497,11 @@ void Foam::Matrix<Form, Type>::operator=
     const ConstMatrixBlock<MatrixType>& Mb
 )
 {
-    for (label i=0; i<mRows_; i++)
+    for (label i = 0; i < mRows_; ++i)
     {
-        for (label j=0; j<nCols_; j++)
+        for (label j = 0; j < nCols_; ++j)
         {
-            (*this)(i,j) = Mb(i,j);
+            (*this)(i, j) = Mb(i, j);
         }
     }
 }
@@ -335,263 +514,353 @@ void Foam::Matrix<Form, Type>::operator=
     const MatrixBlock<MatrixType>& Mb
 )
 {
-    for (label i=0; i<mRows_; i++)
+    for (label i = 0; i < mRows_; ++i)
     {
-        for (label j=0; j<nCols_; j++)
+        for (label j = 0; j < nCols_; ++j)
         {
-            (*this)(i,j) = Mb(i,j);
+            (*this)(i, j) = Mb(i, j);
         }
     }
 }
 
 
 template<class Form, class Type>
-void Foam::Matrix<Form, Type>::operator=(const Type& s)
+void Foam::Matrix<Form, Type>::operator=(const Type& val)
 {
-    if (v_)
-    {
-        const label mn = size();
-        for (label i=0; i<mn; i++)
-        {
-            v_[i] = s;
-        }
-    }
+    std::fill(begin(), end(), val);
 }
 
 
 template<class Form, class Type>
 void Foam::Matrix<Form, Type>::operator=(const zero)
 {
-    if (v_)
-    {
-        const label mn = size();
-        for (label i=0; i<mn; i++)
-        {
-            v_[i] = Zero;
-        }
-    }
+    std::fill(begin(), end(), Zero);
 }
 
 
-// * * * * * * * * * * * * * * * Global Functions  * * * * * * * * * * * * * //
-
 template<class Form, class Type>
-const Type& Foam::max(const Matrix<Form, Type>& M)
+void Foam::Matrix<Form, Type>::operator+=(const Matrix<Form, Type>& other)
 {
-    const label mn = M.size();
-
-    if (mn)
+    #ifdef FULLDEBUG
+    if (this == &other)
     {
-        label curMaxI = 0;
-        const Type* Mv = M.v();
-
-        for (label i=1; i<mn; i++)
-        {
-            if (Mv[i] > Mv[curMaxI])
-            {
-                curMaxI = i;
-            }
-        }
-
-        return Mv[curMaxI];
+        FatalErrorInFunction
+            << "Attempted addition to self"
+            << abort(FatalError);
     }
-    else
+
+    if (m() != other.m() || n() != other.n())
     {
         FatalErrorInFunction
-            << "Matrix is empty"
+            << "Attempt to add matrices with different sizes: ("
+            << m() << ", " << n() << ") != ("
+            << other.m() << ", " << other.n() << ')' << nl
             << abort(FatalError);
+    }
+    #endif
 
-        // Return in error to keep compiler happy
-        return M(0, 0);
+    auto iter2 = other.cbegin();
+    for (Type& val : *this)
+    {
+        val += *iter2;
+        ++iter2;
     }
 }
 
 
 template<class Form, class Type>
-const Type& Foam::min(const Matrix<Form, Type>& M)
+void Foam::Matrix<Form, Type>::operator-=(const Matrix<Form, Type>& other)
 {
-    const label mn = M.size();
-
-    if (mn)
+    #ifdef FULLDEBUG
+    if (this == &other)
     {
-        label curMinI = 0;
-        const Type* Mv = M.v();
-
-        for (label i=1; i<mn; i++)
-        {
-            if (Mv[i] < Mv[curMinI])
-            {
-                curMinI = i;
-            }
-        }
-
-        return Mv[curMinI];
+        FatalErrorInFunction
+            << "Attempted subtraction from self"
+            << abort(FatalError);
     }
-    else
+
+    if (m() != other.m() || n() != other.n())
     {
         FatalErrorInFunction
-            << "Matrix is empty"
+            << "Attempt to subtract matrices with different sizes: ("
+            << m() << ", " << n() << ") != ("
+            << other.m() << ", " << other.n() << ')' << nl
             << abort(FatalError);
+    }
+    #endif
 
-        // Return in error to keep compiler happy
-        return M(0, 0);
+    auto iter2 = other.cbegin();
+    for (Type& val : *this)
+    {
+        val -= *iter2;
+        ++iter2;
     }
 }
 
 
-// * * * * * * * * * * * * * * * Global Operators  * * * * * * * * * * * * * //
-
 template<class Form, class Type>
-Form Foam::operator-(const Matrix<Form, Type>& M)
+void Foam::Matrix<Form, Type>::operator+=(const Type& s)
 {
-    Form nM(M.m(), M.n());
+    for (Type& val : *this)
+    {
+        val += s;
+    }
+}
 
-    if (M.m() && M.n())
+
+template<class Form, class Type>
+void Foam::Matrix<Form, Type>::operator-=(const Type& s)
+{
+    for (Type& val : *this)
     {
-        Type* nMv = nM.v();
-        const Type* Mv = M.v();
+        val -= s;
+    }
+}
 
-        const label mn = M.size();
-        for (label i=0; i<mn; i++)
-        {
-            nMv[i] = -Mv[i];
-        }
+
+template<class Form, class Type>
+void Foam::Matrix<Form, Type>::operator*=(const Type& s)
+{
+    for (Type& val : *this)
+    {
+        val *= s;
     }
+}
+
 
-    return nM;
+template<class Form, class Type>
+void Foam::Matrix<Form, Type>::operator/=(const Type& s)
+{
+    for (Type& val : *this)
+    {
+        val /= s;
+    }
 }
 
 
+// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * * //
+
 template<class Form, class Type>
-Form Foam::operator+(const Matrix<Form, Type>& A, const Matrix<Form, Type>& B)
+const Type& Foam::max(const Matrix<Form, Type>& mat)
 {
-    if (A.m() != B.m())
+    if (mat.empty())
     {
         FatalErrorInFunction
-            << "Attempt to add matrices with different numbers of rows: "
-            << A.m() << ", " << B.m()
-            << abort(FatalError);
+            << "Matrix is empty" << abort(FatalError);
     }
 
-    if (A.n() != B.n())
+    return *(std::max_element(mat.cbegin(), mat.cend()));
+}
+
+
+template<class Form, class Type>
+const Type& Foam::min(const Matrix<Form, Type>& mat)
+{
+    if (mat.empty())
     {
         FatalErrorInFunction
-            << "Attempt to add matrices with different numbers of columns: "
-            << A.n() << ", " << B.n()
-            << abort(FatalError);
+            << "Matrix is empty" << abort(FatalError);
     }
 
-    Form AB(A.m(), A.n());
+    return *(std::min_element(mat.cbegin(), mat.cend()));
+}
 
-    Type* ABv = AB.v();
-    const Type* Av = A.v();
-    const Type* Bv = B.v();
 
-    const label mn = A.size();
-    for (label i=0; i<mn; i++)
+template<class Form, class Type>
+Foam::MinMax<Type> Foam::minMax(const Matrix<Form, Type>& mat)
+{
+    MinMax<Type> result;
+
+    for (const Type& val : mat)
     {
-        ABv[i] = Av[i] + Bv[i];
+        result += val;
     }
 
-    return AB;
+    return result;
 }
 
 
+// * * * * * * * * * * * * * * * Global Operators  * * * * * * * * * * * * * //
+
 template<class Form, class Type>
-Form Foam::operator-(const Matrix<Form, Type>& A, const Matrix<Form, Type>& B)
+Form Foam::operator-(const Matrix<Form, Type>& mat)
 {
-    if (A.m() != B.m())
+    Form result(mat.sizes());
+
+    std::transform
+    (
+        mat.cbegin(),
+        mat.cend(),
+        result.begin(),
+        std::negate<Type>()
+    );
+
+    return result;
+}
+
+
+template<class Form1, class Form2, class Type>
+Form1 Foam::operator+
+(
+    const Matrix<Form1, Type>& A,
+    const Matrix<Form2, Type>& B
+)
+{
+    #ifdef FULLDEBUG
+    if (A.m() != B.m() || A.n() != B.n())
     {
         FatalErrorInFunction
-            << "Attempt to add matrices with different numbers of rows: "
-            << A.m() << ", " << B.m()
+            << "Attempt to add matrices with different sizes: ("
+            << A.m() << ", " << A.n() << ") != ("
+            << B.m() << ", " << B.n() << ')' << nl
             << abort(FatalError);
     }
+    #endif
+
+    Form1 result(A.sizes());
+
+    std::transform
+    (
+        A.cbegin(),
+        A.cend(),
+        B.cbegin(),
+        result.begin(),
+        std::plus<Type>()
+    );
 
-    if (A.n() != B.n())
+    return result;
+}
+
+
+template<class Form1, class Form2, class Type>
+Form1 Foam::operator-
+(
+    const Matrix<Form1, Type>& A,
+    const Matrix<Form2, Type>& B
+)
+{
+    #ifdef FULLDEBUG
+    if (A.m() != B.m() || A.n() != B.n())
     {
         FatalErrorInFunction
-            << "Attempt to add matrices with different numbers of columns: "
-            << A.n() << ", " << B.n()
+            << "Attempt to subtract matrices with different sizes: ("
+            << A.m() << ", " << A.n() << ") != ("
+            << B.m() << ", " << B.n() << ')' << nl
             << abort(FatalError);
     }
+    #endif
 
-    Form AB(A.m(), A.n());
-
-    Type* ABv = AB.v();
-    const Type* Av = A.v();
-    const Type* Bv = B.v();
+    Form1 result(A.sizes());
 
-    const label mn = A.size();
-    for (label i=0; i<mn; i++)
-    {
-        ABv[i] = Av[i] - Bv[i];
-    }
+    std::transform
+    (
+        A.cbegin(),
+        A.cend(),
+        B.cbegin(),
+        result.begin(),
+        std::minus<Type>()
+    );
 
-    return AB;
+    return result;
 }
 
 
 template<class Form, class Type>
-Form Foam::operator*(const scalar s, const Matrix<Form, Type>& M)
+Form Foam::operator*(const Type& s, const Matrix<Form, Type>& mat)
 {
-    Form sM(M.m(), M.n());
+    Form result(mat.sizes());
 
-    if (M.m() && M.n())
-    {
-        Type* sMv = sM.v();
-        const Type* Mv = M.v();
+    std::transform
+    (
+        mat.cbegin(),
+        mat.cend(),
+        result.begin(),
+        [&](const Type& val) { return s * val; }
+    );
 
-        const label mn = M.size();
-        for (label i=0; i<mn; i++)
-        {
-            sMv[i] = s*Mv[i];
-        }
-    }
+    return result;
+}
+
+
+template<class Form, class Type>
+Form Foam::operator+(const Type& s, const Matrix<Form, Type>& mat)
+{
+    Form result(mat.sizes());
 
-    return sM;
+    std::transform
+    (
+        mat.cbegin(),
+        mat.cend(),
+        result.begin(),
+        [&](const Type& val) { return s + val; }
+    );
+
+    return result;
 }
 
 
 template<class Form, class Type>
-Form Foam::operator*(const Matrix<Form, Type>& M, const scalar s)
+Form Foam::operator-(const Type& s, const Matrix<Form, Type>& mat)
 {
-    Form sM(M.m(), M.n());
+    Form result(mat.sizes());
 
-    if (M.m() && M.n())
-    {
-        Type* sMv = sM.v();
-        const Type* Mv = M.v();
+    std::transform
+    (
+        mat.cbegin(),
+        mat.end(),
+        result.begin(),
+        [&](const Type& val) { return s - val; }
+    );
+
+    return result;
+}
 
-        const label mn = M.size();
-        for (label i=0; i<mn; i++)
-        {
-            sMv[i] = Mv[i]*s;
-        }
-    }
 
-    return sM;
+template<class Form, class Type>
+Form Foam::operator*(const Matrix<Form, Type>& mat, const Type& s)
+{
+    return s*mat;
 }
 
 
 template<class Form, class Type>
-Form Foam::operator/(const Matrix<Form, Type>& M, const scalar s)
+Form Foam::operator+(const Matrix<Form, Type>& mat, const Type& s)
 {
-    Form sM(M.m(), M.n());
+    return s + mat;
+}
 
-    if (M.m() && M.n())
-    {
-        Type* sMv = sM.v();
-        const Type* Mv = M.v();
 
-        const label mn = M.size();
-        for (label i=0; i<mn; i++)
-        {
-            sMv[i] = Mv[i]/s;
-        }
-    }
+template<class Form, class Type>
+Form Foam::operator-(const Matrix<Form, Type>& mat, const Type& s)
+{
+    Form result(mat.sizes());
+
+    std::transform
+    (
+        mat.cbegin(),
+        mat.end(),
+        result.begin(),
+        [&](const Type& val) { return val - s; }
+    );
+
+    return result;
+}
+
+
+template<class Form, class Type>
+Form Foam::operator/(const Matrix<Form, Type>& mat, const Type& s)
+{
+    Form result(mat.sizes());
+
+    std::transform
+    (
+        mat.cbegin(),
+        mat.end(),
+        result.begin(),
+        [&](const Type& val) { return val / s; }
+    );
 
-    return sM;
+    return result;
 }
 
 
@@ -603,16 +872,17 @@ Foam::operator*
     const Matrix<Form2, Type>& B
 )
 {
+    #ifdef FULLDEBUG
     if (A.n() != B.m())
     {
         FatalErrorInFunction
             << "Attempt to multiply incompatible matrices:" << nl
-            << "Matrix A : " << A.m() << " x " << A.n() << nl
-            << "Matrix B : " << B.m() << " x " << B.n() << nl
-            << "In order to multiply matrices, columns of A must equal "
-            << "rows of B"
+            << "Matrix A : (" << A.m() << ", " << A.n() << ')' << nl
+            << "Matrix B : (" << B.m() << ", " << B.n() << ')' << nl
+            << "The columns of A must equal rows of B"
             << abort(FatalError);
     }
+    #endif
 
     typename typeOfInnerProduct<Type, Form1, Form2>::type AB
     (
@@ -621,11 +891,11 @@ Foam::operator*
         Zero
     );
 
-    for (label i=0; i<AB.m(); i++)
+    for (label i = 0; i < AB.m(); ++i)
     {
-        for (label j=0; j<AB.n(); j++)
+        for (label k = 0; k < B.m(); ++k)
         {
-            for (label k=0; k<B.m(); k++)
+            for (label j = 0; j < AB.n(); ++j)
             {
                 AB(i, j) += A(i, k)*B(k, j);
             }
@@ -636,36 +906,87 @@ Foam::operator*
 }
 
 
-template<class Form, class Type>
-inline Foam::tmp<Foam::Field<Type>> Foam::operator*
+template<class Form1, class Form2, class Type>
+typename Foam::typeOfInnerProduct<Type, Form1, Form2>::type
+Foam::operator&
+(
+    const Matrix<Form1, Type>& AT,
+    const Matrix<Form2, Type>& B
+)
+{
+    #ifdef FULLDEBUG
+    if (AT.m() != B.m())
+    {
+        FatalErrorInFunction
+            << "Attempt to multiply incompatible matrices:" << nl
+            << "Matrix A : (" << AT.m() << ", " << AT.n() << ')' << nl
+            << "Matrix B : (" << B.m() << ", " << B.n() << ')' << nl
+            << "The rows of A must equal rows of B"
+            << abort(FatalError);
+    }
+    #endif
+
+    typename typeOfInnerProduct<Type, Form1, Form2>::type AB
+    (
+        AT.n(),
+        B.n(),
+        Zero
+    );
+
+    for (label i = 0; i < AB.m(); ++i)
+    {
+        for (label k = 0; k < B.m(); ++k)
+        {
+            for (label j = 0; j < AB.n(); ++j)
+            {
+                AB(i, j) += Detail::conj(AT(k, i))*B(k, j);
+            }
+        }
+    }
+
+    return AB;
+}
+
+
+template<class Form1, class Form2, class Type>
+typename Foam::typeOfInnerProduct<Type, Form1, Form2>::type
+Foam::operator^
 (
-    const Matrix<Form, Type>& M,
-    const Field<Type>& f
+    const Matrix<Form1, Type>& A,
+    const Matrix<Form2, Type>& BT
 )
 {
-    if (M.n() != f.size())
+    #ifdef FULLDEBUG
+    if (A.n() != BT.n())
     {
         FatalErrorInFunction
-            << "Attempt to multiply incompatible matrix and field:" << nl
-            << "Matrix : " << M.m() << " x " << M.n() << nl
-            << "Field : " << f.size() << " rows" << nl
-            << "In order to multiply a matrix M and field f, "
-               "columns of M must equal rows of f"
+            << "Attempt to multiply incompatible matrices:" << nl
+            << "Matrix A : (" << A.m() << ", " << A.n() << ')' << nl
+            << "Matrix B : (" << BT.m() << ", " << BT.n() << ')' << nl
+            << "The columns of A must equal columns of B"
             << abort(FatalError);
     }
+    #endif
 
-    tmp<Field<Type>> tMf(new Field<Type>(M.m(), Zero));
-    Field<Type>& Mf = tMf.ref();
+    typename typeOfInnerProduct<Type, Form1, Form2>::type AB
+    (
+        A.m(),
+        BT.m(),
+        Zero
+    );
 
-    for (label i=0; i<M.m(); i++)
+    for (label i = 0; i < AB.m(); ++i)
     {
-        for (label j=0; j<M.n(); j++)
+        for (label k = 0; k < BT.n(); ++k)
         {
-            Mf[i] += M(i, j)*f[j];
+            for (label j = 0; j < AB.n(); ++j)
+            {
+                AB(i, j) += A(i, k)*Detail::conj(BT(j, k));
+            }
         }
     }
 
-    return tMf;
+    return AB;
 }
 
 
diff --git a/src/OpenFOAM/matrices/Matrix/Matrix.H b/src/OpenFOAM/matrices/Matrix/Matrix.H
index fd6a0823be4eb79e4c1abde64abf633e8d52b80d..2aef3908967f739eee8ca85a2a04e9d2e016b3de 100644
--- a/src/OpenFOAM/matrices/Matrix/Matrix.H
+++ b/src/OpenFOAM/matrices/Matrix/Matrix.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) 2011-2016 OpenFOAM Foundation
@@ -28,6 +28,16 @@ Class
 
 Description
     A templated (m x n) matrix of objects of \<T\>.
+    The layout is (mRows x nCols) - row-major order:
+
+    \verbatim
+        (0,0)
+          +---> j [nCols]
+          |
+          |
+          v
+          i [mRows]
+    \endverbatim
 
 SourceFiles
     Matrix.C
@@ -39,39 +49,21 @@ SourceFiles
 #ifndef Matrix_H
 #define Matrix_H
 
-#include "bool.H"
-#include "label.H"
 #include "uLabel.H"
+#include "Pair.H"
 #include "Field.H"
-#include "zero.H"
 #include "autoPtr.H"
+#include "complex.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
 namespace Foam
 {
 
-// Forward declaration of friend functions and operators
-
+// Forward Declarations
 template<class Form, class Type> class Matrix;
-
-template<class Form, class Type> Istream& operator>>
-(
-    Istream&,
-    Matrix<Form, Type>&
-);
-
-template<class Form, class Type> Ostream& operator<<
-(
-    Ostream&,
-    const Matrix<Form, Type>&
-);
-
-template<class MatrixType>
-class ConstMatrixBlock;
-
-template<class MatrixType>
-class MatrixBlock;
+template<class MatrixType> class ConstMatrixBlock;
+template<class MatrixType> class MatrixBlock;
 
 
 /*---------------------------------------------------------------------------*\
@@ -81,16 +73,27 @@ class MatrixBlock;
 template<class Form, class Type>
 class Matrix
 {
-    // Private data
+    // Private Data
 
-        //- Number of rows and columns in Matrix.
+        //- Number of rows and columns in Matrix
         label mRows_, nCols_;
 
-        //- Row pointers
+        //- Vector of values of type Type
         Type* __restrict__ v_;
 
-        //- Allocate the storage for the element vector
-        void allocate();
+
+    // Private Member Functions
+
+        //- Allocate storage for the contents
+        inline void doAlloc();
+
+        //- Right-multiply Matrix by a column vector (A * x)
+        template<class ListType>
+        tmp<Field<Type>> AmulImpl(const ListType& x) const;
+
+        //- Left-multiply Matrix by a row vector (x * A)
+        template<class ListType>
+        tmp<Field<Type>> TmulImpl(const ListType& x) const;
 
 
 public:
@@ -105,42 +108,65 @@ public:
     // Static Member Functions
 
         //- Return a null Matrix
-        inline static const mType& null();
+        inline static const Matrix<Form, Type>& null();
+
+
+    // Iterators
+
+        //- Random access iterator for traversing a Matrix
+        typedef Type* iterator;
+
+        //- Random access iterator for traversing a Matrix
+        typedef const Type* const_iterator;
 
 
     // Constructors
 
-        //- Null constructor.
+        //- Construct null
         inline Matrix();
 
-        //- Construct given number of rows and columns.
+        //- Construct given number of rows/columns
         Matrix(const label m, const label n);
 
-        //- Construct with given number of rows and columns
-        //  initializing all elements to zero
+        //- Construct with given number of rows/columns
+        //- initializing all elements to zero
         Matrix(const label m, const label n, const zero);
 
-        //- Construct with given number of rows and columns
-        //  initializing all elements to the given value
-        Matrix(const label m, const label n, const Type&);
+        //- Construct with given number of rows/columns
+        //- initializing all elements to the given value
+        Matrix(const label m, const label n, const Type& val);
+
+        //- Construct given number of rows/columns
+        inline explicit Matrix(const labelPair& dims);
+
+        //- Construct given number of rows/columns
+        //- initializing all elements to zero
+        inline Matrix(const labelPair& dims, const zero);
+
+        //- Construct with given number of rows/columns
+        //- initializing all elements to the given value
+        inline Matrix(const labelPair& dims, const Type& val);
+
+        //- Copy construct
+        Matrix(const Matrix<Form, Type>& mat);
 
-        //- Copy constructor.
-        Matrix(const mType&);
+        //- Move construct
+        Matrix(Matrix<Form, Type>&& mat);
 
-        //- Copy constructor from matrix of a different form
+        //- Copy constructor from Matrix of a different form
         template<class Form2>
-        explicit Matrix(const Matrix<Form2, Type>&);
+        explicit Matrix(const Matrix<Form2, Type>& mat);
 
-        //- Construct from a block of another matrix
+        //- Construct from a block of another Matrix
         template<class MatrixType>
-        Matrix(const ConstMatrixBlock<MatrixType>&);
+        Matrix(const ConstMatrixBlock<MatrixType>& Mb);
 
-        //- Construct from a block of another matrix
+        //- Construct from a block of another Matrix
         template<class MatrixType>
-        Matrix(const MatrixBlock<MatrixType>&);
+        Matrix(const MatrixBlock<MatrixType>& Mb);
 
         //- Construct from Istream.
-        Matrix(Istream&);
+        explicit Matrix(Istream& is);
 
         //- Clone
         inline autoPtr<mType> clone() const;
@@ -152,222 +178,552 @@ public:
 
     // Member Functions
 
-        // Access
+    // Access
 
-            //- Return the number of rows
-            inline label m() const;
+        //- Return the number of rows
+        inline label m() const noexcept;
 
-            //- Return the number of columns
-            inline label n() const;
+        //- Return the number of columns
+        inline label n() const noexcept;
 
-            //- Return the number of elements in matrix (m*n)
-            inline label size() const;
+        //- Return the number of elements in Matrix (m*n)
+        inline label size() const;
 
-            //- Return element vector of the constant Matrix
-            inline const Type* v() const;
+        //- Return row/column sizes
+        inline labelPair sizes() const;
 
-            //- Return element vector of the Matrix
-            inline Type* v();
+        //- Return true if Matrix is empty (i.e., size() is zero)
+        inline bool empty() const noexcept;
 
+        //- Return const pointer to the first data element, which can also
+        //- be used to address into Matrix contents
+        inline const Type* cdata() const noexcept;
 
-        // Block access
+        //- Return pointer to the first data element, which can also
+        //- be used to address into Matrix contents
+        inline Type* data() noexcept;
 
-            inline ConstMatrixBlock<mType> block
-            (
-                const label m,
-                const label n,
-                const label mStart,
-                const label nStart
-            ) const;
+        //- Return const pointer to data in the specified row
+        //  Subscript checking only with FULLDEBUG
+        inline const Type* rowData(const label irow) const;
 
-            template<class VectorSpace>
-            inline ConstMatrixBlock<mType> block
-            (
-                const label mStart,
-                const label nStart
-            ) const;
+        //- Return pointer to data in the specified row
+        //  Subscript checking only with FULLDEBUG
+        inline Type* rowData(const label irow);
 
-            inline ConstMatrixBlock<mType> col
-            (
-                const label m,
-                const label rowStart
-            ) const;
+        //- Linear addressing const element access
+        //  Subscript checking only with FULLDEBUG
+        inline const Type& at(const label idx) const;
 
-            inline ConstMatrixBlock<mType> col
-            (
-                const label m,
-                const label mStart,
-                const label nStart
-            ) const;
+        //- Linear addressing element access
+        //  Subscript checking only with FULLDEBUG
+        inline Type& at(const label idx);
 
 
-            inline MatrixBlock<mType> block
-            (
-                const label m,
-                const label n,
-                const label mStart,
-                const label nStart
-            );
+    // Block Access (const)
 
-            template<class VectorSpace>
-            inline MatrixBlock<mType> block
-            (
-                const label mStart,
-                const label nStart
-            );
+        //- Return const column or column's subset of Matrix
+        //  Return entire column by its index: M.subColumn(a);
+        //  Return subset of a column starting from rowIndex: M.subColumn(a, b);
+        //  Return subset of a column starting from rowIndex with szRows elems:
+        //      M.subColumn(a, b, c);
+        inline ConstMatrixBlock<mType> subColumn
+        (
+            const label colIndex,
+            const label rowIndex = 0,
+            label len = -1
+        ) const;
+
+        //- Return const row or const row's subset of Matrix
+        //  Return entire row by its index: M.subRow(a);
+        //  Return subset of a row starting from columnIndex: M.subRow(a,b);
+        //  Return subset of a row starting from columnIndex with szCols elems:
+        //      M.subRow(a, b, c);
+        inline ConstMatrixBlock<mType> subRow
+        (
+            const label rowIndex,
+            const label colIndex = 0,
+            label len = -1
+        ) const;
+
+        //- Return const sub-block of Matrix
+        //  Sub-block starting at columnIndex & rowIndex indices
+        inline ConstMatrixBlock<mType> subMatrix
+        (
+            const label rowIndex,
+            const label colIndex,
+            label szRows = -1,
+            label szCols = -1
+        ) const;
+
+        //- Access Field as a ConstMatrixBlock
+        template<class VectorSpace>
+        inline ConstMatrixBlock<mType> block
+        (
+            const label rowIndex,
+            const label colIndex
+        ) const;
 
-            inline MatrixBlock<mType> col
-            (
-                const label m,
-                const label rowStart
-            );
 
-            inline MatrixBlock<mType> col
-            (
-                const label m,
-                const label mStart,
-                const label nStart
-            );
+    // Block Access (non-const)
 
+        //- Return column or column's subset of Matrix
+        inline MatrixBlock<mType> subColumn
+        (
+            const label colIndex,
+            const label rowIndex = 0,
+            label len = -1
+        );
 
-        // Check
+        //- Return row or row's subset of Matrix
+        inline MatrixBlock<mType> subRow
+        (
+            const label rowIndex,
+            const label colIndex = 0,
+            label len = -1
+        );
 
-            //- Check index i is within valid range (0 ... m-1).
-            inline void checki(const label i) const;
+        //- Return sub-block of Matrix
+        inline MatrixBlock<mType> subMatrix
+        (
+            const label rowIndex,
+            const label colIndex,
+            label szRows = -1,
+            label szCols = -1
+        );
 
-            //- Check index j is within valid range (0 ... n-1).
-            inline void checkj(const label j) const;
+        //- Access Field as a MatrixBlock
+        template<class VectorSpace>
+        inline MatrixBlock<mType> block
+        (
+            const label rowIndex,
+            const label colIndex
+        );
 
 
-        // Edit
+    // Check
 
-            //- Clear the Matrix, i.e. set sizes to zero.
-            void clear();
+        //- Check index i is within valid range [0, m)
+        inline void checki(const label irow) const;
 
-            //- Transfer the contents of the argument Matrix into this Matrix
-            //  and annul the argument Matrix.
-            void transfer(mType&);
+        //- Check index j is within valid range [0, n)
+        inline void checkj(const label jcol) const;
 
-            //- Resize the matrix preserving the elements
-            void setSize(const label m, const label n);
+        //- Check that dimensions are positive, non-zero
+        inline void checkSize() const;
 
-            //- Resize the matrix without reallocating storage (unsafe)
-            inline void shallowResize(const label m, const label n);
+        //- True if all entries have identical values, and Matrix is non-empty
+        inline bool uniform() const;
 
 
-        //- Return the transpose of the matrix
+    // Edit
+
+        //- Clear Matrix, i.e. set sizes to zero
+        void clear();
+
+        //- Release storage management of Matrix contents by transferring
+        //- management to a List
+        List<Type> release();
+
+        //- Swap contents
+        void swap(Matrix<Form, Type>& mat);
+
+        //- Transfer the contents of the argument Matrix into this Matrix
+        //- and annul the argument Matrix
+        void transfer(Matrix<Form, Type>& mat);
+
+        //- Change Matrix dimensions, preserving the elements
+        void resize(const label m, const label n);
+
+        //- Change Matrix dimensions, preserving the elements
+        inline void setSize(const label m, const label n);
+
+        //- Resize Matrix without reallocating storage (unsafe)
+        inline void shallowResize(const label m, const label n);
+
+        //- Round to zero elements with magnitude smaller than tol (SMALL)
+        void round(const scalar tol = SMALL);
+
+
+    // Operations
+
+        //- Return (conjugate) transpose of Matrix
         Form T() const;
 
+        //- Right-multiply Matrix by a column vector (A * x)
+        inline tmp<Field<Type>> Amul(const UList<Type>& x) const;
+
+        //- Right-multiply Matrix by a column vector (A * x)
+        template<class Addr>
+        inline tmp<Field<Type>> Amul
+        (
+            const IndirectListBase<Type, Addr>& x
+        ) const;
+
+        //- Left-multiply Matrix by a row vector (x * A)
+        inline tmp<Field<Type>> Tmul(const UList<Type>& x) const;
+
+        //- Left-multiply Matrix by a row vector (x * A)
+        template<class Addr>
+        inline tmp<Field<Type>> Tmul
+        (
+            const IndirectListBase<Type, Addr>& x
+        ) const;
+
+        //- Extract the diagonal elements. Method may change in the future.
+        List<Type> diag() const;
 
-    // Member operators
+        //- Assign diagonal of Matrix
+        void diag(const UList<Type>& list);
 
-        //- Return subscript-checked row of Matrix.
-        inline Type* operator[](const label);
+        //- Return the trace
+        Type trace() const;
 
-        //- Return subscript-checked row of constant Matrix.
-        inline const Type* operator[](const label) const;
+        //- Return L2-Norm of chosen column
+        //  Optional without sqrt for parallel usage.
+        scalar columnNorm(const label colIndex, const bool noSqrt=false) const;
+
+        //- Return Frobenius norm of Matrix
+        //  Optional without sqrt for parallel usage.
+        //  https://en.wikipedia.org/wiki/Matrix_norm#Frobenius_norm
+        scalar norm(const bool noSqrt=false) const;
+
+
+    // Member Operators
+
+        //- Return const pointer to data in the specified row - rowData().
+        //  Subscript checking only with FULLDEBUG
+        inline const Type* operator[](const label irow) const;
+
+        //- Return pointer to data in the specified row - rowData().
+        //  Subscript checking only with FULLDEBUG
+        inline Type* operator[](const label irow);
 
         //- (i, j) const element access operator
-        inline const Type& operator()(const label i, const label j) const;
+        //  Subscript checking only with FULLDEBUG
+        inline const Type& operator()(const label irow, const label jcol) const;
 
         //- (i, j) element access operator
-        inline Type& operator()(const label i, const label j);
+        //  Subscript checking only with FULLDEBUG
+        inline Type& operator()(const label irow, const label jcol);
+
+        //- Copy assignment. Takes linear time.
+        void operator=(const Matrix<Form, Type>& mat);
 
-        //- Assignment operator. Takes linear time.
-        void operator=(const mType&);
+        //- Move assignment
+        void operator=(Matrix<Form, Type>&& mat);
 
-        //- Assignment to a block of another matrix
+        //- Assignment to a block of another Matrix
         template<class MatrixType>
-        void operator=(const ConstMatrixBlock<MatrixType>&);
+        void operator=(const ConstMatrixBlock<MatrixType>& Mb);
 
-        //- Assignment to a block of another matrix
+        //- Assignment to a block of another Matrix
         template<class MatrixType>
-        void operator=(const MatrixBlock<MatrixType>&);
+        void operator=(const MatrixBlock<MatrixType>& Mb);
 
         //- Assignment of all elements to zero
         void operator=(const zero);
 
         //- Assignment of all elements to the given value
-        void operator=(const Type&);
+        void operator=(const Type& val);
 
+        //- Matrix addition
+        void operator+=(const Matrix<Form, Type>& other);
 
-    // IOstream operators
+        //- Matrix subtraction
+        void operator-=(const Matrix<Form, Type>& other);
+
+        //- Matrix scalar addition
+        void operator+=(const Type& s);
+
+        //- Matrix scalar subtraction
+        void operator-=(const Type& s);
+
+        //- Matrix scalar multiplication
+        void operator*=(const Type& s);
+
+        //- Matrix scalar division
+        void operator/=(const Type& s);
+
+
+    // Random Access Iterator (non-const)
+
+        //- Return an iterator to begin traversing a Matrix
+        inline iterator begin();
+
+        //- Return an iterator to end traversing a Matrix
+        inline iterator end();
 
-        //- Read Matrix from Istream, discarding contents of existing Matrix.
-        friend Istream& operator>> <Form, Type>
-        (
-            Istream&,
-            mType&
-        );
 
-        //- Write Matrix to Ostream.
-        friend Ostream& operator<< <Form, Type>
+    // Random Access Iterator (const)
+
+        //- Return const_iterator to begin traversing a constant Matrix
+        inline const_iterator cbegin() const;
+
+        //- Return const_iterator to end traversing a constant Matrix
+        inline const_iterator cend() const;
+
+        //- Return const_iterator to begin traversing a constant Matrix
+        inline const_iterator begin() const;
+
+        //- Return const_iterator to end traversing a constant Matrix
+        inline const_iterator end() const;
+
+
+    // IO
+
+        //- Read Matrix from Istream, discarding existing contents.
+        bool readMatrix(Istream& is);
+
+        //- Write Matrix, with line-breaks in ASCII when length exceeds
+        //- shortLen.
+        //  Using '0' suppresses line-breaks entirely.
+        Ostream& writeMatrix(Ostream& os, const label shortLen=0) const;
+
+
+    // Housekeeping
+
+        //- Deprecated(2019-04) raw data pointer, const access
+        //  \deprecated(2019-04) - use cdata() method
+        const Type* FOAM_DEPRECATED_FOR(2019-04, "cdata() method") v() const
+        {
+            return v_;
+        }
+
+        //- Deprecated(2019-04) raw data pointer, non-const access
+        //  \deprecated(2019-04) - use data() method
+        Type* FOAM_DEPRECATED_FOR(2019-04, "data() method") v()
+        {
+            return v_;
+        }
+
+        //- Deprecated(2019-04) - use subMatrix()
+        //  \deprecated(2019-04) - use subMatrix()
+        ConstMatrixBlock<mType>
+        FOAM_DEPRECATED_FOR(2019-04, "subMatrix() method") block
         (
-            Ostream&,
-            const mType&
-        );
+            const label m,
+            const label n,
+            const label mStart,
+            const label nStart
+        ) const
+        {
+            return this->subMatrix(mStart, nStart, m, n);
+        }
+
+        //- Deprecated(2019-04) - use subMatrix()
+        //  \deprecated(2019-04) - use subMatrix()
+        MatrixBlock<mType>
+        FOAM_DEPRECATED_FOR(2019-04, "subMatrix() method") block
+        (
+            const label m,
+            const label n,
+            const label mStart,
+            const label nStart
+        )
+        {
+            return this->subMatrix(mStart, nStart, m, n);
+        }
+
+
+        //- Deprecated(2019-04) - use subColumn()
+        //  \deprecated(2019-04) - use subColumn()
+        ConstMatrixBlock<mType>
+        FOAM_DEPRECATED_FOR(2019-04, "subColumn() method") col
+        (
+            const label m,
+            const label mStart,
+            const label nStart
+        ) const
+        {
+            return this->subColumn(nStart, mStart, m);
+        }
+
+        //- Deprecated(2019-04) - use subColumn()
+        //  \deprecated(2019-04) - use subColumn()
+        MatrixBlock<mType>
+        FOAM_DEPRECATED_FOR(2019-04, "subColumn() method") col
+        (
+            const label m,
+            const label mStart,
+            const label nStart
+        )
+        {
+            return this->subColumn(nStart, mStart, m);
+        }
+
+        //- Deleted(2019-04) - use subColumn()
+        //  \deprecated(2019-04) - use subColumn()
+        void col(const label m, const label rowStart) const = delete;
+
+        //- Deleted(2019-04) - use subColumn()
+        //  \deprecated(2019-04) - use subColumn()
+        void col(const label m, const label rowStart) = delete;
 };
 
 
-// Global functions and operators
+// * * * * * * * * * * * * * * * IOstream Operator  * * * * * * * * * * * * * //
 
+//- Read Matrix from Istream, discarding contents of existing Matrix.
 template<class Form, class Type>
-const Type& max(const Matrix<Form, Type>&);
+Istream& operator>>(Istream& is, Matrix<Form, Type>& mat);
 
+//- Write Matrix to Ostream, as per Matrix::writeMatrix() with
+//- default length, which is given by Detail::ListPolicy::short_length
 template<class Form, class Type>
-const Type& min(const Matrix<Form, Type>&);
+Ostream& operator<<(Ostream& os, const Matrix<Form, Type>& mat);
 
+
+// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * * //
+
+//- Find max value in Matrix
 template<class Form, class Type>
-Form operator-(const Matrix<Form, Type>&);
+const Type& max(const Matrix<Form, Type>& mat);
 
+//- Find min value in Matrix
+template<class Form, class Type>
+const Type& min(const Matrix<Form, Type>& mat);
+
+//- Find the min/max values of Matrix
+template<class Form, class Type>
+MinMax<Type> minMax(const Matrix<Form, Type>& mat);
+
+
+// * * * * * * * * * * * * * * * Global Operators * * * * * * * * * * * * * * //
+
+//- Matrix negation
+template<class Form, class Type>
+Form operator-(const Matrix<Form, Type>& mat);
+
+//- Matrix addition. Returns Matrix of the same form as the first parameter.
+template<class Form1, class Form2, class Type>
+Form1 operator+
+(
+    const Matrix<Form1, Type>& A,
+    const Matrix<Form2, Type>& B
+);
+
+//- Matrix subtraction. Returns Matrix of the same form as the first parameter.
+template<class Form1, class Form2, class Type>
+Form1 operator-
+(
+    const Matrix<Form1, Type>& A,
+    const Matrix<Form2, Type>& B
+);
+
+//- Scalar multiplication of Matrix
+template<class Form, class Type>
+Form operator*
+(
+    const Type& s,
+    const Matrix<Form, Type>& mat
+);
+
+//- Scalar addition of Matrix
 template<class Form, class Type>
 Form operator+
 (
-    const Matrix<Form, Type>&,
-    const Matrix<Form, Type>&
+    const Type& s,
+    const Matrix<Form, Type>& mat
 );
 
+//- Scalar subtraction of Matrix
 template<class Form, class Type>
 Form operator-
 (
-    const Matrix<Form, Type>&,
-    const Matrix<Form, Type>&
+    const Type& s,
+    const Matrix<Form, Type>& mat
 );
 
+//- Scalar multiplication of Matrix
 template<class Form, class Type>
 Form operator*
 (
-    const scalar,
-    const Matrix<Form, Type>&
+    const Matrix<Form, Type>& mat,
+    const Type& s
 );
 
+//- Scalar addition of Matrix
 template<class Form, class Type>
-Form operator*
+Form operator+
 (
-    const Matrix<Form, Type>&,
-    const scalar
+    const Matrix<Form, Type>& mat,
+    const Type& s
 );
 
+//- Scalar subtraction of Matrix
+template<class Form, class Type>
+Form operator-
+(
+    const Matrix<Form, Type>& mat,
+    const Type& s
+);
+
+//- Scalar division of Matrix
 template<class Form, class Type>
 Form operator/
 (
-    const Matrix<Form, Type>&,
-    const scalar
+    const Matrix<Form, Type>& mat,
+    const Type& s
 );
 
+//- Matrix-Matrix multiplication using ikj-algorithm
 template<class Form1, class Form2, class Type>
 typename typeOfInnerProduct<Type, Form1, Form2>::type
 operator*
 (
-    const Matrix<Form1, Type>& a,
-    const Matrix<Form2, Type>& b
+    const Matrix<Form1, Type>& A,
+    const Matrix<Form2, Type>& B
 );
 
+//- Matrix-vector multiplication (A * x), where x is a column vector
 template<class Form, class Type>
-tmp<Field<Type>> operator*
+inline tmp<Field<Type>> operator*
+(
+    const Matrix<Form, Type>& mat,
+    const UList<Type>& x
+);
+
+//- Matrix-vector multiplication (A * x), where x is a column vector
+template<class Form, class Type, class Addr>
+inline tmp<Field<Type>> operator*
+(
+    const Matrix<Form, Type>& mat,
+    const IndirectListBase<Type, Addr>& x
+);
+
+//- Vector-Matrix multiplication (x * A), where x is a row vector
+template<class Form, class Type>
+inline tmp<Field<Type>> operator*
+(
+    const UList<Type>& x,
+    const Matrix<Form, Type>& mat
+);
+
+//- Vector-Matrix multiplication (x * A), where x is a row vector
+template<class Form, class Type, class Addr>
+inline tmp<Field<Type>> operator*
+(
+    const IndirectListBase<Type, Addr>& x,
+    const Matrix<Form, Type>& mat
+);
+
+//- Implicit inner product of Matrix-Matrix, equivalent to A.T()*B
+template<class Form1, class Form2, class Type>
+typename typeOfInnerProduct<Type, Form1, Form2>::type
+operator&
+(
+    const Matrix<Form1, Type>& ATranspose,
+    const Matrix<Form2, Type>& B
+);
+
+//- Implicit outer product of Matrix-Matrix, equivalent to A*B.T()
+template<class Form1, class Form2, class Type>
+typename typeOfInnerProduct<Type, Form1, Form2>::type
+operator^
 (
-    const Matrix<Form, Type>&,
-    const Field<Type>&
+    const Matrix<Form1, Type>& A,
+    const Matrix<Form2, Type>& BTranspose
 );
 
 
diff --git a/src/OpenFOAM/matrices/Matrix/MatrixI.H b/src/OpenFOAM/matrices/Matrix/MatrixI.H
index bcc4a856752a9da4e142f4b4f7840c54857f8cbd..4c229fbd1879636c12dbf90a3f3238c7f406021e 100644
--- a/src/OpenFOAM/matrices/Matrix/MatrixI.H
+++ b/src/OpenFOAM/matrices/Matrix/MatrixI.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) 2011-2016 OpenFOAM Foundation
@@ -27,6 +27,20 @@ License
 
 #include "MatrixBlock.H"
 
+// * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * * //
+
+template<class Form, class Type>
+inline void Foam::Matrix<Form, Type>::doAlloc()
+{
+    const label len = size();
+
+    if (len)
+    {
+        v_ = new Type[len];
+    }
+}
+
+
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
 template<class Form, class Type>
@@ -39,8 +53,29 @@ inline Foam::Matrix<Form, Type>::Matrix()
 
 
 template<class Form, class Type>
-inline Foam::autoPtr<Foam::Matrix<Form, Type>> Foam::Matrix<Form, Type>::
-clone() const
+inline Foam::Matrix<Form, Type>::Matrix(const labelPair& dims)
+:
+    Matrix<Form, Type>(dims.first(), dims.second())
+{}
+
+
+template<class Form, class Type>
+inline Foam::Matrix<Form, Type>::Matrix(const labelPair& dims, const zero)
+:
+    Matrix<Form, Type>(dims.first(), dims.second(), Zero)
+{}
+
+
+template<class Form, class Type>
+inline Foam::Matrix<Form, Type>::Matrix(const labelPair& dims, const Type& val)
+:
+    Matrix<Form, Type>(dims.first(), dims.second(), val)
+{}
+
+
+template<class Form, class Type>
+inline Foam::autoPtr<Foam::Matrix<Form, Type>>
+Foam::Matrix<Form, Type>::clone() const
 {
     return autoPtr<Matrix<Form, Type>>::New(*this);
 }
@@ -56,14 +91,14 @@ inline const Foam::Matrix<Form, Type>& Foam::Matrix<Form, Type>::null()
 
 
 template<class Form, class Type>
-inline Foam::label Foam::Matrix<Form, Type>::m() const
+inline Foam::label Foam::Matrix<Form, Type>::m() const noexcept
 {
     return mRows_;
 }
 
 
 template<class Form, class Type>
-inline Foam::label Foam::Matrix<Form, Type>::n() const
+inline Foam::label Foam::Matrix<Form, Type>::n() const noexcept
 {
     return nCols_;
 }
@@ -72,216 +107,354 @@ inline Foam::label Foam::Matrix<Form, Type>::n() const
 template<class Form, class Type>
 inline Foam::label Foam::Matrix<Form, Type>::size() const
 {
-    return mRows_*nCols_;
+    return mRows_ * nCols_;
+}
+
+
+template<class Form, class Type>
+inline Foam::labelPair Foam::Matrix<Form, Type>::sizes() const
+{
+    return labelPair(mRows_, nCols_);
+}
+
+
+template<class Form, class Type>
+inline bool Foam::Matrix<Form, Type>::empty() const noexcept
+{
+    return !mRows_ || !nCols_;
 }
 
 
 template<class Form, class Type>
 inline void Foam::Matrix<Form, Type>::checki(const label i) const
 {
-    #ifdef FULLDEBUG
     if (!mRows_ || !nCols_)
     {
         FatalErrorInFunction
             << "Attempt to access element from empty matrix"
             << abort(FatalError);
     }
-    else if (i<0 || i>=mRows_)
+    if (i < 0 || mRows_ <= i)
     {
         FatalErrorInFunction
             << "Index " << i << " out of range 0 ... " << mRows_-1
             << abort(FatalError);
     }
-    #endif
 }
 
 
 template<class Form, class Type>
 inline void Foam::Matrix<Form, Type>::checkj(const label j) const
 {
-    #ifdef FULLDEBUG
     if (!mRows_ || !nCols_)
     {
         FatalErrorInFunction
             << "Attempt to access element from empty matrix"
             << abort(FatalError);
     }
-    else if (j<0 || j>=nCols_)
+    if (j < 0 || nCols_ <= j)
     {
         FatalErrorInFunction
             << "index " << j << " out of range 0 ... " << nCols_-1
             << abort(FatalError);
     }
-    #endif
 }
 
 
 template<class Form, class Type>
-inline const Type* Foam::Matrix<Form, Type>::v() const
+inline void Foam::Matrix<Form, Type>::checkSize() const
+{
+    if (mRows_ < 0 || nCols_ < 0)
+    {
+        FatalErrorInFunction
+            << "Incorrect size (" << mRows_ << ", " << nCols_ << ')' << nl
+            << abort(FatalError);
+    }
+    // Could also check for odd sizes, like (0, N) and make (0,0)
+}
+
+
+template<class Form, class Type>
+inline bool Foam::Matrix<Form, Type>::uniform() const
+{
+    const label len = size();
+
+    if (len == 0)
+    {
+        return false;
+    }
+
+    for (label idx = 1; idx < len; ++idx)
+    {
+        if (v_[0] != v_[idx])
+        {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+
+template<class Form, class Type>
+inline const Type* Foam::Matrix<Form, Type>::cdata() const noexcept
 {
     return v_;
 }
 
 
 template<class Form, class Type>
-inline Type* Foam::Matrix<Form, Type>::v()
+inline Type* Foam::Matrix<Form, Type>::data() noexcept
 {
     return v_;
 }
 
 
+template<class Form, class Type>
+inline const Type* Foam::Matrix<Form, Type>::rowData(const label irow) const
+{
+    #ifdef FULLDEBUG
+    checki(irow);
+    #endif
+    return (v_ + irow*nCols_);
+}
+
+
+template<class Form, class Type>
+inline Type* Foam::Matrix<Form, Type>::rowData(const label irow)
+{
+    #ifdef FULLDEBUG
+    checki(irow);
+    #endif
+    return (v_ + irow*nCols_);
+}
+
+
+template<class Form, class Type>
+inline const Type& Foam::Matrix<Form, Type>::at(const label idx) const
+{
+    #ifdef FULLDEBUG
+    if (idx < 0 || this->size() <= idx)
+    {
+        FatalErrorInFunction
+            << "index " << idx << " out of range 0 ... " << this->size()
+            << abort(FatalError);
+    }
+    #endif
+    return (v_ + idx);
+}
+
+
+template<class Form, class Type>
+inline Type& Foam::Matrix<Form, Type>::at(const label idx)
+{
+    #ifdef FULLDEBUG
+    if (idx < 0 || this->size() <= idx)
+    {
+        FatalErrorInFunction
+            << "index " << idx << " out of range 0 ... " << this->size()
+            << abort(FatalError);
+    }
+    #endif
+    return (v_ + idx);
+}
+
+
 template<class Form, class Type>
 inline Foam::ConstMatrixBlock<Foam::Matrix<Form, Type>>
-Foam::Matrix<Form, Type>::block
+Foam::Matrix<Form, Type>::subColumn
 (
-    const label m,
-    const label n,
-    const label mStart,
-    const label nStart
+    const label colIndex,
+    const label rowIndex,
+    label len
 ) const
 {
+    if (len < 0)
+    {
+        len = mRows_ - rowIndex;
+    }
+
     return ConstMatrixBlock<mType>
     (
         *this,
-        m,
-        n,
-        mStart,
-        nStart
+        len, // rows
+        1,
+        rowIndex,
+        colIndex
     );
 }
 
 
 template<class Form, class Type>
-template<class VectorSpace>
 inline Foam::ConstMatrixBlock<Foam::Matrix<Form, Type>>
-Foam::Matrix<Form, Type>::block
+Foam::Matrix<Form, Type>::subRow
 (
-    const label mStart,
-    const label nStart
+    const label rowIndex,
+    const label colIndex,
+    label len
 ) const
 {
+    if (len < 0)
+    {
+        len = nCols_ - colIndex;
+    }
+
     return ConstMatrixBlock<mType>
     (
         *this,
-        VectorSpace::mRows,
-        VectorSpace::nCols,
-        mStart,
-        nStart
+        1,
+        len, // columns
+        rowIndex,
+        colIndex
     );
 }
 
 
 template<class Form, class Type>
 inline Foam::ConstMatrixBlock<Foam::Matrix<Form, Type>>
-Foam::Matrix<Form, Type>::col
+Foam::Matrix<Form, Type>::subMatrix
 (
-    const label m,
-    const label mStart
+    const label rowIndex,
+    const label colIndex,
+    label szRows,
+    label szCols
 ) const
 {
+    if (szRows < 0) szRows = mRows_ - rowIndex;
+    if (szCols < 0) szCols = nCols_ - colIndex;
+
     return ConstMatrixBlock<mType>
     (
         *this,
-        m,
-        1,
-        mStart,
-        0
+        szRows,
+        szCols,
+        rowIndex,
+        colIndex
     );
 }
 
 
 template<class Form, class Type>
+template<class VectorSpace>
 inline Foam::ConstMatrixBlock<Foam::Matrix<Form, Type>>
-Foam::Matrix<Form, Type>::col
+Foam::Matrix<Form, Type>::block
 (
-    const label m,
-    const label mStart,
-    const label nStart
+    const label rowIndex,
+    const label colIndex
 ) const
 {
     return ConstMatrixBlock<mType>
     (
         *this,
-        m,
-        1,
-        mStart,
-        nStart
+        VectorSpace::mRows,
+        VectorSpace::nCols,
+        rowIndex,
+        colIndex
     );
 }
 
 
 template<class Form, class Type>
 inline Foam::MatrixBlock<Foam::Matrix<Form, Type>>
-Foam::Matrix<Form, Type>::block
+Foam::Matrix<Form, Type>::subColumn
 (
-    const label m,
-    const label n,
-    const label mStart,
-    const label nStart
+    const label colIndex,
+    const label rowIndex,
+    label len
 )
 {
+    if (len < 0)
+    {
+        len = mRows_ - rowIndex;
+    }
+
     return MatrixBlock<mType>
     (
         *this,
-        m,
-        n,
-        mStart,
-        nStart
+        len, // rows
+        1,
+        rowIndex,
+        colIndex
     );
 }
 
 
 template<class Form, class Type>
-template<class VectorSpace>
 inline Foam::MatrixBlock<Foam::Matrix<Form, Type>>
-Foam::Matrix<Form, Type>::block(const label mStart, const label nStart)
+Foam::Matrix<Form, Type>::subRow
+(
+    const label rowIndex,
+    const label colIndex,
+    label len
+)
 {
+    if (len < 0)
+    {
+        len = nCols_ - colIndex;
+    }
+
     return MatrixBlock<mType>
     (
         *this,
-        VectorSpace::mRows,
-        VectorSpace::nCols,
-        mStart,
-        nStart
+        1,
+        len, // columns
+        rowIndex,
+        colIndex
     );
 }
 
 
 template<class Form, class Type>
 inline Foam::MatrixBlock<Foam::Matrix<Form, Type>>
-Foam::Matrix<Form, Type>::col(const label m, const label mStart)
+Foam::Matrix<Form, Type>::subMatrix
+(
+    const label rowIndex,
+    const label colIndex,
+    label szRows,
+    label szCols
+)
 {
+    if (szRows < 0) szRows = mRows_ - rowIndex;
+    if (szCols < 0) szCols = nCols_ - colIndex;
+
     return MatrixBlock<mType>
     (
         *this,
-        m,
-        1,
-        mStart,
-        0
+        szRows,
+        szCols,
+        rowIndex,
+        colIndex
     );
 }
 
 
 template<class Form, class Type>
+template<class VectorSpace>
 inline Foam::MatrixBlock<Foam::Matrix<Form, Type>>
-Foam::Matrix<Form, Type>::col
+Foam::Matrix<Form, Type>::block
 (
-    const label m,
-    const label mStart,
-    const label nStart
+    const label rowIndex,
+    const label colIndex
 )
 {
     return MatrixBlock<mType>
     (
         *this,
-        m,
-        1,
-        mStart,
-        nStart
+        VectorSpace::mRows,
+        VectorSpace::nCols,
+        rowIndex,
+        colIndex
     );
 }
 
 
+template<class Form, class Type>
+inline void Foam::Matrix<Form, Type>::setSize(const label m, const label n)
+{
+    resize(m, n);
+}
+
+
 template<class Form, class Type>
 void Foam::Matrix<Form, Type>::shallowResize(const label m, const label n)
 {
@@ -290,47 +463,191 @@ void Foam::Matrix<Form, Type>::shallowResize(const label m, const label n)
 }
 
 
+template<class Form, class Type>
+inline Foam::tmp<Foam::Field<Type>> Foam::Matrix<Form, Type>::Amul
+(
+    const UList<Type>& x
+) const
+{
+    return this->AmulImpl(x);
+}
+
+
+template<class Form, class Type>
+template<class Addr>
+inline Foam::tmp<Foam::Field<Type>> Foam::Matrix<Form, Type>::Amul
+(
+    const IndirectListBase<Type, Addr>& x
+) const
+{
+    return this->AmulImpl(x);
+}
+
+
+template<class Form, class Type>
+inline Foam::tmp<Foam::Field<Type>> Foam::Matrix<Form, Type>::Tmul
+(
+    const UList<Type>& x
+) const
+{
+    return this->TmulImpl(x);
+}
+
+
+template<class Form, class Type>
+template<class Addr>
+inline Foam::tmp<Foam::Field<Type>> Foam::Matrix<Form, Type>::Tmul
+(
+    const IndirectListBase<Type, Addr>& x
+) const
+{
+    return this->TmulImpl(x);
+}
+
+
+// * * * * * * * * * * * * * * * * * Iterators * * * * * * * * * * * * * * * //
+
+template<class Form, class Type>
+inline typename Foam::Matrix<Form, Type>::iterator
+Foam::Matrix<Form, Type>::begin()
+{
+    return v_;
+}
+
+
+template<class Form, class Type>
+inline typename Foam::Matrix<Form, Type>::iterator
+Foam::Matrix<Form, Type>::end()
+{
+    return v_ + (mRows_ * nCols_);
+}
+
+
+template<class Form, class Type>
+inline typename Foam::Matrix<Form, Type>::const_iterator
+Foam::Matrix<Form, Type>::cbegin() const
+{
+    return v_;
+}
+
+
+template<class Form, class Type>
+inline typename Foam::Matrix<Form, Type>::const_iterator
+Foam::Matrix<Form, Type>::cend() const
+{
+    return v_ + (mRows_ * nCols_);
+}
+
+
+template<class Form, class Type>
+inline typename Foam::Matrix<Form, Type>::const_iterator
+Foam::Matrix<Form, Type>::begin() const
+{
+    return v_;
+}
+
+
+template<class Form, class Type>
+inline typename Foam::Matrix<Form, Type>::const_iterator
+Foam::Matrix<Form, Type>::end() const
+{
+    return v_ + (mRows_ * nCols_);
+}
+
+
 // * * * * * * * * * * * * * * * Member Operators  * * * * * * * * * * * * * //
 
 template<class Form, class Type>
 inline const Type& Foam::Matrix<Form, Type>::operator()
 (
-    const label i,
-    const label j
+    const label irow,
+    const label jcol
 ) const
 {
-    checki(i);
-    checkj(j);
-    return v_[i*nCols_ + j];
+    #ifdef FULLDEBUG
+    checki(irow);
+    checkj(jcol);
+    #endif
+    return v_[irow*nCols_ + jcol];
 }
 
 
 template<class Form, class Type>
 inline Type& Foam::Matrix<Form, Type>::operator()
 (
-    const label i,
-    const label j
+    const label irow,
+    const label jcol
 )
 {
-    checki(i);
-    checkj(j);
-    return v_[i*nCols_ + j];
+    #ifdef FULLDEBUG
+    checki(irow);
+    checkj(jcol);
+    #endif
+    return v_[irow*nCols_ + jcol];
 }
 
 
 template<class Form, class Type>
-inline const Type* Foam::Matrix<Form, Type>::operator[](const label i) const
+inline const Type* Foam::Matrix<Form, Type>::operator[](const label irow) const
 {
-    checki(i);
-    return v_ + i*nCols_;
+    #ifdef FULLDEBUG
+    checki(irow);
+    #endif
+    return v_ + irow*nCols_;
+}
+
+
+template<class Form, class Type>
+inline Type* Foam::Matrix<Form, Type>::operator[](const label irow)
+{
+    #ifdef FULLDEBUG
+    checki(irow);
+    #endif
+    return v_ + irow*nCols_;
 }
 
 
 template<class Form, class Type>
-inline Type* Foam::Matrix<Form, Type>::operator[](const label i)
+inline Foam::tmp<Foam::Field<Type>> Foam::operator*
+(
+    const Matrix<Form, Type>& mat,
+    const UList<Type>& x
+)
+{
+    return mat.Amul(x);
+}
+
+
+template<class Form, class Type, class Addr>
+inline Foam::tmp<Foam::Field<Type>> Foam::operator*
+(
+    const Matrix<Form, Type>& mat,
+    const IndirectListBase<Type, Addr>& x
+)
+{
+    return mat.Amul(x);
+}
+
+
+template<class Form, class Type>
+inline Foam::tmp<Foam::Field<Type>> Foam::operator*
+(
+    const UList<Type>& x,
+    const Matrix<Form, Type>& mat
+)
+{
+    return mat.Tmul(x);
+}
+
+
+template<class Form, class Type, class Addr>
+inline Foam::tmp<Foam::Field<Type>> Foam::operator*
+(
+    const IndirectListBase<Type, Addr>& x,
+    const Matrix<Form, Type>& mat
+)
 {
-    checki(i);
-    return v_ + i*nCols_;
+    return mat.Tmul(x);
 }
 
 
diff --git a/src/OpenFOAM/matrices/Matrix/MatrixIO.C b/src/OpenFOAM/matrices/Matrix/MatrixIO.C
index e4628fbc090001c0004d93ecbbe8aeb9e4b5a833..9b93656bb61c359079c4922c9cf304bccf3007b0 100644
--- a/src/OpenFOAM/matrices/Matrix/MatrixIO.C
+++ b/src/OpenFOAM/matrices/Matrix/MatrixIO.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) 2011-2016 OpenFOAM Foundation
@@ -30,6 +30,8 @@ License
 #include "Ostream.H"
 #include "token.H"
 #include "contiguous.H"
+#include "ListPolicy.H"
+#include <algorithm>
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
@@ -45,26 +47,25 @@ Foam::Matrix<Form, Type>::Matrix(Istream& is)
 
 
 template<class Form, class Type>
-Foam::Istream& Foam::operator>>(Istream& is, Matrix<Form, Type>& M)
+bool Foam::Matrix<Form, Type>::readMatrix(Istream& is)
 {
     // Anull matrix
-    M.clear();
+    clear();
 
     is.fatalCheck(FUNCTION_NAME);
 
     token firstToken(is);
 
-    is.fatalCheck
-    (
-        "operator>>(Istream&, Matrix<Form, Type>&) : reading first token"
-    );
+    is.fatalCheck("readMatrix : reading first token");
 
     if (firstToken.isLabel())
     {
-        M.mRows_ = firstToken.labelToken();
-        M.nCols_ = readLabel(is);
+        mRows_ = firstToken.labelToken();
+        nCols_ = readLabel(is);
+        doAlloc();
 
-        label mn = M.mRows_*M.nCols_;
+        // The total size
+        const label len = size();
 
         // Read list contents depending on data format
         if (is.format() == IOstream::ASCII || !contiguous<Type>())
@@ -72,29 +73,22 @@ Foam::Istream& Foam::operator>>(Istream& is, Matrix<Form, Type>& M)
             // Read beginning of contents
             char listDelimiter = is.readBeginList("Matrix");
 
-            if (mn)
+            if (len)
             {
-                M.allocate();
-                Type* v = M.v_;
-
                 if (listDelimiter == token::BEGIN_LIST)
                 {
-                    label k = 0;
+                    label idx = 0;
 
-                    // loop over rows
-                    for (label i=0; i<M.m(); i++)
+                    // Loop over rows
+                    for (label i = 0; i < mRows_; ++i)
                     {
                         listDelimiter = is.readBeginList("MatrixRow");
 
-                        for (label j=0; j<M.n(); j++)
+                        for (label j = 0; j < nCols_; ++j)
                         {
-                            is >> v[k++];
+                            is >> v_[idx++];
 
-                            is.fatalCheck
-                            (
-                                "operator>>(Istream&, Matrix<Form, Type>&) : "
-                                "reading entry"
-                            );
+                            is.fatalCheck("readMatrix : reading reading entry");
                         }
 
                         is.readEndList("MatrixRow");
@@ -105,16 +99,9 @@ Foam::Istream& Foam::operator>>(Istream& is, Matrix<Form, Type>& M)
                     Type element;
                     is >> element;
 
-                    is.fatalCheck
-                    (
-                        "operator>>(Istream&, Matrix<Form, Type>&) : "
-                        "reading the single entry"
-                    );
+                    is.fatalCheck("readMatrix : reading the single entry");
 
-                    for (label i=0; i<mn; i++)
-                    {
-                        v[i] = element;
-                    }
+                    std::fill(begin(), end(), element);
                 }
             }
 
@@ -123,89 +110,72 @@ Foam::Istream& Foam::operator>>(Istream& is, Matrix<Form, Type>& M)
         }
         else
         {
-            if (mn)
+            if (len)
             {
-                M.allocate();
-                Type* v = M.v_;
+                is.read(reinterpret_cast<char*>(v_), len*sizeof(Type));
 
-                is.read(reinterpret_cast<char*>(v), mn*sizeof(Type));
-
-                is.fatalCheck
-                (
-                    "operator>>(Istream&, Matrix<Form, Type>&) : "
-                    "reading the binary block"
-                );
+                is.fatalCheck("readMatrix : reading the binary block");
             }
         }
-    }
-    else
-    {
-        FatalIOErrorInFunction(is)
-            << "incorrect first token, expected <int>, found "
-            << firstToken.info()
-            << exit(FatalIOError);
+
+        return len;
     }
 
-    return is;
+
+    FatalIOErrorInFunction(is)
+        << "incorrect first token, expected <int>, found "
+        << firstToken.info()
+        << exit(FatalIOError);
+
+    return 0;
 }
 
 
 template<class Form, class Type>
-Foam::Ostream& Foam::operator<<(Ostream& os, const Matrix<Form, Type>& M)
+Foam::Ostream& Foam::Matrix<Form, Type>::writeMatrix
+(
+    Ostream& os,
+    const label shortLen
+) const
 {
-    label mn = M.mRows_*M.nCols_;
+    const Matrix<Form, Type>& mat = *this;
 
-    os  << M.m() << token::SPACE << M.n();
+    // The total size
+    const label len = mat.size();
+
+    // Rows, columns size
+    os  << mat.m() << token::SPACE << mat.n();
 
     // Write list contents depending on data format
     if (os.format() == IOstream::ASCII || !contiguous<Type>())
     {
-        if (mn)
+        if (len)
         {
-            const Type* v = M.v_;
+            const Type* v = mat.cdata();
 
-            // can the contents be considered 'uniform' (ie, identical)
-            bool uniform = (mn > 1 && contiguous<Type>());
-            if (uniform)
+            // Can the contents be considered 'uniform' (ie, identical)
+            if (len > 1 && contiguous<Type>() && mat.uniform())
             {
-                for (label i=0; i<mn; ++i)
-                {
-                    if (v[i] != v[0])
-                    {
-                        uniform = false;
-                        break;
-                    }
-                }
+                // Two or more entries, and all entries have identical values.
+                os  << token::BEGIN_BLOCK << v[0] << token::END_BLOCK;
             }
-
-            if (uniform)
-            {
-                // Write start delimiter
-                os  << token::BEGIN_BLOCK;
-
-                // Write contents
-                os << v[0];
-
-                // Write end delimiter
-                os << token::END_BLOCK;
-            }
-            else if (mn < 10 && contiguous<Type>())
+            else if (len < shortLen && contiguous<Type>())
             {
                 // Write start contents delimiter
                 os  << token::BEGIN_LIST;
 
-                label k = 0;
+                label idx = 0;
 
-                // loop over rows
-                for (label i=0; i<M.m(); i++)
+                // Loop over rows
+                for (label i = 0; i < mat.m(); ++i)
                 {
                     os  << token::BEGIN_LIST;
 
                     // Write row
-                    for (label j=0; j< M.n(); j++)
+                    for (label j = 0; j < mat.n(); ++j)
                     {
                         if (j) os << token::SPACE;
-                        os << v[k++];
+                        os << v[idx++];
                     }
 
                     os << token::END_LIST;
@@ -219,17 +189,17 @@ Foam::Ostream& Foam::operator<<(Ostream& os, const Matrix<Form, Type>& M)
                 // Write start contents delimiter
                 os  << nl << token::BEGIN_LIST;
 
-                label k = 0;
+                label idx = 0;
 
-                // loop over rows
-                for (label i=0; i<M.m(); i++)
+                // Loop over rows
+                for (label i=0; i < mat.m(); ++i)
                 {
                     os  << nl << token::BEGIN_LIST;
 
                     // Write row
-                    for (label j=0; j< M.n(); j++)
+                    for (label j=0; j < mat.n(); ++j)
                     {
-                        os << nl << v[k++];
+                        os << nl << v[idx++];
                     }
 
                     os << nl << token::END_LIST;
@@ -246,9 +216,16 @@ Foam::Ostream& Foam::operator<<(Ostream& os, const Matrix<Form, Type>& M)
     }
     else
     {
-        if (mn)
+        // Contents are binary and contiguous
+
+        if (len)
         {
-            os.write(reinterpret_cast<const char*>(M.v_), mn*sizeof(Type));
+            // write(...) includes surrounding start/end delimiters
+            os.write
+            (
+                reinterpret_cast<const char*>(mat.cdata()),
+                len*sizeof(Type)
+            );
         }
     }
 
@@ -257,4 +234,19 @@ Foam::Ostream& Foam::operator<<(Ostream& os, const Matrix<Form, Type>& M)
 }
 
 
+template<class Form, class Type>
+Foam::Istream& Foam::operator>>(Istream& is, Matrix<Form, Type>& mat)
+{
+    mat.readMatrix(is);
+    return is;
+}
+
+
+template<class Form, class Type>
+Foam::Ostream& Foam::operator<<(Ostream& os, const Matrix<Form, Type>& mat)
+{
+    return mat.writeMatrix(os, Detail::ListPolicy::short_length<Type>::value);
+}
+
+
 // ************************************************************************* //
diff --git a/src/OpenFOAM/matrices/Matrix/MatrixTools.C b/src/OpenFOAM/matrices/Matrix/MatrixTools.C
new file mode 100644
index 0000000000000000000000000000000000000000..5ce736cdf3980a003a81c8bf5635474d125953d2
--- /dev/null
+++ b/src/OpenFOAM/matrices/Matrix/MatrixTools.C
@@ -0,0 +1,136 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2019 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 <http://www.gnu.org/licenses/>.
+
+\*---------------------------------------------------------------------------*/
+
+#include "MatrixTools.H"
+
+// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * * //
+
+template<class Form1, class Form2, class Type>
+bool Foam::MatrixTools::equal
+(
+    const Matrix<Form1, Type>& A,
+    const Matrix<Form2, Type>& B,
+    const bool verbose,
+    const scalar relTol,
+    const scalar absTol
+)
+{
+    const label len = A.size();
+
+    if (len != B.size())
+    {
+        if (verbose)
+        {
+            Info<< "Matrices have different sizes: "
+                << len << " vs " << B.size() << nl;
+        }
+        return false;
+    }
+
+    auto iter1 = A.cbegin();
+    auto iter2 = B.cbegin();
+
+    for (label i = 0; i < len; ++i)
+    {
+        if ((absTol + relTol*mag(*iter2)) < Foam::mag(*iter1 - *iter2))
+        {
+            if (verbose)
+            {
+                Info<< "Matrix element " << i
+                    << " differs beyond tolerance: "
+                    << *iter1 << " vs " << *iter2 << nl;
+            }
+            return false;
+        }
+
+        ++iter1;
+        ++iter2;
+    }
+
+    if (verbose)
+    {
+        Info<< "All elements equal within the tolerances" << nl;
+    }
+
+    return true;
+}
+
+
+template<class Container>
+Foam::Ostream& Foam::MatrixTools::printMatrix
+(
+    Ostream& os,
+    const Container& mat
+)
+{
+    os  << mat.m() << ' ' << mat.n();
+
+    if (mat.m() == 1)
+    {
+        // row-vector
+        os  << " (";
+        for (label j = 0; j < mat.n(); ++j)
+        {
+            if (j) os  << ' ';
+            os  << mat(0,j);
+        }
+        os  << ')' << nl;
+    }
+    else if (mat.n() == 1)
+    {
+        // col-vector
+
+        os  << " (";
+        for (label i = 0; i < mat.m(); ++i)
+        {
+            if (i) os  << ' ';
+            os  << mat(i,0);
+        }
+        os  << ')' << nl;
+    }
+    else
+    {
+        // Regular
+
+        os  << nl << '(' << nl;
+
+        for (label i = 0; i < mat.m(); ++i)
+        {
+            os  << '(';
+            for (label j = 0; j < mat.n(); ++j)
+            {
+                if (j) os  << ' ';
+                os  << mat(i,j);
+            }
+            os  << ')' << nl;
+        }
+        os  << ')' << nl;
+    }
+
+    return os;
+}
+
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/matrices/Matrix/MatrixTools.H b/src/OpenFOAM/matrices/Matrix/MatrixTools.H
new file mode 100644
index 0000000000000000000000000000000000000000..8c63efc0fe0d2ba349caefb4e73d26fb350ac97e
--- /dev/null
+++ b/src/OpenFOAM/matrices/Matrix/MatrixTools.H
@@ -0,0 +1,90 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2019 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 <http://www.gnu.org/licenses/>.
+
+Namespace
+    Foam::MatrixTools
+
+Description
+    Collection of static functions for matrix-related verifications.
+
+SourceFiles
+    MatrixTools.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef MatrixTools_H
+#define MatrixTools_H
+
+#include "Matrix.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+// Forward declarations
+class Ostream;
+
+
+/*---------------------------------------------------------------------------*\
+                       Namespace MatrixTools Declaration
+\*---------------------------------------------------------------------------*/
+
+namespace MatrixTools
+{
+
+//- Compare matrix elements for absolute or relative equality
+template<class Form1, class Form2, class Type>
+bool equal
+(
+    const Matrix<Form1, Type>& A,
+    const Matrix<Form2, Type>& B,
+    const bool verbose = false,
+    const scalar relTol = 1e-5,
+    const scalar absTol = 1e-8
+);
+
+
+//- Simple ASCII output of Matrix, MatrixBlock
+template<class Container>
+Ostream& printMatrix(Ostream& os, const Container& mat);
+
+
+} // End namespace MatrixTools
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#ifdef NoRepository
+    #include "MatrixTools.C"
+#endif
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/matrices/MatrixBlock/MatrixBlock.C b/src/OpenFOAM/matrices/MatrixBlock/MatrixBlock.C
index c60aaba83dea175efd2245cac3de10c5cc084d55..7ced3ca8de125530acbffb654e374810de26d053 100644
--- a/src/OpenFOAM/matrices/MatrixBlock/MatrixBlock.C
+++ b/src/OpenFOAM/matrices/MatrixBlock/MatrixBlock.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           |
+    \\  /    A nd           | Copyright (C) 2004-2010, 2019 OpenCFD Ltd.
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
                             | Copyright (C) 2016 OpenFOAM Foundation
@@ -71,6 +71,76 @@ Foam::MatrixBlock<MatrixType>::operator Field<cmptType>() const
 }
 
 
+template<class MatrixType>
+Foam::label Foam::ConstMatrixBlock<MatrixType>::disallow
+(
+    const char* what
+) const
+{
+    FatalErrorInFunction
+        << "Block addresses " << what
+        << " outside matrix or invalid matrix components"
+        << abort(FatalError);
+    return 0;
+}
+
+
+template<class MatrixType>
+Foam::label Foam::MatrixBlock<MatrixType>::disallow
+(
+    const char* what
+) const
+{
+    FatalErrorInFunction
+        << "Block addresses " << what
+        << " outside matrix or invalid matrix components"
+        << abort(FatalError);
+    return 0;
+}
+
+
+template<class MatrixType> void Foam::ConstMatrixBlock<MatrixType>::checkIndex
+(
+    const label i,
+    const label j
+) const
+{
+    if (i < 0 || i >= mRows_)
+    {
+        FatalErrorInFunction
+            << "Index " << i << " is out of range 0 ... " << mRows_ - 1
+            << abort(FatalError);
+    }
+    else if (j < 0 || j >= nCols_)
+    {
+        FatalErrorInFunction
+            << "Index " << j << " is out of range 0 ... " << nCols_ - 1
+            << abort(FatalError);
+    }
+}
+
+
+template<class MatrixType> void Foam::MatrixBlock<MatrixType>::checkIndex
+(
+    const label i,
+    const label j
+) const
+{
+    if (i < 0 || i >= mRows_)
+    {
+        FatalErrorInFunction
+            << "Index " << i << " is out of range 0 ... " << mRows_ - 1
+            << abort(FatalError);
+    }
+    else if (j < 0 || j >= nCols_)
+    {
+        FatalErrorInFunction
+            << "Index " << j << " is out of range 0 ... " << nCols_ - 1
+            << abort(FatalError);
+    }
+}
+
+
 // * * * * * * * * * * * * * * * Member Operators  * * * * * * * * * * * * * //
 
 template<class MatrixType>
@@ -89,9 +159,9 @@ void Foam::MatrixBlock<MatrixType>::operator=
             << abort(FatalError);
     }
 
-    for (label i=0; i<mRows_; i++)
+    for (label i = 0; i < mRows_; ++i)
     {
-        for (label j=0; j<nCols_; j++)
+        for (label j = 0; j < nCols_; ++j)
         {
             (*this)(i, j) = Mb(i, j);
         }
@@ -116,9 +186,9 @@ void Foam::MatrixBlock<MatrixType>::operator=
                 << abort(FatalError);
         }
 
-        for (label i=0; i<mRows_; i++)
+        for (label i = 0; i < mRows_; ++i)
         {
-            for (label j=0; j<nCols_; j++)
+            for (label j = 0; j < nCols_; ++j)
             {
                 (*this)(i, j) = Mb(i, j);
             }
@@ -144,9 +214,9 @@ void Foam::MatrixBlock<MatrixType>::operator=
                 << abort(FatalError);
         }
 
-        for (label i=0; i<mRows_; i++)
+        for (label i = 0; i < mRows_; ++i)
         {
-            for (label j=0; j<nCols_; j++)
+            for (label j = 0; j < nCols_; ++j)
             {
                 (*this)(i, j) = Mb(i, j);
             }
@@ -173,9 +243,9 @@ void Foam::MatrixBlock<MatrixType>::operator=
                 << abort(FatalError);
         }
 
-        for (label i=0; i<mRows_; i++)
+        for (label i = 0; i < mRows_; ++i)
         {
-            for (label j=0; j<nCols_; j++)
+            for (label j = 0; j < nCols_; ++j)
             {
                 (*this)(i, j) = Mb(i, j);
             }
@@ -202,9 +272,9 @@ void Foam::MatrixBlock<MatrixType>::operator=
                 << abort(FatalError);
         }
 
-        for (label i=0; i<mRows_; i++)
+        for (label i = 0; i < mRows_; ++i)
         {
-            for (label j=0; j<nCols_; j++)
+            for (label j = 0; j < nCols_; ++j)
             {
                 (*this)(i, j) = Mb(i, j);
             }
@@ -235,9 +305,9 @@ void Foam::MatrixBlock<MatrixType>::operator=
             << abort(FatalError);
     }
 
-    for (direction i=0; i<mRows_; ++i)
+    for (direction i = 0; i < mRows_; ++i)
     {
-        for (direction j=0; j<nCols_; ++j)
+        for (direction j = 0; j < nCols_; ++j)
         {
             operator()(i, j) = Mb(i, j);
         }
@@ -266,7 +336,7 @@ void Foam::MatrixBlock<MatrixType>::operator=
             << abort(FatalError);
     }
 
-    for (direction i=0; i<mRows_; ++i)
+    for (direction i = 0; i < mRows_; ++i)
     {
         operator()(i, 0) = Mb[i];
     }
@@ -289,9 +359,9 @@ void Foam::MatrixBlock<MatrixType>::operator=
             << abort(FatalError);
     }
 
-    for (label i=0; i<mRows_; i++)
+    for (label i = 0; i < mRows_; ++i)
     {
-        for (label j=0; j<nCols_; j++)
+        for (label j = 0; j < nCols_; ++j)
         {
             (*this)(i, j) = ms(i, j);
         }
@@ -315,7 +385,7 @@ void Foam::MatrixBlock<MatrixType>::operator=
             << abort(FatalError);
     }
 
-    for (direction i=0; i<Ncmpts; ++i)
+    for (direction i = 0; i < Ncmpts; ++i)
     {
         operator()(i, 0) = ms[i];
     }
diff --git a/src/OpenFOAM/matrices/MatrixBlock/MatrixBlock.H b/src/OpenFOAM/matrices/MatrixBlock/MatrixBlock.H
index d2b3d119aca855c215c2de33b72c81aba6d5d5c4..bb3cf1d95e9194888cbda316528628445c7e7867 100644
--- a/src/OpenFOAM/matrices/MatrixBlock/MatrixBlock.H
+++ b/src/OpenFOAM/matrices/MatrixBlock/MatrixBlock.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           |
+    \\  /    A nd           | Copyright (C) 2004-2010, 2019 OpenCFD Ltd.
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
                             | Copyright (C) 2016 OpenFOAM Foundation
@@ -60,19 +60,26 @@ namespace Foam
 template<class MatrixType>
 class ConstMatrixBlock
 {
-    // Private data
+    // Private Data
 
         //- Const reference to the parent matrix
         const MatrixType& matrix_;
 
-        // Block size
+        //- Block size
         const label mRows_;
         const label nCols_;
 
-        // Block location in parent matrix
+        //- Block location in parent matrix
         const label rowStart_;
         const label colStart_;
 
+
+    // Private Member Functions
+
+        //- Error message for failed sanity checks during matrix construction
+        label disallow(const char *what) const;
+
+
 public:
 
     typedef typename MatrixType::cmptType cmptType;
@@ -98,6 +105,9 @@ public:
         //- Return the number of columns in the block
         inline label n() const;
 
+        //- Return row/column sizes
+        inline labelPair sizes() const;
+
         //- (i, j) const element access operator
         inline const cmptType& operator()
         (
@@ -107,6 +117,9 @@ public:
 
         //- Convert a column of a matrix to a Field
         operator Field<cmptType>() const;
+
+        //- Check if (i, j) is within range of row-column limits
+        void checkIndex(const label i, const label j) const;
 };
 
 
@@ -117,19 +130,26 @@ public:
 template<class MatrixType>
 class MatrixBlock
 {
-    // Private data
+    // Private Data
 
         //- Reference to the parent matrix
         MatrixType& matrix_;
 
-        // Block size
+        //- Block size
         const label mRows_;
         const label nCols_;
 
-        // Block location in parent matrix
+        //- Block location in parent matrix
         const label rowStart_;
         const label colStart_;
 
+
+    // Private Member Functions
+
+        //- Error message for failed sanity checks during matrix construction
+        label disallow(const char *what) const;
+
+
 public:
 
     typedef typename MatrixType::cmptType cmptType;
@@ -155,6 +175,9 @@ public:
         //- Return the number of columns in the block
         inline label n() const;
 
+        //- Return row/column sizes
+        inline labelPair sizes() const;
+
         //- (i, j) const element access operator
         inline const cmptType& operator()
         (
@@ -168,8 +191,11 @@ public:
         //- Convert a column of a matrix to a Field
         operator Field<cmptType>() const;
 
+        //- Check if (i, j) is within range of row-column limits
+        void checkIndex(const label i, const label j) const;
+
 
-    // Member operators
+    // Member Operators
 
         //- Assignment to a compatible matrix
         template<class Form>
diff --git a/src/OpenFOAM/matrices/MatrixBlock/MatrixBlockI.H b/src/OpenFOAM/matrices/MatrixBlock/MatrixBlockI.H
index 9ac2f2977e8da8d9f1dddb97d8f74a12eede9296..e6a47e0ba4c63e6c7f363750a7bb1ce689d8b959 100644
--- a/src/OpenFOAM/matrices/MatrixBlock/MatrixBlockI.H
+++ b/src/OpenFOAM/matrices/MatrixBlock/MatrixBlockI.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           |
+    \\  /    A nd           | Copyright (C) 2004-2010, 2019 OpenCFD Ltd.
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
                             | Copyright (C) 2016 OpenFOAM Foundation
@@ -38,24 +38,21 @@ Foam::ConstMatrixBlock<MatrixType>::ConstMatrixBlock
 )
 :
     matrix_(matrix),
-    mRows_(m),
-    nCols_(n),
-    rowStart_(mStart),
-    colStart_(nStart)
-{
-    #ifdef FULLDEBUG
-    if
+    mRows_(0 < m ? m : disallow("row dim")),
+    nCols_(0 < n ? n : disallow("col dim")),
+    rowStart_
+    (
+        0 <= mStart
+     || mStart + mRows_ <= matrix.m()
+     ?  mStart : disallow("row start")
+    ),
+    colStart_
     (
-        rowStart_ + mRows_ > matrix.m()
-     || colStart_ + nCols_ > matrix.n()
+        0 <= nStart
+     || nStart + nCols_ <= matrix.n()
+     ?  nStart : disallow("col start")
     )
-    {
-        FatalErrorInFunction
-            << "Block addresses outside matrix"
-            << abort(FatalError);
-    }
-    #endif
-}
+{}
 
 
 template<class MatrixType>
@@ -69,24 +66,21 @@ Foam::MatrixBlock<MatrixType>::MatrixBlock
 )
 :
     matrix_(matrix),
-    mRows_(m),
-    nCols_(n),
-    rowStart_(mStart),
-    colStart_(nStart)
-{
-    #ifdef FULLDEBUG
-    if
+    mRows_(0 < m ? m : disallow("row dim")),
+    nCols_(0 < n ? n : disallow("col dim")),
+    rowStart_
+    (
+        0 <= mStart
+     || mStart + mRows_ <= matrix.m()
+     ?  mStart : disallow("row start")
+    ),
+    colStart_
     (
-        rowStart_ + mRows_ > matrix.m()
-     || colStart_ + nCols_ > matrix.n()
+        0 <= nStart
+     || nStart + nCols_ <= matrix.n()
+     ?  nStart : disallow("col start")
     )
-    {
-        FatalErrorInFunction
-            << "Block addresses outside matrix"
-            << abort(FatalError);
-    }
-    #endif
-}
+{}
 
 
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
@@ -119,6 +113,20 @@ inline Foam::label Foam::MatrixBlock<MatrixType>::n() const
 }
 
 
+template<class MatrixType>
+inline Foam::labelPair Foam::ConstMatrixBlock<MatrixType>::sizes() const
+{
+    return labelPair(mRows_, nCols_);
+}
+
+
+template<class MatrixType>
+inline Foam::labelPair Foam::MatrixBlock<MatrixType>::sizes() const
+{
+    return labelPair(mRows_, nCols_);
+}
+
+
 // * * * * * * * * * * * * * * * Member Operators  * * * * * * * * * * * * * //
 
 template<class MatrixType>
@@ -130,18 +138,7 @@ Foam::ConstMatrixBlock<MatrixType>::operator()
 ) const
 {
     #ifdef FULLDEBUG
-    if (i<0 || i>=mRows_)
-    {
-        FatalErrorInFunction
-            << "Index " << i << " out of range 0 ... " << mRows_-1
-            << abort(FatalError);
-    }
-    if (j<0 || j>=nCols_)
-    {
-        FatalErrorInFunction
-            << "Index " << j << " out of range 0 ... " << nCols_-1
-            << abort(FatalError);
-    }
+    checkIndex(i, j);
     #endif
 
     return matrix_(i + rowStart_, j + colStart_);
@@ -157,18 +154,7 @@ Foam::MatrixBlock<MatrixType>::operator()
 ) const
 {
     #ifdef FULLDEBUG
-    if (i<0 || i>=mRows_)
-    {
-        FatalErrorInFunction
-            << "Index " << i << " out of range 0 ... " << mRows_-1
-            << abort(FatalError);
-    }
-    if (j<0 || j>=nCols_)
-    {
-        FatalErrorInFunction
-            << "Index " << j << " out of range 0 ... " << nCols_-1
-            << abort(FatalError);
-    }
+    checkIndex(i, j);
     #endif
 
     return matrix_(i + rowStart_, j + colStart_);
@@ -184,18 +170,7 @@ Foam::MatrixBlock<MatrixType>::operator()
 )
 {
     #ifdef FULLDEBUG
-    if (i<0 || i>=mRows_)
-    {
-        FatalErrorInFunction
-            << "Index " << i << " out of range 0 ... " << mRows_-1
-            << abort(FatalError);
-    }
-    if (j<0 || j>=nCols_)
-    {
-        FatalErrorInFunction
-            << "Index " << j << " out of range 0 ... " << nCols_-1
-            << abort(FatalError);
-    }
+    checkIndex(i, j);
     #endif
 
     return matrix_(i + rowStart_, j + colStart_);
diff --git a/src/OpenFOAM/matrices/QRMatrix/QRMatrix.C b/src/OpenFOAM/matrices/QRMatrix/QRMatrix.C
index 75cd80a05271ad148c3a887d6d2d6d4fd50b5b68..624db7b7dcd0dc6e87378bb16c940bee028e8f18 100644
--- a/src/OpenFOAM/matrices/QRMatrix/QRMatrix.C
+++ b/src/OpenFOAM/matrices/QRMatrix/QRMatrix.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) 2016 OpenFOAM Foundation
@@ -30,22 +30,22 @@ License
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
 template<class MatrixType>
-Foam::QRMatrix<MatrixType>::QRMatrix(const MatrixType& M)
+Foam::QRMatrix<MatrixType>::QRMatrix(const MatrixType& mat)
 {
-    decompose(M);
+    decompose(mat);
 }
 
 
 // * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * * //
 
 template<class MatrixType>
-void Foam::QRMatrix<MatrixType>::decompose(const MatrixType& M)
+void Foam::QRMatrix<MatrixType>::decompose(const MatrixType& mat)
 {
-    const label m = M.m();
-    const label n = M.n();
+    const label m = mat.m();
+    const label n = mat.n();
 
     // Initialize the R-matrix to M
-    R_ = M;
+    R_ = mat;
 
     // Initialize the Q-matrix to I
     Q_.setSize(m);
@@ -158,18 +158,19 @@ void Foam::QRMatrix<MatrixType>::decompose(const MatrixType& M)
 
 
 template<class MatrixType>
+template<template<typename> class ListContainer>
 void Foam::QRMatrix<MatrixType>::solvex
 (
-    Field<cmptType>& x
+    ListContainer<cmptType>& x
 ) const
 {
     const label n = R_.n();
 
-    for (int i=n-1; i>=0; i--)
+    for (label i = n - 1; i >= 0; --i)
     {
         cmptType sum = x[i];
 
-        for (label j=i+1; j<n; j++)
+        for (label j = i + 1; j < n; ++j)
         {
             sum -= x[j]*R_(i, j);
         }
@@ -187,19 +188,21 @@ void Foam::QRMatrix<MatrixType>::solvex
 
 
 template<class MatrixType>
-void Foam::QRMatrix<MatrixType>::solve
+template<template<typename> class ListContainer>
+void Foam::QRMatrix<MatrixType>::solveImpl
 (
-    Field<cmptType>& x,
-    const Field<cmptType>& source
+    List<cmptType>& x,
+    const ListContainer<cmptType>& source
 ) const
 {
+    // Assert (&x != &source) ?
     const label m = Q_.m();
 
-    // x = Q_.T()*source;
-    for (label i=0; i<m; i++)
+    // x = Q_.T()*source;  ie, Q_.Tmul(source)
+    for (label i = 0; i < m; ++i)
     {
         x[i] = 0;
-        for (label j=0; j<m; j++)
+        for (label j = 0; j < m; ++j)
         {
             x[i] += Q_(j, i)*source[j];
         }
@@ -210,18 +213,56 @@ void Foam::QRMatrix<MatrixType>::solve
 
 
 template<class MatrixType>
+void Foam::QRMatrix<MatrixType>::solve
+(
+    List<cmptType>& x,
+    const UList<cmptType>& source
+) const
+{
+    solveImpl(x, source);
+}
+
+
+template<class MatrixType>
+template<class Addr>
+void Foam::QRMatrix<MatrixType>::solve
+(
+    List<cmptType>& x,
+    const IndirectListBase<cmptType, Addr>& source
+) const
+{
+    solveImpl(x, source);
+}
+
+
+template<class MatrixType>
+Foam::tmp<Foam::Field<typename MatrixType::cmptType>>
+Foam::QRMatrix<MatrixType>::solve
+(
+    const UList<cmptType>& source
+) const
+{
+    auto tresult(Q_.Tmul(source));
+
+    solvex(tresult.ref());
+
+    return tresult;
+}
+
+
+template<class MatrixType>
+template<class Addr>
 Foam::tmp<Foam::Field<typename MatrixType::cmptType>>
 Foam::QRMatrix<MatrixType>::solve
 (
-    const Field<cmptType>& source
+    const IndirectListBase<cmptType, Addr>& source
 ) const
 {
-    tmp<Field<cmptType>> tx(new Field<cmptType>(Q_.m()));
-    Field<cmptType>& x = tx.ref();
+    auto tresult(Q_.Tmul(source));
 
-    solve(x, source);
+    solvex(tresult.ref());
 
-    return tx;
+    return tresult;
 }
 
 
@@ -234,14 +275,14 @@ Foam::QRMatrix<MatrixType>::inv() const
     Field<cmptType> x(m);
     QMatrixType inv(m);
 
-    for (label i=0; i<m; i++)
+    for (label i = 0; i < m; ++i)
     {
-        for (label j=0; j<m; j++)
+        for (label j = 0; j < m; ++j)
         {
             x[j] = Q_(i, j);
         }
         solvex(x);
-        inv.block(m, 1, 0, i) = x;
+        inv.subColumn(i) = x;
     }
 
     return inv;
diff --git a/src/OpenFOAM/matrices/QRMatrix/QRMatrix.H b/src/OpenFOAM/matrices/QRMatrix/QRMatrix.H
index e925967646989300744743fb554185bd8bf5d0a8..0dc739ce9319edd743658742979140061ab0e8d0 100644
--- a/src/OpenFOAM/matrices/QRMatrix/QRMatrix.H
+++ b/src/OpenFOAM/matrices/QRMatrix/QRMatrix.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) 2016 OpenFOAM Foundation
@@ -53,16 +53,16 @@ namespace Foam
 template<class MatrixType>
 class QRMatrix
 {
-
 public:
 
     typedef typename MatrixType::cmptType cmptType;
     typedef SquareMatrix<cmptType> QMatrixType;
     typedef MatrixType RMatrixType;
 
+
 private:
 
-    // Private data
+    // Private Data
 
         //- The Q-matrix
         QMatrixType Q_;
@@ -71,12 +71,22 @@ private:
         RMatrixType R_;
 
 
-    // Private member functions
+    // Private Member Functions
 
         //- Solve the linear system with the Field argument x initialized to
-        //  the appropriate transformed source (e.g. Q.T()*source)
-        //  and return the solution in x
-        void solvex(Field<cmptType>& x) const;
+        //- the appropriate transformed source (e.g. Q.T()*source)
+        //- and return the solution in x
+        template<template<typename> class ListContainer>
+        void solvex(ListContainer<cmptType>& x) const;
+
+        //- Solve the linear system with the given source
+        //- and return the solution in x
+        template<template<typename> class ListContainer>
+        void solveImpl
+        (
+            List<cmptType>& x,
+            const ListContainer<cmptType>& source
+        ) const;
 
 
 public:
@@ -102,14 +112,38 @@ public:
         void decompose(const MatrixType& M);
 
         //- Solve the linear system with the given source
-        //  and returning the solution in the Field argument x
-        void solve(Field<cmptType>& x, const Field<cmptType>& source) const;
+        //- and return the solution in the argument x
+        void solve
+        (
+            List<cmptType>& x,
+            const UList<cmptType>& source
+        ) const;
 
         //- Solve the linear system with the given source
-        //  returning the solution
-        tmp<Field<cmptType>> solve(const Field<cmptType>& source) const;
+        //- and return the solution in the argument x
+        template<class Addr>
+        void solve
+        (
+            List<cmptType>& x,
+            const IndirectListBase<cmptType, Addr>& source
+        ) const;
 
-        //- Return the inverse of a square matrix
+        //- Solve the linear system with the given source
+        //- and return the solution
+        tmp<Field<cmptType>> solve
+        (
+            const UList<cmptType>& source
+        ) const;
+
+        //- Solve the linear system with the given source
+        //- and return the solution
+        template<class Addr>
+        tmp<Field<cmptType>> solve
+        (
+            const IndirectListBase<cmptType, Addr>& source
+        ) const;
+
+        //- Return the inverse of (Q*R), so that solving x = (Q*R).inv()*source
         QMatrixType inv() const;
 };
 
diff --git a/src/OpenFOAM/matrices/QRMatrix/QRMatrixI.H b/src/OpenFOAM/matrices/QRMatrix/QRMatrixI.H
index 256c22bac40abd8f1255a67d90ad749b0b0f235d..c1d6a0826bb602d461a7718127ac093ecead2167 100644
--- a/src/OpenFOAM/matrices/QRMatrix/QRMatrixI.H
+++ b/src/OpenFOAM/matrices/QRMatrix/QRMatrixI.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) 2016 OpenFOAM Foundation
diff --git a/src/OpenFOAM/matrices/RectangularMatrix/RectangularMatrix.H b/src/OpenFOAM/matrices/RectangularMatrix/RectangularMatrix.H
index 11457760128ac5468e02c1b32bbc15665e936132..668e0241b013dbd326acb5444144bbbe184b60b1 100644
--- a/src/OpenFOAM/matrices/RectangularMatrix/RectangularMatrix.H
+++ b/src/OpenFOAM/matrices/RectangularMatrix/RectangularMatrix.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) 2011-2016 OpenFOAM Foundation
@@ -49,7 +49,7 @@ namespace Foam
 {
 
 /*---------------------------------------------------------------------------*\
-                           Class Matrix Declaration
+                      Class RectangularMatrix Declaration
 \*---------------------------------------------------------------------------*/
 
 template<class Type>
@@ -62,46 +62,63 @@ public:
 
     // Constructors
 
-        //- Null constructor.
+        //- Construct null
         inline RectangularMatrix();
 
-        //- Construct given number of rows and columns,
+        //- Construct a square matrix (rows == columns)
+        inline explicit RectangularMatrix(const label n);
+
+        //- Construct given number of rows/columns
         inline RectangularMatrix(const label m, const label n);
 
+        //- Construct given number of rows/columns
+        //- initializing all elements to zero
+        inline RectangularMatrix(const label m, const label n, const zero);
+
+        //- Construct given number of rows/columns
+        //- initializing all elements to the given value
+        inline RectangularMatrix(const label m, const label n, const Type& val);
+
+        //- Construct given number of rows/columns
+        inline explicit RectangularMatrix(const labelPair& dims);
+
+        //- Construct given number of rows/columns
+        //- initializing all elements to zero
+        inline RectangularMatrix(const labelPair& dims, const zero);
+
+        //- Construct given number of rows/columns
+        //- initializing all elements to the given value
+        inline RectangularMatrix(const labelPair& dims, const Type& val);
+
         //- Construct from a block of another matrix
         template<class MatrixType>
-        inline RectangularMatrix(const ConstMatrixBlock<MatrixType>&);
+        inline RectangularMatrix(const ConstMatrixBlock<MatrixType>& mat);
 
         //- Construct from a block of another matrix
         template<class MatrixType>
-        inline RectangularMatrix(const MatrixBlock<MatrixType>&);
-
-        //- Construct with given number of rows and columns
-        //  initializing all elements to zero
-        inline RectangularMatrix(const label m, const label n, const zero);
-
-        //- Construct with given number of rows and columns
-        //  and value for all elements.
-        inline RectangularMatrix(const label m, const label n, const Type&);
+        inline RectangularMatrix(const MatrixBlock<MatrixType>& mat);
 
         //- Construct as copy of a square matrix
-        inline RectangularMatrix(const SquareMatrix<Type>&);
+        inline RectangularMatrix(const SquareMatrix<Type>& mat);
 
         //- Construct from Istream.
-        inline RectangularMatrix(Istream&);
+        inline explicit RectangularMatrix(Istream& is);
 
         //- Clone
         inline autoPtr<RectangularMatrix<Type>> clone() const;
 
 
-    // Member operators
+    // Member Operators
+
+        //- Assign all elements to zero
+        inline void operator=(const zero);
 
-        //- Assignment of all elements to zero
-        void operator=(const zero);
+        //- Assign all elements to value
+        inline void operator=(const Type& val);
 };
 
 
-// Global functions and operators
+// * * * * * * * * * * * * * * * Global Functions  * * * * * * * * * * * * * //
 
 template<class Type>
 class typeOfInnerProduct<Type, RectangularMatrix<Type>, RectangularMatrix<Type>>
@@ -111,6 +128,7 @@ public:
     typedef RectangularMatrix<Type> type;
 };
 
+
 template<class Type>
 class typeOfInnerProduct<Type, RectangularMatrix<Type>, SquareMatrix<Type>>
 {
@@ -119,6 +137,7 @@ public:
     typedef RectangularMatrix<Type> type;
 };
 
+
 template<class Type>
 class typeOfInnerProduct<Type, SquareMatrix<Type>, RectangularMatrix<Type>>
 {
@@ -128,6 +147,8 @@ public:
 };
 
 
+// * * * * * * * * * * * * * * * Friend Functions  * * * * * * * * * * * * * //
+
 template<class Type>
 RectangularMatrix<Type> outer(const Field<Type>& f1, const Field<Type>& f2);
 
diff --git a/src/OpenFOAM/matrices/RectangularMatrix/RectangularMatrixI.H b/src/OpenFOAM/matrices/RectangularMatrix/RectangularMatrixI.H
index a584248b593fe909952770571c708afd564105ae..1ff31473717866cc5d894e7a972226fbe59e6751 100644
--- a/src/OpenFOAM/matrices/RectangularMatrix/RectangularMatrixI.H
+++ b/src/OpenFOAM/matrices/RectangularMatrix/RectangularMatrixI.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) 2011-2016 OpenFOAM Foundation
@@ -46,24 +46,24 @@ inline Foam::RectangularMatrix<Type>::RectangularMatrix
 
 
 template<class Type>
-template<class MatrixType>
 inline Foam::RectangularMatrix<Type>::RectangularMatrix
 (
-    const ConstMatrixBlock<MatrixType>& block
+    const label n
 )
 :
-    Matrix<RectangularMatrix<Type>, Type>(block)
+    Matrix<RectangularMatrix<Type>, Type>(n, n)
 {}
 
 
 template<class Type>
-template<class MatrixType>
 inline Foam::RectangularMatrix<Type>::RectangularMatrix
 (
-    const MatrixBlock<MatrixType>& block
+    const label m,
+    const label n,
+    const zero
 )
 :
-    Matrix<RectangularMatrix<Type>, Type>(block)
+    Matrix<RectangularMatrix<Type>, Type>(m, n, Zero)
 {}
 
 
@@ -72,32 +72,74 @@ inline Foam::RectangularMatrix<Type>::RectangularMatrix
 (
     const label m,
     const label n,
+    const Type& val
+)
+:
+    Matrix<RectangularMatrix<Type>, Type>(m, n, val)
+{}
+
+
+template<class Type>
+inline Foam::RectangularMatrix<Type>::RectangularMatrix
+(
+    const labelPair& dims
+)
+:
+    RectangularMatrix<Type>(dims.first(), dims.second())
+{}
+
+
+template<class Type>
+inline Foam::RectangularMatrix<Type>::RectangularMatrix
+(
+    const labelPair& dims,
     const zero
 )
 :
-    Matrix<RectangularMatrix<Type>, Type>(m, n, Zero)
+    RectangularMatrix<Type>(dims.first(), dims.second(), Zero)
 {}
 
 
 template<class Type>
 inline Foam::RectangularMatrix<Type>::RectangularMatrix
 (
-    const label m,
-    const label n,
-    const Type& t
+    const labelPair& dims,
+    const Type& val
 )
 :
-    Matrix<RectangularMatrix<Type>, Type>(m, n, t)
+    RectangularMatrix<Type>(dims.first(), dims.second(), val)
 {}
 
 
 template<class Type>
+template<class MatrixType>
 inline Foam::RectangularMatrix<Type>::RectangularMatrix
 (
-    const SquareMatrix<Type>& SM
+    const ConstMatrixBlock<MatrixType>& mat
 )
 :
-    Matrix<RectangularMatrix<Type>, Type>(SM)
+    Matrix<RectangularMatrix<Type>, Type>(mat)
+{}
+
+
+template<class Type>
+template<class MatrixType>
+inline Foam::RectangularMatrix<Type>::RectangularMatrix
+(
+    const MatrixBlock<MatrixType>& mat
+)
+:
+    Matrix<RectangularMatrix<Type>, Type>(mat)
+{}
+
+
+template<class Type>
+inline Foam::RectangularMatrix<Type>::RectangularMatrix
+(
+    const SquareMatrix<Type>& mat
+)
+:
+    Matrix<RectangularMatrix<Type>, Type>(mat)
 {}
 
 
@@ -119,12 +161,19 @@ Foam::RectangularMatrix<Type>::clone() const
 // * * * * * * * * * * * * * * * Member Operators  * * * * * * * * * * * * * //
 
 template<class Type>
-void Foam::RectangularMatrix<Type>::operator=(const zero)
+inline void Foam::RectangularMatrix<Type>::operator=(const zero)
 {
     Matrix<RectangularMatrix<Type>, Type>::operator=(Zero);
 }
 
 
+template<class Type>
+inline void Foam::RectangularMatrix<Type>::operator=(const Type& val)
+{
+    Matrix<RectangularMatrix<Type>, Type>::operator=(val);
+}
+
+
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
 namespace Foam
@@ -141,9 +190,9 @@ inline Foam::RectangularMatrix<Type> outer
 {
     RectangularMatrix<Type> f1f2T(f1.size(), f2.size());
 
-    for (label i=0; i<f1f2T.m(); i++)
+    for (label i = 0; i < f1f2T.m(); ++i)
     {
-        for (label j=0; j<f1f2T.n(); j++)
+        for (label j = 0; j < f1f2T.n(); ++j)
         {
             f1f2T(i, j) = f1[i]*f2[j];
         }
@@ -157,4 +206,5 @@ inline Foam::RectangularMatrix<Type> outer
 
 } // End namespace Foam
 
+
 // ************************************************************************* //
diff --git a/src/OpenFOAM/matrices/SquareMatrix/SquareMatrix.C b/src/OpenFOAM/matrices/SquareMatrix/SquareMatrix.C
index 5429f5c78e85d18b71907ff30299533797ff3e2d..848b4901b32ad2d6b51b17b56bdfd7abb6755b1b 100644
--- a/src/OpenFOAM/matrices/SquareMatrix/SquareMatrix.C
+++ b/src/OpenFOAM/matrices/SquareMatrix/SquareMatrix.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           |
+    \\  /    A nd           | Copyright (C) 2004-2010, 2019 OpenCFD Ltd.
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
                             | Copyright (C) 2013-2016 OpenFOAM Foundation
@@ -26,6 +26,7 @@ License
 \*---------------------------------------------------------------------------*/
 
 #include "SquareMatrix.H"
+#include "RectangularMatrix.H"
 #include "labelList.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@@ -39,7 +40,7 @@ Foam::scalar Foam::detDecomposed
 {
     Type diagProduct = pTraits<Type>::one;
 
-    for (label i=0; i<matrix.m(); i++)
+    for (label i = 0; i < matrix.m(); ++i)
     {
         diagProduct *= matrix(i, i);
     }
@@ -72,4 +73,19 @@ Foam::scalar Foam::det(SquareMatrix<Type>& matrix)
 }
 
 
+// * * * * * * * * * * * * * * * Member Operators  * * * * * * * * * * * * * //
+
+template<class Type>
+template<class AnyType>
+void Foam::SquareMatrix<Type>::operator=(const Identity<AnyType>)
+{
+    Matrix<SquareMatrix<Type>, Type>::operator=(Zero);
+
+    for (label i=0; i < this->n(); ++i)
+    {
+        this->operator()(i, i) = pTraits<Type>::one;
+    }
+}
+
+
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
diff --git a/src/OpenFOAM/matrices/SquareMatrix/SquareMatrix.H b/src/OpenFOAM/matrices/SquareMatrix/SquareMatrix.H
index e6620449249a4b209a3451c0c193e569899b10ca..1bd82812157b4d15bd8ef9edd38932e1436a9505 100644
--- a/src/OpenFOAM/matrices/SquareMatrix/SquareMatrix.H
+++ b/src/OpenFOAM/matrices/SquareMatrix/SquareMatrix.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) 2011-2016 OpenFOAM Foundation
@@ -47,14 +47,12 @@ SourceFiles
 namespace Foam
 {
 
-// Forward declaration of friend functions and operators
-
-template<class Type>
-class RectangularMatrix;
+// Forward Declarations
+template<class Type> class RectangularMatrix;
 
 
 /*---------------------------------------------------------------------------*\
-                           Class Matrix Declaration
+                        Class SquareMatrix Declaration
 \*---------------------------------------------------------------------------*/
 
 template<class Type>
@@ -67,42 +65,57 @@ public:
 
     // Constructors
 
-        //- Null constructor.
+        //- Construct null
         inline SquareMatrix();
 
-        //- Construct given number of rows/columns.
-        inline SquareMatrix(const label n);
+        //- Construct for given size (rows == cols)
+        inline explicit SquareMatrix(const label n);
 
-        //- Construct from a block of another matrix
-        template<class MatrixType>
-        inline SquareMatrix(const ConstMatrixBlock<MatrixType>&);
+        //- Construct for given size (rows == cols)
+        //- initializing all elements to zero
+        inline SquareMatrix(const label n, const zero);
 
-        //- Construct from a block of another matrix
-        template<class MatrixType>
-        inline SquareMatrix(const MatrixBlock<MatrixType>&);
+        //- Construct for given size (rows == cols)
+        //- initializing all elements to the given value
+        inline SquareMatrix(const label n, const Type& val);
 
-        //- Construct given number of rows/columns
-        //  initializing all elements to zero
-        inline SquareMatrix(const label n, const zero);
+        //- Construct for given size (rows == cols)
+        //- initializing to the identity matrix
+        template<class AnyType>
+        inline SquareMatrix(const label n, const Identity<AnyType>);
+
+        //- Construct given number of rows/columns (checked to be equal)
+        //  For constructor consistency in rectangular matrices
+        inline explicit SquareMatrix(const labelPair& dims);
 
-        //- Construct given number of rows and columns (checked to be equal)
-        //  initializing all elements to zero
+        //- Construct given number of rows/columns (checked to be equal)
+        //- initializing all elements to zero
+        //  For constructor consistency with rectangular matrices
+        inline SquareMatrix(const labelPair& dims, const zero);
+
+        //- Construct given number of rows/columns (checked to be equal)
+        //- initializing all elements to the given value
+        //  For constructor consistency with rectangular matrices
+        inline SquareMatrix(const labelPair& dims, const Type& val);
+
+        //- Construct given number of rows/columns (checked to be equal)
+        //- initializing all elements to zero
         inline SquareMatrix(const label m, const label n, const zero);
 
-        //- Construct given number of rows/columns
-        //  Initializing to the identity matrix
-        inline SquareMatrix(const label n, const Identity<Type>);
+        //- Construct from sub-matrix block
+        template<class MatrixType>
+        inline SquareMatrix(const ConstMatrixBlock<MatrixType>& mat);
 
-        //- Construct with given number of rows and rows
-        //  initializing all elements to the given value
-        inline SquareMatrix(const label n, const Type&);
+        //- Construct from sub-matrix block
+        template<class MatrixType>
+        inline SquareMatrix(const MatrixBlock<MatrixType>& mat);
 
         //- Construct as copy of a RectangularMatrix
-        //  which is checked to be square
-        inline explicit SquareMatrix(const RectangularMatrix<Type>&);
+        //- which is checked to be square
+        inline explicit SquareMatrix(const RectangularMatrix<Type>& mat);
 
-        //- Construct from Istream.
-        inline SquareMatrix(Istream&);
+        //- Construct from Istream
+        inline explicit SquareMatrix(Istream& is);
 
         //- Clone
         inline autoPtr<SquareMatrix<Type>> clone() const;
@@ -110,26 +123,33 @@ public:
 
     // Member Functions
 
-        // Edit
+    // Edit
 
-            //- Resize the matrix preserving the elements
-            inline void setSize(const label m);
+        //- Resize the matrix preserving the elements
+        inline void resize(const label m);
 
-            //- Resize the matrix without reallocating storage (unsafe)
-            inline void shallowResize(const label m);
+        //- Resize the matrix preserving the elements
+        inline void setSize(const label m);
 
+        //- Resize the matrix without reallocating storage (unsafe)
+        inline void shallowResize(const label m);
 
-    // Member operators
 
-        //- Assignment of all elements to zero
-        void operator=(const zero);
+    // Member Operators
 
-        //- Assignment elements to the
-        void operator=(const Identity<Type>);
+        //- Assign all elements to zero
+        inline void operator=(const zero);
+
+        //- Assign all elements to value
+        inline void operator=(const Type& val);
+
+        //- Set to identity matrix
+        template<class AnyType>
+        void operator=(const Identity<AnyType>);
 };
 
 
-// Global functions and operators
+// * * * * * * * * * * * * * * * Global Functions  * * * * * * * * * * * * * //
 
 //- Return the LU decomposed SquareMatrix det
 template<class Type>
@@ -151,7 +171,6 @@ public:
     typedef SquareMatrix<Type> type;
 };
 
-
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
 } // End namespace Foam
diff --git a/src/OpenFOAM/matrices/SquareMatrix/SquareMatrixI.H b/src/OpenFOAM/matrices/SquareMatrix/SquareMatrixI.H
index 529ed82ba8e607c13e1c49b7e6498dc6e351395e..47897b61dc033b4df7751e52797874e06719cb97 100644
--- a/src/OpenFOAM/matrices/SquareMatrix/SquareMatrixI.H
+++ b/src/OpenFOAM/matrices/SquareMatrix/SquareMatrixI.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) 2011-2016 OpenFOAM Foundation
@@ -25,6 +25,15 @@ License
 
 \*---------------------------------------------------------------------------*/
 
+#define CHECK_MATRIX_IS_SQUARE(a, b)                                           \
+    if (a != b)                                                                \
+    {                                                                          \
+        FatalErrorInFunction                                                   \
+            << "Attempt to create a non-square matrix ("                       \
+            << a << ", " << b << ')' << nl << abort(FatalError);               \
+    }
+
+
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
 template<class Type>
@@ -42,36 +51,80 @@ inline Foam::SquareMatrix<Type>::SquareMatrix(const label n)
 
 
 template<class Type>
-template<class MatrixType>
 inline Foam::SquareMatrix<Type>::SquareMatrix
 (
-    const ConstMatrixBlock<MatrixType>& block
+    const label n,
+    const zero
 )
 :
-    Matrix<SquareMatrix<Type>, Type>(block)
+    Matrix<SquareMatrix<Type>, Type>(n, n, Zero)
 {}
 
 
 template<class Type>
-template<class MatrixType>
 inline Foam::SquareMatrix<Type>::SquareMatrix
 (
-    const MatrixBlock<MatrixType>& block
+    const label n,
+    const Type& val
 )
 :
-    Matrix<SquareMatrix<Type>, Type>(block)
+    Matrix<SquareMatrix<Type>, Type>(n, n, val)
 {}
 
 
 template<class Type>
+template<class AnyType>
 inline Foam::SquareMatrix<Type>::SquareMatrix
 (
     const label n,
-    const zero
+    const Identity<AnyType>
 )
 :
     Matrix<SquareMatrix<Type>, Type>(n, n, Zero)
-{}
+{
+    for (label i=0; i < n; ++i)
+    {
+        this->operator()(i, i) = pTraits<Type>::one;
+    }
+}
+
+
+template<class Type>
+inline Foam::SquareMatrix<Type>::SquareMatrix
+(
+    const labelPair& dims
+)
+:
+    Matrix<SquareMatrix<Type>, Type>(dims)
+{
+    CHECK_MATRIX_IS_SQUARE(dims.first(), dims.second());
+}
+
+
+template<class Type>
+inline Foam::SquareMatrix<Type>::SquareMatrix
+(
+    const labelPair& dims,
+    const zero
+)
+:
+    Matrix<SquareMatrix<Type>, Type>(dims, Zero)
+{
+    CHECK_MATRIX_IS_SQUARE(dims.first(), dims.second());
+}
+
+
+template<class Type>
+inline Foam::SquareMatrix<Type>::SquareMatrix
+(
+    const labelPair& dims,
+    const Type& val
+)
+:
+    Matrix<SquareMatrix<Type>, Type>(dims, val)
+{
+    CHECK_MATRIX_IS_SQUARE(dims.first(), dims.second());
+}
 
 
 template<class Type>
@@ -84,58 +137,45 @@ inline Foam::SquareMatrix<Type>::SquareMatrix
 :
     Matrix<SquareMatrix<Type>, Type>(m, n, Zero)
 {
-    if (m != n)
-    {
-        FatalErrorInFunction
-            << "Attempt to construct a square matrix "
-            << m << " x " << n << nl
-            << abort(FatalError);
-    }
+    CHECK_MATRIX_IS_SQUARE(m, n);
 }
 
 
 template<class Type>
+template<class MatrixType>
 inline Foam::SquareMatrix<Type>::SquareMatrix
 (
-    const label n,
-    const Identity<Type>
+    const ConstMatrixBlock<MatrixType>& mat
 )
 :
-    Matrix<SquareMatrix<Type>, Type>(n, n, Zero)
+    Matrix<SquareMatrix<Type>, Type>(mat)
 {
-    for (label i=0; i<n; i++)
-    {
-        this->operator()(i, i) = Type(I);
-    }
+    // Check is square?
 }
 
 
 template<class Type>
+template<class MatrixType>
 inline Foam::SquareMatrix<Type>::SquareMatrix
 (
-    const label n,
-    const Type& t
+    const MatrixBlock<MatrixType>& mat
 )
 :
-    Matrix<SquareMatrix<Type>, Type>(n, n, t)
-{}
+    Matrix<SquareMatrix<Type>, Type>(mat)
+{
+    // Check is square?
+}
 
 
 template<class Type>
 inline Foam::SquareMatrix<Type>::SquareMatrix
 (
-    const RectangularMatrix<Type>& RM
+    const RectangularMatrix<Type>& mat
 )
 :
-    Matrix<SquareMatrix<Type>, Type>(RM)
+    Matrix<SquareMatrix<Type>, Type>(mat)
 {
-    if (this->m() != this->n())
-    {
-        FatalErrorInFunction
-            << "Attempt to construct a square matrix from a rectangular matrix "
-            << this->m() << " x " << this->n() << nl
-            << abort(FatalError);
-    }
+    CHECK_MATRIX_IS_SQUARE(mat.m(), mat.n());
 }
 
 
@@ -143,7 +183,9 @@ template<class Type>
 inline Foam::SquareMatrix<Type>::SquareMatrix(Istream& is)
 :
     Matrix<SquareMatrix<Type>, Type>(is)
-{}
+{
+    CHECK_MATRIX_IS_SQUARE(this->m(), this->n());
+}
 
 
 template<class Type>
@@ -156,10 +198,17 @@ Foam::SquareMatrix<Type>::clone() const
 
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
+template<class Type>
+inline void Foam::SquareMatrix<Type>::resize(const label m)
+{
+    Matrix<SquareMatrix<Type>, Type>::resize(m, m);
+}
+
+
 template<class Type>
 inline void Foam::SquareMatrix<Type>::setSize(const label m)
 {
-    Matrix<SquareMatrix<Type>, Type>::setSize(m, m);
+    Matrix<SquareMatrix<Type>, Type>::resize(m, m);
 }
 
 
@@ -173,20 +222,16 @@ inline void Foam::SquareMatrix<Type>::shallowResize(const label m)
 // * * * * * * * * * * * * * * * Member Operators  * * * * * * * * * * * * * //
 
 template<class Type>
-void Foam::SquareMatrix<Type>::operator=(const zero)
+inline void Foam::SquareMatrix<Type>::operator=(const zero)
 {
     Matrix<SquareMatrix<Type>, Type>::operator=(Zero);
 }
 
 
 template<class Type>
-void Foam::SquareMatrix<Type>::operator=(const Identity<Type>)
+inline void Foam::SquareMatrix<Type>::operator=(const Type& val)
 {
-    Matrix<SquareMatrix<Type>, Type>::operator=(Zero);
-    for (label i=0; i<this->n(); i++)
-    {
-        this->operator()(i, i) = Type(I);
-    }
+    Matrix<SquareMatrix<Type>, Type>::operator=(val);
 }
 
 
@@ -206,9 +251,9 @@ inline Foam::SquareMatrix<Type> symmOuter
 {
     SquareMatrix<Type> f1f2T(f1.size());
 
-    for (label i=0; i<f1f2T.m(); i++)
+    for (label i = 0; i < f1f2T.m(); ++i)
     {
-        for (label j=0; j<f1f2T.n(); j++)
+        for (label j = 0; j < f1f2T.n(); ++j)
         {
             f1f2T(i, j) = f1[i]*f2[j];
         }
@@ -222,4 +267,9 @@ inline Foam::SquareMatrix<Type> symmOuter
 
 } // End namespace Foam
 
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#undef CHECK_MATRIX_IS_SQUARE
+
 // ************************************************************************* //
diff --git a/src/OpenFOAM/matrices/SymmetricSquareMatrix/SymmetricSquareMatrix.C b/src/OpenFOAM/matrices/SymmetricSquareMatrix/SymmetricSquareMatrix.C
index 3f7e6a2a0282de2630ef8e460c5d21913150ce1d..561cd7bafc0bce3c4bea49da4c51c007b2fc45f0 100644
--- a/src/OpenFOAM/matrices/SymmetricSquareMatrix/SymmetricSquareMatrix.C
+++ b/src/OpenFOAM/matrices/SymmetricSquareMatrix/SymmetricSquareMatrix.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) 2011-2016 OpenFOAM Foundation
@@ -39,15 +39,15 @@ Foam::SymmetricSquareMatrix<Type> Foam::invDecomposed
 
     SymmetricSquareMatrix<Type> inv(n, Zero);
 
-    for (label i=0; i<n; i++)
+    for (label i = 0; i < n; ++i)
     {
         inv(i, i) = 1.0/matrix(i, i);
 
-        for (label j=0; j<i; j++)
+        for (label j = 0; j < i; ++j)
         {
             Type sum = Zero;
 
-            for (label k=j; k<i; k++)
+            for (label k = j; k < i; ++k)
             {
                 sum -= matrix(i, k)*inv(k, j);
             }
@@ -58,11 +58,11 @@ Foam::SymmetricSquareMatrix<Type> Foam::invDecomposed
 
     SymmetricSquareMatrix<Type> result(n, Zero);
 
-    for (label k=0; k<n; k++)
+    for (label k = 0; k < n; ++k)
     {
-        for (label i=0; i <= k; i++)
+        for (label i = 0; i <= k; ++i)
         {
-            for (label j=0; j <= k; j++)
+            for (label j = 0; j <= k; ++j)
             {
                 result(i, j) += inv(k, i)*inv(k, j);
             }
@@ -91,7 +91,7 @@ Type Foam::detDecomposed(const SymmetricSquareMatrix<Type>& matrix)
 {
     Type diagProduct = pTraits<Type>::one;
 
-    for (label i=0; i<matrix.m(); i++)
+    for (label i = 0; i < matrix.m(); ++i)
     {
         diagProduct *= matrix(i, i);
     }
@@ -110,4 +110,19 @@ Type Foam::det(const SymmetricSquareMatrix<Type>& matrix)
 }
 
 
+// * * * * * * * * * * * * * * * Member Operators  * * * * * * * * * * * * * //
+
+template<class Type>
+template<class AnyType>
+void Foam::SymmetricSquareMatrix<Type>::operator=(const Identity<AnyType>)
+{
+    Matrix<SymmetricSquareMatrix<Type>, Type>::operator=(Zero);
+
+    for (label i=0; i < this->n(); ++i)
+    {
+        this->operator()(i, i) = pTraits<Type>::one;
+    }
+}
+
+
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
diff --git a/src/OpenFOAM/matrices/SymmetricSquareMatrix/SymmetricSquareMatrix.H b/src/OpenFOAM/matrices/SymmetricSquareMatrix/SymmetricSquareMatrix.H
index 267da6b327f5114a270240e7401f85d756b0075f..7390f401ab54f9f5cd2810b7a2c8cdeedbefda24 100644
--- a/src/OpenFOAM/matrices/SymmetricSquareMatrix/SymmetricSquareMatrix.H
+++ b/src/OpenFOAM/matrices/SymmetricSquareMatrix/SymmetricSquareMatrix.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) 2011-2016 OpenFOAM Foundation
@@ -40,7 +40,6 @@ SourceFiles
 #define SymmetricSquareMatrix_H
 
 #include "SquareMatrix.H"
-#include "Identity.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
@@ -61,31 +60,47 @@ public:
 
     // Constructors
 
-        //- Null constructor.
+        //- Construct null
         inline SymmetricSquareMatrix();
 
-        //- Construct given number of rows/columns.
-        inline SymmetricSquareMatrix(const label n);
+        //- Construct for given size (rows == cols)
+        inline explicit SymmetricSquareMatrix(const label n);
 
-        //- Construct given number of rows/columns, initializing to zero
+        //- Construct for given size (rows == cols)
+        //- initializing all elements to zero
         inline SymmetricSquareMatrix(const label n, const zero);
 
-        //- Construct given number of rows/columns,
-        inline SymmetricSquareMatrix(const label n, const Identity<Type>);
+        //- Construct for given size (rows == cols)
+        //- initializing all elements to the given value
+        inline SymmetricSquareMatrix(const label n, const Type& val);
 
-        //- Construct with given number of rows/columns
-        //  initializing all elements to the given value
-        inline SymmetricSquareMatrix(const label n, const Type&);
+        //- Construct for given size (rows == cols)
+        //- setting the diagonal to one and off-diagonals to zero
+        template<class AnyType>
+        inline SymmetricSquareMatrix(const label n, const Identity<AnyType>);
 
-        //- Construct from Istream.
-        inline SymmetricSquareMatrix(Istream&);
+        //- Construct from Istream
+        inline explicit SymmetricSquareMatrix(Istream& is);
 
         //- Clone
         inline autoPtr<SymmetricSquareMatrix<Type>> clone() const;
+
+
+    // Member Operators
+
+        //- Assign all elements to zero
+        inline void operator=(const zero);
+
+        //- Assign all elements to value
+        inline void operator=(const Type& val);
+
+        //- Set to identity matrix
+        template<class AnyType>
+        void operator=(const Identity<AnyType>);
 };
 
 
-// Global functions
+// Global Functions
 
 //- Return the LU decomposed SymmetricSquareMatrix inverse
 template<class Type>
diff --git a/src/OpenFOAM/matrices/SymmetricSquareMatrix/SymmetricSquareMatrixI.H b/src/OpenFOAM/matrices/SymmetricSquareMatrix/SymmetricSquareMatrixI.H
index 7dcc04e2b7527b60aee5cb5f511c1a160b96cdf2..c707347a06c11b42af217884272429c6235b3ced 100644
--- a/src/OpenFOAM/matrices/SymmetricSquareMatrix/SymmetricSquareMatrixI.H
+++ b/src/OpenFOAM/matrices/SymmetricSquareMatrix/SymmetricSquareMatrixI.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) 2011-2016 OpenFOAM Foundation
@@ -25,6 +25,15 @@ License
 
 \*---------------------------------------------------------------------------*/
 
+#define CHECK_MATRIX_IS_SQUARE(a, b)                                           \
+    if (a != b)                                                                \
+    {                                                                          \
+        FatalErrorInFunction                                                   \
+            << "Attempt to create a non-square matrix ("                       \
+            << a << ", " << b << ')' << nl << abort(FatalError);               \
+    }
+
+
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
 template<class Type>
@@ -56,34 +65,37 @@ template<class Type>
 inline Foam::SymmetricSquareMatrix<Type>::SymmetricSquareMatrix
 (
     const label n,
-    const Identity<Type>
+    const Type& val
 )
 :
-    Matrix<SymmetricSquareMatrix<Type>, Type>(n, n, Zero)
-{
-    for (label i=0; i<n; i++)
-    {
-        this->operator()(i, i) = pTraits<Type>::one;
-    }
-}
+    Matrix<SymmetricSquareMatrix<Type>, Type>(n, n, val)
+{}
 
 
 template<class Type>
+template<class AnyType>
 inline Foam::SymmetricSquareMatrix<Type>::SymmetricSquareMatrix
 (
     const label n,
-    const Type& t
+    const Identity<AnyType>
 )
 :
-    Matrix<SymmetricSquareMatrix<Type>, Type>(n, n, t)
-{}
+    Matrix<SymmetricSquareMatrix<Type>, Type>(n, n, Zero)
+{
+    for (label i=0; i < n; ++i)
+    {
+        this->operator()(i, i) = pTraits<Type>::one;
+    }
+}
 
 
 template<class Type>
 inline Foam::SymmetricSquareMatrix<Type>::SymmetricSquareMatrix(Istream& is)
 :
     Matrix<SymmetricSquareMatrix<Type>, Type>(is)
-{}
+{
+    CHECK_MATRIX_IS_SQUARE(this->m(), this->n());
+}
 
 
 template<class Type>
@@ -94,4 +106,24 @@ Foam::SymmetricSquareMatrix<Type>::clone() const
 }
 
 
+// * * * * * * * * * * * * * * * Member Operators  * * * * * * * * * * * * * //
+
+template<class Type>
+inline void Foam::SymmetricSquareMatrix<Type>::operator=(const zero)
+{
+    Matrix<SymmetricSquareMatrix<Type>, Type>::operator=(Zero);
+}
+
+
+template<class Type>
+inline void Foam::SymmetricSquareMatrix<Type>::operator=(const Type& val)
+{
+    Matrix<SymmetricSquareMatrix<Type>, Type>::operator=(val);
+}
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#undef CHECK_MATRIX_IS_SQUARE
+
 // ************************************************************************* //
diff --git a/src/OpenFOAM/matrices/scalarMatrices/scalarMatrices.C b/src/OpenFOAM/matrices/scalarMatrices/scalarMatrices.C
index 792270a600484eede8ed6c3ea1d699074b62e107..b8551c4ee20ab0a0f1fa50a5e31e1c44eb3902da 100644
--- a/src/OpenFOAM/matrices/scalarMatrices/scalarMatrices.C
+++ b/src/OpenFOAM/matrices/scalarMatrices/scalarMatrices.C
@@ -52,13 +52,13 @@ void Foam::LUDecompose
     scalar vv[m];
     sign = 1;
 
-    for (label i=0; i<m; i++)
+    for (label i = 0; i < m; ++i)
     {
         scalar largestCoeff = 0.0;
         scalar temp;
         const scalar* __restrict__ matrixi = matrix[i];
 
-        for (label j=0; j<m; j++)
+        for (label j = 0; j < m; ++j)
         {
             if ((temp = mag(matrixi[j])) > largestCoeff)
             {
@@ -75,16 +75,16 @@ void Foam::LUDecompose
         vv[i] = 1.0/largestCoeff;
     }
 
-    for (label j=0; j<m; j++)
+    for (label j = 0; j < m; ++j)
     {
         scalar* __restrict__ matrixj = matrix[j];
 
-        for (label i=0; i<j; i++)
+        for (label i = 0; i < j; ++i)
         {
             scalar* __restrict__ matrixi = matrix[i];
 
             scalar sum = matrixi[j];
-            for (label k=0; k<i; k++)
+            for (label k = 0; k < i; ++k)
             {
                 sum -= matrixi[k]*matrix(k, j);
             }
@@ -94,12 +94,12 @@ void Foam::LUDecompose
         label iMax = 0;
 
         scalar largestCoeff = 0.0;
-        for (label i=j; i<m; i++)
+        for (label i = j; i < m; ++i)
         {
             scalar* __restrict__ matrixi = matrix[i];
             scalar sum = matrixi[j];
 
-            for (label k=0; k<j; k++)
+            for (label k = 0; k < j; ++k)
             {
                 sum -= matrixi[k]*matrix(k, j);
             }
@@ -120,7 +120,7 @@ void Foam::LUDecompose
         {
             scalar* __restrict__ matrixiMax = matrix[iMax];
 
-            for (label k=0; k<m; k++)
+            for (label k = 0; k < m; ++k)
             {
                 Swap(matrixj[k], matrixiMax[k]);
             }
@@ -138,7 +138,7 @@ void Foam::LUDecompose
         {
             scalar rDiag = 1.0/matrixj[j];
 
-            for (label i=j+1; i<m; i++)
+            for (label i = j + 1; i < m; ++i)
             {
                 matrix(i, j) *= rDiag;
             }
@@ -153,23 +153,23 @@ void Foam::LUDecompose(scalarSymmetricSquareMatrix& matrix)
     label size = matrix.m();
 
     // Set upper triangular parts to zero.
-    for (label j=0; j<size; j++)
+    for (label j = 0; j < size; ++j)
     {
-        for (label k=j + 1; k<size; k++)
+        for (label k = j + 1; k < size; ++k)
         {
             matrix(j, k) = 0.0;
         }
     }
 
-    for (label j=0; j<size; j++)
+    for (label j = 0; j < size; ++j)
     {
         scalar d = 0.0;
 
-        for (label k=0; k<j; k++)
+        for (label k = 0; k < j; ++k)
         {
             scalar s = 0.0;
 
-            for (label i=0; i<k; i++)
+            for (label i = 0; i < k; ++i)
             {
                 s += matrix(i, k)*matrix(i, j);
             }
@@ -225,14 +225,14 @@ void Foam::multiply
 
     ans = scalarRectangularMatrix(A.m(), C.n(), Zero);
 
-    for (label i=0; i<A.m(); i++)
+    for (label i = 0; i < A.m(); ++i)
     {
-        for (label g = 0; g < C.n(); g++)
+        for (label g = 0; g < C.n(); ++g)
         {
-            for (label l=0; l<C.m(); l++)
+            for (label l = 0; l < C.m(); ++l)
             {
                 scalar ab = 0;
-                for (label j=0; j<A.n(); j++)
+                for (label j = 0; j < A.n(); ++j)
                 {
                     ab += A(i, j)*B(j, l);
                 }
@@ -269,11 +269,11 @@ void Foam::multiply
 
     ans = scalarRectangularMatrix(A.m(), C.n(), Zero);
 
-    for (label i=0; i<A.m(); i++)
+    for (label i = 0; i < A.m(); ++i)
     {
-        for (label g=0; g<C.n(); g++)
+        for (label g = 0; g < C.n(); ++g)
         {
-            for (label l=0; l<C.m(); l++)
+            for (label l = 0; l < C.m(); ++l)
             {
                 ans(i, g) += C(l, g) * A(i, l)*B[l];
             }
@@ -310,11 +310,11 @@ void Foam::multiply
 
     ans = scalarSquareMatrix(size, Zero);
 
-    for (label i=0; i<size; i++)
+    for (label i = 0; i < size; ++i)
     {
-        for (label g=0; g<size; g++)
+        for (label g = 0; g < size; ++g)
         {
-            for (label l=0; l<size; l++)
+            for (label l = 0; l < size; ++l)
             {
                 ans(i, g) += C(l, g)*A(i, l)*B[l];
             }
@@ -323,6 +323,7 @@ void Foam::multiply
 }
 
 
+//- Pseudo-inverse algorithm for scalar matrices, using Moore-Penrose inverse
 Foam::scalarRectangularMatrix Foam::SVDinv
 (
     const scalarRectangularMatrix& A,
diff --git a/src/OpenFOAM/matrices/scalarMatrices/scalarMatrices.H b/src/OpenFOAM/matrices/scalarMatrices/scalarMatrices.H
index 19f0705ed8248382408133b4a867aff994f76996..48990578c989ea36a74b87f5a6042d4fc6e981ab 100644
--- a/src/OpenFOAM/matrices/scalarMatrices/scalarMatrices.H
+++ b/src/OpenFOAM/matrices/scalarMatrices/scalarMatrices.H
@@ -60,12 +60,12 @@ typedef SymmetricSquareMatrix<scalar> scalarSymmetricSquareMatrix;
 typedef DiagonalMatrix<scalar> scalarDiagonalMatrix;
 
 //- Solve the matrix using Gaussian elimination with pivoting,
-//  returning the solution in the source
+//- returning the solution in the source
 template<class Type>
 void solve(scalarSquareMatrix& matrix, List<Type>& source);
 
 //- Solve the matrix using Gaussian elimination with pivoting
-//  and return the solution
+//- and return the solution
 template<class Type>
 void solve
 (
@@ -82,7 +82,7 @@ void LUDecompose
 );
 
 //- LU decompose the matrix with pivoting.
-//  sign is -1 for odd number of row interchanges and 1 for even number.
+//- sign is -1 for odd number of row interchanges and 1 for even number.
 void LUDecompose
 (
     scalarSquareMatrix& matrix,
@@ -94,7 +94,7 @@ void LUDecompose
 void LUDecompose(scalarSymmetricSquareMatrix& matrix);
 
 //- LU back-substitution with given source, returning the solution
-//  in the source
+//- in the source
 template<class Type>
 void LUBacksubstitute
 (
@@ -104,8 +104,8 @@ void LUBacksubstitute
 );
 
 //- LU back-substitution with given source, returning the solution
-//  in the source. Specialised for symmetric square matrices that have been
-//  decomposed into LU where U = L.T() as pivoting is not required
+//- in the source. Specialised for symmetric square matrices that have been
+//- decomposed into LU where U = L.T() as pivoting is not required
 template<class Type>
 void LUBacksubstitute
 (
@@ -114,12 +114,12 @@ void LUBacksubstitute
 );
 
 //- Solve the matrix using LU decomposition with pivoting
-//  returning the LU form of the matrix and the solution in the source
+//- returning the LU form of the matrix and the solution in the source
 template<class Type>
 void LUsolve(scalarSquareMatrix& matrix, List<Type>& source);
 
 //- Solve the matrix using LU decomposition returning the LU form of the matrix
-//  and the solution in the source, where U = L.T()
+//- and the solution in the source, where U = L.T()
 template<class Type>
 void LUsolve(scalarSymmetricSquareMatrix& matrix, List<Type>& source);
 
diff --git a/src/OpenFOAM/matrices/scalarMatrices/scalarMatricesTemplates.C b/src/OpenFOAM/matrices/scalarMatrices/scalarMatricesTemplates.C
index d2ce3dec347940f4413429fefa3c12bcdd3ed592..70ad847e2a8c07b0d297759deb2f2b01508ee23f 100644
--- a/src/OpenFOAM/matrices/scalarMatrices/scalarMatricesTemplates.C
+++ b/src/OpenFOAM/matrices/scalarMatrices/scalarMatricesTemplates.C
@@ -41,13 +41,13 @@ void Foam::solve
     label m = tmpMatrix.m();
 
     // Elimination
-    for (label i=0; i<m; i++)
+    for (label i = 0; i < m; ++i)
     {
         label iMax = i;
         scalar largestCoeff = mag(tmpMatrix(iMax, i));
 
         // Swap elements around to find a good pivot
-        for (label j=i+1; j<m; j++)
+        for (label j = i + 1; j < m; ++j)
         {
             if (mag(tmpMatrix(j, i)) > largestCoeff)
             {
@@ -58,7 +58,7 @@ void Foam::solve
 
         if (i != iMax)
         {
-            for (label k=i; k<m; k++)
+            for (label k = i; k < m; ++k)
             {
                 Swap(tmpMatrix(i, k), tmpMatrix(iMax, k));
             }
@@ -74,11 +74,11 @@ void Foam::solve
         }
 
         // Reduce to upper triangular form
-        for (label j=i+1; j<m; j++)
+        for (label j = i + 1; j < m; ++j)
         {
             sourceSol[j] -= sourceSol[i]*(tmpMatrix(j, i)/tmpMatrix(i, i));
 
-            for (label k=m-1; k>=i; k--)
+            for (label k = m - 1; k >= i; --k)
             {
                 tmpMatrix(j, k) -=
                     tmpMatrix(i, k)*tmpMatrix(j, i)/tmpMatrix(i, i);
@@ -87,11 +87,11 @@ void Foam::solve
     }
 
     // Back-substitution
-    for (label j=m-1; j>=0; j--)
+    for (label j = m - 1; j >= 0; --j)
     {
         Type ntempvec = Zero;
 
-        for (label k=j+1; k<m; k++)
+        for (label k = j + 1; k < m; ++k)
         {
             ntempvec += tmpMatrix(j, k)*sourceSol[k];
         }
@@ -127,7 +127,7 @@ void Foam::LUBacksubstitute
 
     label ii = 0;
 
-    for (label i=0; i<m; i++)
+    for (label i = 0; i < m; ++i)
     {
         label ip = pivotIndices[i];
         Type sum = sourceSol[ip];
@@ -136,25 +136,25 @@ void Foam::LUBacksubstitute
 
         if (ii != 0)
         {
-            for (label j=ii-1; j<i; j++)
+            for (label j = ii - 1; j < i; ++j)
             {
                 sum -= luMatrixi[j]*sourceSol[j];
             }
         }
         else if (sum != Type(Zero))
         {
-            ii = i+1;
+            ii = i + 1;
         }
 
         sourceSol[i] = sum;
     }
 
-    for (label i=m-1; i>=0; i--)
+    for (label i = m - 1; i >= 0; --i)
     {
         Type sum = sourceSol[i];
         const scalar* __restrict__ luMatrixi = luMatrix[i];
 
-        for (label j=i+1; j<m; j++)
+        for (label j = i + 1; j < m; ++j)
         {
             sum -= luMatrixi[j]*sourceSol[j];
         }
@@ -175,32 +175,32 @@ void Foam::LUBacksubstitute
 
     label ii = 0;
 
-    for (label i=0; i<m; i++)
+    for (label i = 0; i < m; ++i)
     {
         Type sum = sourceSol[i];
         const scalar* __restrict__ luMatrixi = luMatrix[i];
 
         if (ii != 0)
         {
-            for (label j=ii-1; j<i; j++)
+            for (label j = ii - 1; j < i; ++j)
             {
                 sum -= luMatrixi[j]*sourceSol[j];
             }
         }
         else if (sum != Type(Zero))
         {
-            ii = i+1;
+            ii = i + 1;
         }
 
         sourceSol[i] = sum/luMatrixi[i];
     }
 
-    for (label i=m-1; i>=0; i--)
+    for (label i = m - 1; i >= 0; --i)
     {
         Type sum = sourceSol[i];
         const scalar* __restrict__ luMatrixi = luMatrix[i];
 
-        for (label j=i+1; j<m; j++)
+        for (label j = i + 1; j < m; ++j)
         {
             sum -= luMatrixi[j]*sourceSol[j];
         }
@@ -253,11 +253,11 @@ void Foam::multiply
 
     ans = Matrix<Form, Type>(A.m(), B.n(), Zero);
 
-    for (label i=0; i<A.m(); i++)
+    for (label i = 0; i < A.m(); ++i)
     {
-        for (label j=0; j<B.n(); j++)
+        for (label j = 0; j < B.n(); ++j)
         {
-            for (label l=0; l<B.m(); l++)
+            for (label l = 0; l < B.m(); ++l)
             {
                 ans(i, j) += A(i, l)*B(l, j);
             }
diff --git a/src/OpenFOAM/meshes/meshShapes/cellModel/cellModels.C b/src/OpenFOAM/meshes/meshShapes/cellModel/cellModels.C
index 4178d814f1f9dfe1d62421eb299dafd557195c95..9880404151ab76a9b04be4938d8c41e6c20f9c75 100644
--- a/src/OpenFOAM/meshes/meshShapes/cellModel/cellModels.C
+++ b/src/OpenFOAM/meshes/meshShapes/cellModel/cellModels.C
@@ -35,7 +35,7 @@ Foam::PtrList<Foam::cellModel> Foam::cellModel::models_;
 Foam::List<const Foam::cellModel*> Foam::cellModel::modelPtrs_;
 
 const Foam::Enum<Foam::cellModel::modelType> Foam::cellModel::modelNames
-{
+({
     { modelType::UNKNOWN, "unknown" },
     { modelType::HEX, "hex" },
     { modelType::WEDGE, "wedge" },
@@ -44,7 +44,7 @@ const Foam::Enum<Foam::cellModel::modelType> Foam::cellModel::modelNames
     { modelType::TET, "tet" },
     { modelType::TETWEDGE, "tetWedge" },
     { modelType::SPLITHEX, "splitHex" },
-};
+});
 
 
 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
diff --git a/src/OpenFOAM/meshes/meshShapes/face/face.H b/src/OpenFOAM/meshes/meshShapes/face/face.H
index d2e78edf3e72ed6348401f128fd1f1009768d387..28817059d422b91ee04452ad94b55b655853a77f 100644
--- a/src/OpenFOAM/meshes/meshShapes/face/face.H
+++ b/src/OpenFOAM/meshes/meshShapes/face/face.H
@@ -202,8 +202,8 @@ public:
 
         //- Legacy name for areaNormal()
         //  \deprecated(2018-06) Deprecated for new use
-        inline vector normal(const UList<point>& p) const
-        FOAM_DEPRECATED_FOR(2018-12, "areaNormal() or unitNormal()")
+        vector FOAM_DEPRECATED_FOR(2018-12, "areaNormal() or unitNormal()")
+        normal(const UList<point>& p) const
         {
             return areaNormal(p); // Legacy definition
         }
diff --git a/src/OpenFOAM/meshes/meshShapes/triFace/triFace.H b/src/OpenFOAM/meshes/meshShapes/triFace/triFace.H
index ea964983e3d5d40c464aa3829b3bb3c398637d4c..87622154331078c24d419428634ad125da3b0d36 100644
--- a/src/OpenFOAM/meshes/meshShapes/triFace/triFace.H
+++ b/src/OpenFOAM/meshes/meshShapes/triFace/triFace.H
@@ -133,8 +133,8 @@ public:
 
         //- Legacy name for areaNormal()
         //  \deprecated(2018-06) Deprecated for new use
-        inline vector normal(const UList<point>& points) const
-        FOAM_DEPRECATED_FOR(2018-12, "areaNormal() or unitNormal()")
+        vector FOAM_DEPRECATED_FOR(2018-12, "areaNormal() or unitNormal()")
+        normal(const UList<point>& points) const
         {
             return areaNormal(points); // Legacy definition
         }
diff --git a/src/OpenFOAM/meshes/primitiveShapes/triangle/triangle.H b/src/OpenFOAM/meshes/primitiveShapes/triangle/triangle.H
index cf985f027868cdcb8eec1556ec34909efda269ac..58b90a93aac3a81f220c31a96eb5878a9d6e6f45 100644
--- a/src/OpenFOAM/meshes/primitiveShapes/triangle/triangle.H
+++ b/src/OpenFOAM/meshes/primitiveShapes/triangle/triangle.H
@@ -216,8 +216,8 @@ public:
 
             //- Legacy name for areaNormal().
             //  \deprecated(2018-06) Deprecated for new use
-            inline vector normal() const
-            FOAM_DEPRECATED_FOR(2018-12, "areaNormal() or unitNormal()")
+            vector FOAM_DEPRECATED_FOR(2018-12, "areaNormal() or unitNormal()")
+            normal() const
             {
                 return areaNormal();
             }
diff --git a/src/OpenFOAM/primitives/Pair/Pair.H b/src/OpenFOAM/primitives/Pair/Pair.H
index 22d2172bfad9e38679a177db44dc94c28dcb36f5..db9589d6aced91b4695dd4652b6f9c954469edb6 100644
--- a/src/OpenFOAM/primitives/Pair/Pair.H
+++ b/src/OpenFOAM/primitives/Pair/Pair.H
@@ -50,6 +50,13 @@ See also
 namespace Foam
 {
 
+// Forward declarations
+template<class T> class Pair;
+
+// Common pair types
+typedef Pair<label> labelPair;      //!< A pair of labels
+
+
 /*---------------------------------------------------------------------------*\
                             Class Pair Declaration
 \*---------------------------------------------------------------------------*/
@@ -163,7 +170,6 @@ public:
                 return seed;
             }
         };
-
 };
 
 
diff --git a/src/OpenFOAM/primitives/Pair/labelPair.H b/src/OpenFOAM/primitives/Pair/labelPair.H
index 01e7419951c94c502c3e913eb535eb10a871af01..f4f81158df02af6226661c8c623591b999dd8769 100644
--- a/src/OpenFOAM/primitives/Pair/labelPair.H
+++ b/src/OpenFOAM/primitives/Pair/labelPair.H
@@ -23,12 +23,6 @@ License
     You should have received a copy of the GNU General Public License
     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
 
-Typedef
-    Foam::labelPair
-
-Description
-    A pair of labels.
-
 Typedef
     Foam::labelPairPair
 
@@ -66,7 +60,6 @@ Description
 
 namespace Foam
 {
-    typedef Pair<label> labelPair;
     typedef Pair<labelPair> labelPairPair;
     typedef List<labelPair> labelPairList;
     typedef UList<labelPair> labelPairUList;
diff --git a/src/OpenFOAM/primitives/Scalar/Scalar.C b/src/OpenFOAM/primitives/Scalar/Scalar.C
index adbd7aac6c65e38a31f04f6a035be9cc647b57c3..de61336a83e482e5c3a03d29cf9ae75463bd282a 100644
--- a/src/OpenFOAM/primitives/Scalar/Scalar.C
+++ b/src/OpenFOAM/primitives/Scalar/Scalar.C
@@ -39,6 +39,7 @@ const Scalar pTraits<Scalar>::min = -ScalarVGREAT;
 const Scalar pTraits<Scalar>::max = ScalarVGREAT;
 const Scalar pTraits<Scalar>::rootMin = -ScalarROOTVGREAT;
 const Scalar pTraits<Scalar>::rootMax = ScalarROOTVGREAT;
+const Scalar pTraits<Scalar>::vsmall = ScalarVSMALL;
 
 const char* const pTraits<Scalar>::componentNames[] = { "" };
 
diff --git a/src/OpenFOAM/primitives/Scalar/Scalar.H b/src/OpenFOAM/primitives/Scalar/Scalar.H
index 9039dbdcb92ce7a0f3f95d283801cbbf7ae65555..0d171b29f06854b81a0dcedea4a0d55d91fd2d8b 100644
--- a/src/OpenFOAM/primitives/Scalar/Scalar.H
+++ b/src/OpenFOAM/primitives/Scalar/Scalar.H
@@ -78,6 +78,7 @@ public:
         static const Scalar min;
         static const Scalar rootMax;
         static const Scalar rootMin;
+        static const Scalar vsmall;
 
 
     // Constructors
diff --git a/src/OpenFOAM/primitives/Scalar/scalar/scalar.H b/src/OpenFOAM/primitives/Scalar/scalar/scalar.H
index 81889c103f5351cba3cc2d3f8bf0b9da51002ebd..f14586dc87da22849babd6b2db77cc3e8477a9b4 100644
--- a/src/OpenFOAM/primitives/Scalar/scalar/scalar.H
+++ b/src/OpenFOAM/primitives/Scalar/scalar/scalar.H
@@ -28,7 +28,7 @@ Typedef
 
 Description
     A floating-point number identical to float or double depending on
-    whether WM_SP or WM_DP is defined.
+    whether WM_SP, WM_SPDP or WM_DP is defined.
 
 SourceFiles
     scalar.C
@@ -43,13 +43,18 @@ SourceFiles
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
-#if defined(WM_SP)
+#if defined(WM_SP) || defined(WM_SPDP)
 
 // Define scalar as a float
 
 namespace Foam
 {
     typedef floatScalar scalar;
+    #if defined(WM_SPDP)
+    typedef doubleScalar solveScalar;
+    #else
+    typedef floatScalar solveScalar;
+    #endif
 
     constexpr scalar GREAT = floatScalarGREAT;
     constexpr scalar VGREAT = floatScalarVGREAT;
@@ -89,6 +94,7 @@ namespace Foam
 namespace Foam
 {
     typedef doubleScalar scalar;
+    typedef doubleScalar solveScalar;
 
     constexpr scalar GREAT = doubleScalarGREAT;
     constexpr scalar VGREAT = doubleScalarVGREAT;
diff --git a/src/OpenFOAM/primitives/Tensor/floatTensor/floatTensor.H b/src/OpenFOAM/primitives/Tensor/floatTensor/floatTensor.H
index 986b56b24c17e011b5d37cd48029ebffac1b3a94..5240625536ffab1f18ba28395b5eae6a46d8fa41 100644
--- a/src/OpenFOAM/primitives/Tensor/floatTensor/floatTensor.H
+++ b/src/OpenFOAM/primitives/Tensor/floatTensor/floatTensor.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) 2016 OpenFOAM Foundation
@@ -50,7 +50,7 @@ namespace Foam
 typedef Tensor<float> floatTensor;
 
 //- Data associated with floatTensor type are contiguous
-#if !defined(WM_SP)
+#if !defined(WM_SP) && !defined(WM_SPDP)
 template<>
 inline bool contiguous<floatTensor>() {return true;}
 #endif
diff --git a/src/OpenFOAM/primitives/Vector/complexVector/complexVector.C b/src/OpenFOAM/primitives/Vector/complexVector/complexVector.C
index bb99cf534b88ee7a579de77d5e4a834a5106f494..9e5f7f62ffcd85b9805780dfa765e1a133e8c5fc 100644
--- a/src/OpenFOAM/primitives/Vector/complexVector/complexVector.C
+++ b/src/OpenFOAM/primitives/Vector/complexVector/complexVector.C
@@ -44,37 +44,37 @@ const char* const Foam::complexVector::vsType::componentNames[] =
 template<>
 const Foam::complexVector Foam::complexVector::vsType::zero
 (
-    complexVector::uniform(complex::zero)
+    complexVector::uniform(pTraits<complex>::zero)
 );
 
 template<>
 const Foam::complexVector Foam::complexVector::vsType::one
 (
-    complexVector::uniform(complex::one)
+    complexVector::uniform(pTraits<complex>::one)
 );
 
 template<>
 const Foam::complexVector Foam::complexVector::vsType::max
 (
-    complexVector::uniform(complex(VGREAT, VGREAT))
+    complexVector::uniform(pTraits<complex>::max)
 );
 
 template<>
 const Foam::complexVector Foam::complexVector::vsType::min
 (
-    complexVector::uniform(complex(-VGREAT, -VGREAT))
+    complexVector::uniform(pTraits<complex>::min)
 );
 
 template<>
 const Foam::complexVector Foam::complexVector::vsType::rootMax
 (
-    complexVector::uniform(complex(ROOTVGREAT, ROOTVGREAT))
+    complexVector::uniform(pTraits<complex>::rootMax)
 );
 
 template<>
 const Foam::complexVector Foam::complexVector::vsType::rootMin
 (
-    complexVector::uniform(complex(-ROOTVGREAT, -ROOTVGREAT))
+    complexVector::uniform(pTraits<complex>::rootMin)
 );
 
 
diff --git a/src/OpenFOAM/primitives/Vector/floatVector/floatVector.H b/src/OpenFOAM/primitives/Vector/floatVector/floatVector.H
index 1337e8232574b80b0ed4ec452e5125ac062e090e..5c702f6d65d14bbc3e37377681c0be2aa4af9b16 100644
--- a/src/OpenFOAM/primitives/Vector/floatVector/floatVector.H
+++ b/src/OpenFOAM/primitives/Vector/floatVector/floatVector.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) 2011 OpenFOAM Foundation
@@ -50,7 +50,7 @@ namespace Foam
 typedef Vector<float> floatVector;
 
 //- Data associated with floatVector type are contiguous
-#if !defined(WM_SP)
+#if !defined(WM_SP) && !defined(WM_SPDP)
 template<>
 inline bool contiguous<floatVector>() {return true;}
 #endif
diff --git a/src/OpenFOAM/primitives/bools/Switch/Switch.C b/src/OpenFOAM/primitives/bools/Switch/Switch.C
index 56fc8fee687ef0cce338f50c9edc91b704896aa5..7d7e780fdf6d4b24d598770ad50106ee1fa72330 100644
--- a/src/OpenFOAM/primitives/bools/Switch/Switch.C
+++ b/src/OpenFOAM/primitives/bools/Switch/Switch.C
@@ -110,14 +110,14 @@ Foam::Switch::switchType Foam::Switch::parse
 }
 
 
-Foam::Switch Foam::Switch::lookupOrAddToDict
+Foam::Switch Foam::Switch::getOrAddToDict
 (
     const word& name,
     dictionary& dict,
-    const Switch defaultValue
+    const Switch deflt
 )
 {
-    return dict.lookupOrAddDefault<Switch>(name, defaultValue);
+    return dict.getOrAdd<Switch>(name, deflt);
 }
 
 
@@ -146,10 +146,10 @@ Foam::Switch::Switch
 (
     const word& key,
     const dictionary& dict,
-    const Switch defaultValue
+    const Switch deflt
 )
 :
-    Switch(defaultValue)
+    Switch(deflt)
 {
     const entry* eptr = dict.findEntry(key, keyType::LITERAL);
 
diff --git a/src/OpenFOAM/primitives/bools/Switch/Switch.H b/src/OpenFOAM/primitives/bools/Switch/Switch.H
index 0ab2a3ae0d2bfb08bdd78eb0d2e1adffd09062a3..907238897549d50e7916fc86667101560b5b8467 100644
--- a/src/OpenFOAM/primitives/bools/Switch/Switch.H
+++ b/src/OpenFOAM/primitives/bools/Switch/Switch.H
@@ -169,7 +169,7 @@ public:
         (
             const word& key,        //!< Lookup key. Uses LITERAL (not REGEX)
             const dictionary& dict, //!< dictionary
-            const Switch defaultValue //!< fallback if not found
+            const Switch deflt      //!< fallback if not found
         );
 
         //- Construct from Istream
@@ -180,11 +180,11 @@ public:
 
         //- Construct from dictionary, supplying default value so that if the
         //- value is not found, it is added into the dictionary.
-        static Switch lookupOrAddToDict
+        static Switch getOrAddToDict
         (
             const word& name,           //!< Lookup key. Uses REGEX!
             dictionary& dict,           //!< dictionary
-            const Switch defaultValue = switchType::FALSE //!< default to add
+            const Switch deflt = switchType::FALSE //!< default to add
         );
 
 
@@ -235,6 +235,18 @@ public:
 
     // Housekeeping
 
+        //- Construct from dictionary, supplying default value so that if the
+        //- value is not found, it is added into the dictionary.
+        static Switch lookupOrAddToDict
+        (
+            const word& name,           //!< Lookup key. Uses REGEX!
+            dictionary& dict,           //!< dictionary
+            const Switch deflt = switchType::FALSE //!< default to add
+        )
+        {
+            return getOrAddToDict(name, dict, deflt);
+        }
+
         //- Deprecated(2018-03) text representation of the Switch value
         //  \deprecated(2018-03) - use c_str() method
         inline const char* asText() const { return c_str(); };
diff --git a/src/OpenFOAM/primitives/complex/complex.C b/src/OpenFOAM/primitives/complex/complex.C
index 277864c487b54d8e421df9c21ac42c5dd6e609e1..a026a62a328c65271ff64629fbdd3668990839c1 100644
--- a/src/OpenFOAM/primitives/complex/complex.C
+++ b/src/OpenFOAM/primitives/complex/complex.C
@@ -30,13 +30,6 @@ License
 
 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
 
-const char* const Foam::complex::typeName = "complex";
-const Foam::complex Foam::complex::zero(0, 0);
-const Foam::complex Foam::complex::one(1, 0);
-
-
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
 const char* const Foam::pTraits<Foam::complex>::typeName = "complex";
 const char* const Foam::pTraits<Foam::complex>::componentNames[] = {"re", "im"};
 
@@ -69,7 +62,6 @@ Foam::pTraits<Foam::complex>::pTraits(Istream& is)
 }
 
 
-
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
 Foam::complex::complex(Istream& is)
@@ -78,7 +70,7 @@ Foam::complex::complex(Istream& is)
 }
 
 
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+// * * * * * * * * * * * * * * * Global Functions  * * * * * * * * * * * * * //
 
 Foam::word Foam::name(const complex& c)
 {
diff --git a/src/OpenFOAM/primitives/complex/complex.H b/src/OpenFOAM/primitives/complex/complex.H
index 06f4eded4e134772989b248fe574f929088cb592..ab1231745677b112a633edc9e03c58d59bce0e9e 100644
--- a/src/OpenFOAM/primitives/complex/complex.H
+++ b/src/OpenFOAM/primitives/complex/complex.H
@@ -39,6 +39,7 @@ SourceFiles
 #define complex_H
 
 #include <complex>
+#include <type_traits>
 #include "scalar.H"
 #include "word.H"
 #include "zero.H"
@@ -59,13 +60,17 @@ inline const complex& min(const complex&, const complex&);
 inline const complex& max(const complex&, const complex&);
 inline complex limit(const complex&, const complex&);
 inline const complex& sum(const complex&);
-inline complex operator+(const complex&, const complex&);
 inline complex operator-(const complex&);
+inline complex operator+(const complex&, const complex&);
+inline complex operator+(const complex&, const scalar);
+inline complex operator+(const scalar, const complex&);
 inline complex operator-(const complex&, const complex&);
+inline complex operator-(const complex&, const scalar);
+inline complex operator-(const scalar, const complex&);
 inline complex operator*(const complex&, const complex&);
-inline complex operator/(const complex&, const complex&);
-inline complex operator*(const scalar, const complex&);
 inline complex operator*(const complex&, const scalar);
+inline complex operator*(const scalar, const complex&);
+inline complex operator/(const complex&, const complex&);
 inline complex operator/(const complex&, const scalar);
 inline complex operator/(const scalar, const complex&);
 
@@ -84,22 +89,6 @@ class complex
 
 public:
 
-    //- Component type
-    typedef complex cmptType;
-
-
-    // Static Data Members
-
-        //- The type name is "complex"
-        static const char* const typeName;
-
-        //- A complex zero (0,0)
-        static const complex zero;
-
-        //- A complex one (1,0)
-        static const complex one;
-
-
     // Constructors
 
         //- Construct null as zero-initialized
@@ -189,15 +178,19 @@ public:
         //- Assign zero
         inline void operator=(const Foam::zero);
 
-        inline void operator+=(const complex& c);
-        inline void operator-=(const complex& c);
-        inline void operator*=(const complex& c);
-        inline void operator/=(const complex& c);
-
+        //- Assign scalar (imag = zero)
         inline void operator=(const scalar s);
+
+        inline void operator+=(const complex& c);
         inline void operator+=(const scalar s);
+
+        inline void operator-=(const complex& c);
         inline void operator-=(const scalar s);
+
+        inline void operator*=(const complex& c);
         inline void operator*=(const scalar s);
+
+        inline void operator/=(const complex& c);
         inline void operator/=(const scalar s);
 
         inline bool operator==(const complex& c) const;
@@ -209,29 +202,45 @@ public:
         friend scalar magSqr(const complex& c);
         friend scalar mag(const complex& c);
         friend complex sqr(const complex& c);
-        friend const complex& min(const complex&, const complex&);
-        friend const complex& max(const complex&, const complex&);
 
-        friend complex limit(const complex&, const complex&);
+        //- sgn() https://en.wikipedia.org/wiki/Sign_function#Complex_signum
+        friend complex sign(const complex& c);
 
-        friend const complex& sum(const complex&);
+        //- csgn() https://en.wikipedia.org/wiki/Sign_function#Complex_signum
+        friend scalar csign(const complex& c);
+
+        friend const complex& min(const complex& c1, const complex& c2);
+        friend const complex& max(const complex& c1, const complex& c2);
+        friend complex limit(const complex& c1, const complex& c2);
+        friend const complex& sum(const complex& c);
 
 
     // Friend Operators
 
-        friend complex operator+(const complex& c1, const complex& c2);
         friend complex operator-(const complex& c);
+
+        friend complex operator+(const complex& c1, const complex& c2);
+        friend complex operator+(const complex& c, const scalar s);
+        friend complex operator+(const scalar s, const complex& c);
+
         friend complex operator-(const complex& c1, const complex& c2);
-        friend complex operator*(const complex& c1, const complex& c2);
-        friend complex operator/(const complex& c1, const complex& c2);
+        friend complex operator-(const complex& c, const scalar s);
+        friend complex operator-(const scalar s, const complex& c);
 
-        friend complex operator*(const scalar s, const complex& c);
+        friend complex operator*(const complex& c1, const complex& c2);
         friend complex operator*(const complex& c, const scalar s);
+        friend complex operator*(const scalar s, const complex& c);
+
+        friend complex operator/(const complex& c1, const complex& c2);
         friend complex operator/(const complex& c, const scalar s);
         friend complex operator/(const scalar s, const complex& c);
 };
 
 
+/*---------------------------------------------------------------------------*\
+                      Class pTraits<complex> Declaration
+\*---------------------------------------------------------------------------*/
+
 // Template specialisation for pTraits<complex>
 template<>
 class pTraits<complex>
@@ -247,7 +256,7 @@ public:
     typedef label labelType;
 
 
-    // Member constants
+    // Member Constants
 
         //- Dimensionality of space
         static constexpr direction dim = 3;
@@ -263,12 +272,13 @@ public:
 
         static const char* const typeName;
         static const char* const componentNames[];
-        static const complex zero;
-        static const complex one;
-        static const complex max;
-        static const complex min;
-        static const complex rootMax;
-        static const complex rootMin;
+
+        static const complex zero;      //!< complex (0,0)
+        static const complex one;       //!< complex (1,0)
+        static const complex min;       //!< complex (-VGREAT,-VGREAT)
+        static const complex max;       //!< complex (VGREAT,VGREAT)
+        static const complex rootMin;   //!< complex (-ROOTVGREAT, -ROOTVGREAT)
+        static const complex rootMax;   //!< complex (ROOTVGREAT, ROOTVGREAT)
 
 
     // Constructors
@@ -296,6 +306,41 @@ public:
 };
 
 
+/*---------------------------------------------------------------------------*\
+                               Namespace Detail
+\*---------------------------------------------------------------------------*/
+
+namespace Detail
+{
+    // Helper functions for complex, in Detail namespace to avoid possible
+    // name collisions (could change in the future)
+
+    //- The 'conjugate' of non-complex returns itself (pass-through)
+    //- it does not return a complex!
+    template<class T>
+    typename std::enable_if
+    <
+        !std::is_same<complex, T>::value,
+        const T&
+    >::type conj(const T& val)
+    {
+        return val;
+    }
+
+    //- The conjugate of a complex number
+    template<class T>
+    typename std::enable_if
+    <
+        std::is_same<complex, T>::value,
+        complex
+    >::type conj(const T& val)
+    {
+        return val.conjugate();
+    }
+
+} // End namespace Detail
+
+
 // * * * * * * * * * * * * * * * Global Operators  * * * * * * * * * * * * * //
 
 Istream& operator>>(Istream& is, complex& c);
diff --git a/src/OpenFOAM/primitives/complex/complexI.H b/src/OpenFOAM/primitives/complex/complexI.H
index 16e8594fb439d5501fcc00425563b6c9cd23fa76..4b98681dac1b40994bda2ab23dc66aa483117c0a 100644
--- a/src/OpenFOAM/primitives/complex/complexI.H
+++ b/src/OpenFOAM/primitives/complex/complexI.H
@@ -129,55 +129,55 @@ inline void Foam::complex::operator=(const Foam::zero)
 }
 
 
-inline void Foam::complex::operator+=(const complex& c)
+inline void Foam::complex::operator=(const scalar s)
 {
-    re += c.re;
-    im += c.im;
+    re = s;
+    im = 0;
 }
 
 
-inline void Foam::complex::operator-=(const complex& c)
+inline void Foam::complex::operator+=(const complex& c)
 {
-    re -= c.re;
-    im -= c.im;
+    re += c.re;
+    im += c.im;
 }
 
 
-inline void Foam::complex::operator*=(const complex& c)
+inline void Foam::complex::operator+=(const scalar s)
 {
-    *this = (*this)*c;
+    re += s;
 }
 
 
-inline void Foam::complex::operator/=(const complex& c)
+inline void Foam::complex::operator-=(const complex& c)
 {
-    *this = *this/c;
+    re -= c.re;
+    im -= c.im;
 }
 
 
-inline void Foam::complex::operator=(const scalar s)
+inline void Foam::complex::operator-=(const scalar s)
 {
-    re = s;
-    im = 0;
+    re -= s;
 }
 
 
-inline void Foam::complex::operator+=(const scalar s)
+inline void Foam::complex::operator*=(const complex& c)
 {
-    re += s;
+    *this = (*this)*c;
 }
 
 
-inline void Foam::complex::operator-=(const scalar s)
+inline void Foam::complex::operator*=(const scalar s)
 {
-    re -= s;
+    re *= s;
+    im *= s;
 }
 
 
-inline void Foam::complex::operator*=(const scalar s)
+inline void Foam::complex::operator/=(const complex& c)
 {
-    re *= s;
-    im *= s;
+    *this = *this/c;
 }
 
 
@@ -221,13 +221,26 @@ inline scalar magSqr(const complex& c)
 
 inline scalar mag(const complex& c)
 {
-    return sqrt(magSqr(c)); // OR std::hypot(c.re, c.im);
+    return std::hypot(c.re, c.im);
 }
 
 
 inline complex sqr(const complex& c)
 {
-    return c * c;
+    return c*c;
+}
+
+
+inline complex sign(const complex& c)
+{
+    const scalar s(mag(c));
+    return s < ROOTVSMALL ? Zero : c/s;
+}
+
+
+inline scalar csign(const complex& c)
+{
+    return equal(c.Re(), 0) ? sign(c.Im()) : sign(c.Re());
 }
 
 
@@ -275,6 +288,12 @@ inline complex transform(const Tensor<scalar>&, const complex c)
 
 // * * * * * * * * * * * * * * * Friend Operators  * * * * * * * * * * * * * //
 
+inline complex operator-(const complex& c)
+{
+    return complex(-c.re, -c.im);
+}
+
+
 inline complex operator+(const complex& c1, const complex& c2)
 {
     return complex
@@ -285,13 +304,15 @@ inline complex operator+(const complex& c1, const complex& c2)
 }
 
 
-inline complex operator-(const complex& c)
+inline complex operator+(const complex& c, const scalar s)
 {
-    return complex
-    (
-        -c.re,
-        -c.im
-    );
+    return complex(c.re + s, c.im);
+}
+
+
+inline complex operator+(const scalar s, const complex& c)
+{
+    return complex(c.re + s, c.im);
 }
 
 
@@ -305,6 +326,18 @@ inline complex operator-(const complex& c1, const complex& c2)
 }
 
 
+inline complex operator-(const complex& c, const scalar s)
+{
+    return complex(c.re - s, c.im);
+}
+
+
+inline complex operator-(const scalar s, const complex& c)
+{
+    return complex(s - c.re, -c.im);
+}
+
+
 inline complex operator*(const complex& c1, const complex& c2)
 {
     return complex
@@ -315,15 +348,9 @@ inline complex operator*(const complex& c1, const complex& c2)
 }
 
 
-inline complex operator/(const complex& c1, const complex& c2)
+inline complex operator*(const complex& c, const scalar s)
 {
-    const scalar sqrC2 = magSqr(c2);
-
-    return complex
-    (
-        (c1.re*c2.re + c1.im*c2.im)/sqrC2,
-        (c1.im*c2.re - c1.re*c2.im)/sqrC2
-    );
+    return complex(s*c.re, s*c.im);
 }
 
 
@@ -333,9 +360,15 @@ inline complex operator*(const scalar s, const complex& c)
 }
 
 
-inline complex operator*(const complex& c, const scalar s)
+inline complex operator/(const complex& c1, const complex& c2)
 {
-    return complex(s*c.re, s*c.im);
+    const scalar sqrC2 = magSqr(c2);
+
+    return complex
+    (
+        (c1.re*c2.re + c1.im*c2.im)/sqrC2,
+        (c1.im*c2.re - c1.re*c2.im)/sqrC2
+    );
 }
 
 
@@ -347,7 +380,7 @@ inline complex operator/(const complex& c, const scalar s)
 
 inline complex operator/(const scalar s, const complex& c)
 {
-    return complex(s/c.re, s/c.im);
+    return complex(s)/c;
 }
 
 
diff --git a/src/OpenFOAM/primitives/enums/Enum.C b/src/OpenFOAM/primitives/enums/Enum.C
index 1e269ff4ede1989814249bfec1da5f2d03cdae96..1ef0c4cc51cf8d44758ab48c8a3d944a9b2ff85c 100644
--- a/src/OpenFOAM/primitives/enums/Enum.C
+++ b/src/OpenFOAM/primitives/enums/Enum.C
@@ -81,14 +81,14 @@ template<class EnumType>
 EnumType Foam::Enum<EnumType>::get
 (
     const word& enumName,
-    const EnumType defaultValue
+    const EnumType deflt
 ) const
 {
     const label idx = find(enumName);
 
     if (idx < 0)
     {
-        return defaultValue;
+        return deflt;
     }
 
     return EnumType(vals_[idx]);
@@ -136,11 +136,11 @@ EnumType Foam::Enum<EnumType>::get
 
 
 template<class EnumType>
-EnumType Foam::Enum<EnumType>::lookupOrDefault
+EnumType Foam::Enum<EnumType>::getOrDefault
 (
     const word& key,
     const dictionary& dict,
-    const EnumType defaultValue,
+    const EnumType deflt,
     const bool failsafe
 ) const
 {
@@ -163,8 +163,8 @@ EnumType Foam::Enum<EnumType>::lookupOrDefault
         {
             IOWarningInFunction(dict)
                 << enumName << " is not in enumeration: " << *this << nl
-                << "using failsafe " << get(defaultValue)
-                << " (value " << int(defaultValue) << ")" << endl;
+                << "using failsafe " << get(deflt)
+                << " (value " << int(deflt) << ")" << endl;
         }
         else
         {
@@ -174,7 +174,7 @@ EnumType Foam::Enum<EnumType>::lookupOrDefault
         }
     }
 
-    return defaultValue;
+    return deflt;
 }
 
 
diff --git a/src/OpenFOAM/primitives/enums/Enum.H b/src/OpenFOAM/primitives/enums/Enum.H
index b5ef2a362444626456533d27cf0aca02878b6b1e..ede847bfc9064c545e0d04038374c9288ac6e858 100644
--- a/src/OpenFOAM/primitives/enums/Enum.H
+++ b/src/OpenFOAM/primitives/enums/Enum.H
@@ -132,7 +132,7 @@ public:
 
         //- The enumeration corresponding to the given name.
         //  \return The enumeration or default if not found.
-        EnumType get(const word& enumName, const EnumType defaultValue) const;
+        EnumType get(const word& enumName, const EnumType deflt) const;
 
         //- The name corresponding to the given enumeration.
         //  Return an empty word if not found.
@@ -155,11 +155,11 @@ public:
         //
         //  \return The value found or default if not found in dictionary.
         //  FatalError (or Warning) if the enumerated name was incorrect.
-        EnumType lookupOrDefault
+        EnumType getOrDefault
         (
             const word& key,        //!< Lookup key. Uses LITERAL (not REGEX)
             const dictionary& dict, //!< dictionary
-            const EnumType defaultValue, //!< fallback if not found
+            const EnumType deflt,   //!< fallback if not found
             const bool failsafe = false  //!< Warn only on bad enumeration
         ) const;
 
@@ -216,33 +216,51 @@ public:
         inline const word& operator[](const EnumType e) const;
 
         //- Return the enumeration corresponding to the given name or
-        //- defaultValue if the name is not found.
+        //- deflt if the name is not found.
         inline EnumType operator()
         (
             const word& enumName,
-            const EnumType defaultValue
+            const EnumType deflt
         ) const;
 
 
     // Housekeeping
 
+        //- Find the key in the dictionary and return the corresponding
+        //- enumeration element based on its name.
+        //
+        //  \return The value found or default if not found in dictionary.
+        //  FatalError (or Warning) if the enumerated name was incorrect.
+        EnumType lookupOrDefault
+        (
+            const word& key,        //!< Lookup key. Uses LITERAL (not REGEX)
+            const dictionary& dict, //!< dictionary
+            const EnumType deflt,   //!< fallback if not found
+            const bool failsafe = false //!< Warn only on bad enumeration
+        ) const
+        {
+            return getOrDefault(key, dict, deflt, failsafe);
+        }
+
         //- Deprecated(2018-10) same as two-parameter get()
         //  \deprecated(2018-10) - use two-parameter get() method
-        inline EnumType lookup(const word& key, const dictionary& dict) const
+        EnumType FOAM_DEPRECATED_FOR(2018-10, "get() method")
+        lookup(const word& key, const dictionary& dict) const
         {
             return get(key, dict);
         }
 
         //- Deprecated(2018-10) lookupOrDefault with warnings instead of error.
-        //  \deprecated(2018-10) - use lookupOrDefault() with failsafe option
-        EnumType lookupOrFailsafe
+        //  \deprecated(2018-10) - use getOrDefault() with failsafe option
+        EnumType FOAM_DEPRECATED_FOR(2018-10, "getOrDefault() method")
+        lookupOrFailsafe
         (
             const word& key,
             const dictionary& dict,
-            const EnumType defaultValue
+            const EnumType deflt
         ) const
         {
-            return lookupOrDefault(key, dict, defaultValue, true);
+            return getOrDefault(key, dict, deflt, true);
         }
 };
 
diff --git a/src/OpenFOAM/primitives/ops/ops.H b/src/OpenFOAM/primitives/ops/ops.H
index c47888e8d78c78f064778b07c861f9e5dc5a4b51..2692eff18f6a9449c5913c6a846ec90c070bb01b 100644
--- a/src/OpenFOAM/primitives/ops/ops.H
+++ b/src/OpenFOAM/primitives/ops/ops.H
@@ -27,9 +27,9 @@ InNamespace
     Foam
 
 Description
-    Various function objects for unary and binary operations.
+    Various functors for unary and binary operations.
     Can be used for parallel combine-reduce operations or other places
-    requiring a function object.
+    requiring a functor.
 
 \*---------------------------------------------------------------------------*/
 
@@ -159,6 +159,25 @@ EqOp(nopEq, (void)x)
     };
 
 
+// Operations taking one parameter, returning bool.
+// The comparison value is defined during construction
+
+#define Bool1Op(opName, op)                                                    \
+                                                                               \
+    template<class T>                                                          \
+    struct opName##Op1                                                         \
+    {                                                                          \
+        const T& value;                                                        \
+                                                                               \
+        opName##Op1(const T& v) : value(v) {}                                  \
+                                                                               \
+        bool operator()(const T& x) const WARNRETURN                           \
+        {                                                                      \
+            return op;                                                         \
+        }                                                                      \
+    };
+
+
 // Weighting operations
 
 #define WeightedOp(opName, op)                                                 \
@@ -216,10 +235,18 @@ BoolOp(lessEq, x <= y)
 BoolOp(greater, x > y)
 BoolOp(greaterEq, x >= y)
 
+Bool1Op(equal, x == value)
+Bool1Op(notEqual, x != value)
+Bool1Op(less, x < value)
+Bool1Op(lessEq, x <= value)
+Bool1Op(greater, x > value)
+Bool1Op(greaterEq, x >= value)
+
 WeightedOp(multiply, (weight*y))
 
 #undef Op
 #undef BoolOp
+#undef Bool1Op
 #undef WeightedOp
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
diff --git a/src/OpenFOAM/primitives/ranges/MinMax/MinMax.H b/src/OpenFOAM/primitives/ranges/MinMax/MinMax.H
index 59b1f16201068dc9d0fac04724837ef87e9a10a9..6c78dfccc9d3a58434e40222bbf936b8654b895c 100644
--- a/src/OpenFOAM/primitives/ranges/MinMax/MinMax.H
+++ b/src/OpenFOAM/primitives/ranges/MinMax/MinMax.H
@@ -161,6 +161,12 @@ public:
 
     // Static Member Functions
 
+        //- A semi-infinite range from minVal to the type max
+        inline static MinMax<T> ge(const T& minVal);
+
+        //- A semi-infinite range from type min to maxVal
+        inline static MinMax<T> le(const T& maxVal);
+
         //- A 0-1 range corresponding to the pTraits zero, one
         inline static MinMax<T> zero_one();
 
diff --git a/src/OpenFOAM/primitives/ranges/MinMax/MinMaxI.H b/src/OpenFOAM/primitives/ranges/MinMax/MinMaxI.H
index afdf34916d467a36443c04fe7a86b6ecf1f8f350..d6ef1ab38e198811face2901e38de4f7f49665da 100644
--- a/src/OpenFOAM/primitives/ranges/MinMax/MinMaxI.H
+++ b/src/OpenFOAM/primitives/ranges/MinMax/MinMaxI.H
@@ -25,6 +25,20 @@ License
 
 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
 
+template<class T>
+inline Foam::MinMax<T> Foam::MinMax<T>::ge(const T& minVal)
+{
+    return MinMax<T>(minVal, pTraits<T>::max);
+}
+
+
+template<class T>
+inline Foam::MinMax<T> Foam::MinMax<T>::le(const T& maxVal)
+{
+    return MinMax<T>(pTraits<T>::min, maxVal);
+}
+
+
 template<class T>
 inline Foam::MinMax<T> Foam::MinMax<T>::zero_one()
 {
diff --git a/src/OpenFOAM/primitives/ranges/scalarRange/scalarRange.C b/src/OpenFOAM/primitives/ranges/scalarRange/scalarRange.C
index 221101fcf0313260b9ea022e2aa5546d6a1882ff..0786ed5ce73b235175d9d58dfba656c1f4aa83d1 100644
--- a/src/OpenFOAM/primitives/ranges/scalarRange/scalarRange.C
+++ b/src/OpenFOAM/primitives/ranges/scalarRange/scalarRange.C
@@ -36,8 +36,8 @@ const Foam::scalarRange Foam::scalarRange::null;
 const Foam::scalarRange Foam::scalarRange::always
 (
     scalarRange::ALWAYS,
-    -Foam::GREAT,
-    Foam::GREAT
+    -GREAT,
+    GREAT
 );
 
 
@@ -158,21 +158,21 @@ Foam::Ostream& Foam::operator<<(Ostream& os, const scalarRange& range)
     switch (range.type_)
     {
         case scalarRange::EQ:
-            os << range.min_;
+            os << range.min();
             break;
 
         case scalarRange::GE:
         case scalarRange::GT:
-            os << range.min_ << ":Inf";
+            os << range.min() << ":Inf";
             break;
 
         case scalarRange::LE:
         case scalarRange::LT:
-            os << "-Inf:" << range.max_;
+            os << "-Inf:" << range.max();
             break;
 
         case scalarRange::GE_LE:
-            os << range.min_ << ':' << range.max_;
+            os << range.min() << ':' << range.max();
             break;
 
         case scalarRange::ALWAYS:
diff --git a/src/OpenFOAM/primitives/ranges/scalarRange/scalarRange.H b/src/OpenFOAM/primitives/ranges/scalarRange/scalarRange.H
index 973f446de2d7f032886376cf4bad03060b8c6033..f71c97cf49365e3952c5c4e407cd36257959977b 100644
--- a/src/OpenFOAM/primitives/ranges/scalarRange/scalarRange.H
+++ b/src/OpenFOAM/primitives/ranges/scalarRange/scalarRange.H
@@ -34,6 +34,7 @@ Description
     used to define an empty (inverse) range.
 
 SeeAlso
+    Foam::MinMax
     Foam::predicates::scalars
 
 SourceFiles
@@ -154,18 +155,27 @@ public:
         static scalarRange parse(const std::string& str);
 
 
-        //- Construct a greater-than-equals bound
+        //- Construct a greater-equals bound
         inline static scalarRange ge(const scalar minVal) noexcept;
 
         //- Construct a greater-than bound
         inline static scalarRange gt(const scalar minVal) noexcept;
 
-        //- Construct a less-than-equals bound
+        //- Construct a greater-equals zero bound
+        inline static scalarRange ge0() noexcept;
+
+        //- Construct a greater-than zero bound
+        inline static scalarRange gt0() noexcept;
+
+        //- Construct a less-equals bound
         inline static scalarRange le(const scalar maxVal) noexcept;
 
         //- Construct a less-than bound
         inline static scalarRange lt(const scalar maxVal) noexcept;
 
+        //- Construct a greater-equals 0, less-equals 1 bound
+        inline static scalarRange zero_one() noexcept;
+
 
     // Member Functions
 
@@ -192,13 +202,13 @@ public:
         inline scalar value() const;
 
         //- True if the value matches the condition.
-        inline bool match(const scalar& value) const;
+        inline bool match(const scalar& val) const;
 
 
     // Member Operators
 
         //- Identical to match(), for use as a predicate.
-        inline bool operator()(const scalar& value) const;
+        inline bool operator()(const scalar& val) const;
 
         inline bool operator==(const scalarRange& rhs) const noexcept;
         inline bool operator!=(const scalarRange& rhs) const noexcept;
diff --git a/src/OpenFOAM/primitives/ranges/scalarRange/scalarRangeI.H b/src/OpenFOAM/primitives/ranges/scalarRange/scalarRangeI.H
index 7de2ee93b769ec1e12cd6dbf9601f17b1e9a6122..42081f162720bc5829522efc3989cabd9c2e6251 100644
--- a/src/OpenFOAM/primitives/ranges/scalarRange/scalarRangeI.H
+++ b/src/OpenFOAM/primitives/ranges/scalarRange/scalarRangeI.H
@@ -40,7 +40,7 @@ inline Foam::scalarRange::scalarRange
 
 inline Foam::scalarRange::scalarRange() noexcept
 :
-    scalarRange(scalarRange::NONE, Foam::GREAT, -Foam::GREAT)
+    scalarRange(scalarRange::NONE, GREAT, -GREAT)
 {}
 
 
@@ -62,7 +62,7 @@ inline Foam::scalarRange::scalarRange
     {
         clear();  // Inverted - explicitly mark as such
     }
-    else if (minVal == maxVal)
+    else if (equal(minVal, maxVal))
     {
         type_ = EQ;
     }
@@ -71,24 +71,42 @@ inline Foam::scalarRange::scalarRange
 
 inline Foam::scalarRange Foam::scalarRange::ge(const scalar minVal) noexcept
 {
-    return scalarRange(GE, minVal, Foam::VGREAT);
+    return scalarRange(scalarRange::GE, minVal, GREAT);
 }
 
 
 inline Foam::scalarRange Foam::scalarRange::gt(const scalar minVal) noexcept
 {
-    return scalarRange(GT, minVal, Foam::VGREAT);
+    return scalarRange(scalarRange::GT, minVal, GREAT);
+}
+
+
+inline Foam::scalarRange Foam::scalarRange::ge0() noexcept
+{
+    return scalarRange(scalarRange::GE, 0, GREAT);
+}
+
+
+inline Foam::scalarRange Foam::scalarRange::gt0() noexcept
+{
+    return scalarRange(scalarRange::GT, 0, GREAT);
 }
 
 
 inline Foam::scalarRange Foam::scalarRange::le(const scalar maxVal) noexcept
 {
-    return scalarRange(LE, -Foam::VGREAT, maxVal);
+    return scalarRange(scalarRange::LE, -GREAT, maxVal);
 }
 
 inline Foam::scalarRange Foam::scalarRange::lt(const scalar maxVal) noexcept
 {
-    return scalarRange(LT, -Foam::VGREAT, maxVal);
+    return scalarRange(scalarRange::LT, -GREAT, maxVal);
+}
+
+
+inline Foam::scalarRange Foam::scalarRange::zero_one() noexcept
+{
+    return scalarRange(scalarRange::GE_LE, 0, 1);
 }
 
 
@@ -96,8 +114,8 @@ inline Foam::scalarRange Foam::scalarRange::lt(const scalar maxVal) noexcept
 
 inline void Foam::scalarRange::clear() noexcept
 {
-    min_ = Foam::GREAT;
-    max_ = -Foam::GREAT;
+    min_ = GREAT;
+    max_ = -GREAT;
     type_ = scalarRange::NONE;
 }
 
@@ -136,16 +154,16 @@ inline Foam::scalar Foam::scalarRange::value() const
 {
     switch (type_)
     {
-        case EQ:    // For equals, min and max are identical
-        case GE:
-        case GT:
+        case scalarRange::EQ: // For equals, min and max are identical
+        case scalarRange::GE:
+        case scalarRange::GT:
             return min_;
 
-        case LE:
-        case LT:
+        case scalarRange::LE:
+        case scalarRange::LT:
             return max_;
 
-        case GE_LE:
+        case scalarRange::GE_LE:
             // Multiply before adding to avoid possible overflow
             return (0.5 * min_) + (0.5 * max_);
 
@@ -155,16 +173,16 @@ inline Foam::scalar Foam::scalarRange::value() const
 }
 
 
-inline bool Foam::scalarRange::match(const scalar& value) const
+inline bool Foam::scalarRange::match(const scalar& val) const
 {
     switch (type_)
     {
-        case EQ:    return equal(value, min_);
-        case GE:    return (value >= min_);
-        case GT:    return (value > min_);
-        case LE:    return (value <= max_);
-        case LT:    return (value < max_);
-        case GE_LE: return (value >= min_ && value <= max_);
+        case EQ:    return equal(val, min_);
+        case GE:    return (val >= min_);
+        case GT:    return (val > min_);
+        case LE:    return (val <= max_);
+        case LT:    return (val < max_);
+        case GE_LE: return (val >= min_ && val <= max_);
         case ALWAYS: return true;
         default:    return false;
     }
@@ -173,9 +191,9 @@ inline bool Foam::scalarRange::match(const scalar& value) const
 
 // * * * * * * * * * * * * * * * Member Operators  * * * * * * * * * * * * * //
 
-inline bool Foam::scalarRange::operator()(const scalar& value) const
+inline bool Foam::scalarRange::operator()(const scalar& val) const
 {
-    return match(value);
+    return match(val);
 }
 
 
diff --git a/src/OpenFOAM/primitives/ranges/scalarRange/scalarRanges.H b/src/OpenFOAM/primitives/ranges/scalarRange/scalarRanges.H
index 1de90bb0f5d4bf308c8be91f116d444a76956b12..d94795b4308c8711a83e84ac49ba6f29014e96c5 100644
--- a/src/OpenFOAM/primitives/ranges/scalarRange/scalarRanges.H
+++ b/src/OpenFOAM/primitives/ranges/scalarRange/scalarRanges.H
@@ -67,7 +67,11 @@ public:
         //- Construct by parsing string for scalar ranges
         //  The individual items are space, comma or semicolon delimited.
         //  Optionally report when any range failed to parse
-        inline scalarRanges(const std::string& str, bool verbose = true);
+        inline explicit scalarRanges
+        (
+            const std::string& str,
+            bool verbose = true
+        );
 
 
     // Static Constructors
diff --git a/src/OpenFOAM/primitives/ranges/tableBounds/tableBounds.C b/src/OpenFOAM/primitives/ranges/tableBounds/tableBounds.C
index 38c811534326ba85167b44a2e23ab36aed90dcac..151946eb287cf9ce80544c7c1df7bff988e25b48 100644
--- a/src/OpenFOAM/primitives/ranges/tableBounds/tableBounds.C
+++ b/src/OpenFOAM/primitives/ranges/tableBounds/tableBounds.C
@@ -29,21 +29,21 @@ License
 
 const Foam::Enum<Foam::bounds::normalBounding>
 Foam::bounds::normalBoundingNames
-{
+({
     { normalBounding::ERROR, "error" },
     { normalBounding::WARN,  "warn" },
     { normalBounding::CLAMP, "clamp" },
-};
+});
 
 
 const Foam::Enum<Foam::bounds::repeatableBounding>
 Foam::bounds::repeatableBoundingNames
-{
+({
     { repeatableBounding::ERROR, "error" },
     { repeatableBounding::WARN,  "warn" },
     { repeatableBounding::CLAMP, "clamp" },
     { repeatableBounding::REPEAT, "repeat" },
-};
+});
 
 
 // ************************************************************************* //
diff --git a/src/OpenFOAM/primitives/strings/lists/hashedWordList.H b/src/OpenFOAM/primitives/strings/lists/hashedWordList.H
index cd401dbb5afc0b2f2b94a24a09e78e2e48a8fb44..f58fc24838c32c5a2d6d5435a74fc7088968d827 100644
--- a/src/OpenFOAM/primitives/strings/lists/hashedWordList.H
+++ b/src/OpenFOAM/primitives/strings/lists/hashedWordList.H
@@ -182,10 +182,10 @@ public:
 
         //- Deprecated(2019-01) Is the specified name found in the list?
         //  \deprecated(2019-01) - use found() method
-        inline bool contains(const word& name) const
-        FOAM_DEPRECATED_FOR(2019-01, "found() method")
+        bool FOAM_DEPRECATED_FOR(2019-01, "found() method")
+        contains(const word& name) const
         {
-            return this-found(name);
+            return this->found(name);
         }
 };
 
diff --git a/src/OpenFOAM/primitives/strings/parsing/parsing.C b/src/OpenFOAM/primitives/strings/parsing/parsing.C
index bb3a38564b3dbaa797d9c952fafac4aee5d519c7..fa9c3aaa4f687b24a067b3c262d537795d191baa 100644
--- a/src/OpenFOAM/primitives/strings/parsing/parsing.C
+++ b/src/OpenFOAM/primitives/strings/parsing/parsing.C
@@ -29,11 +29,11 @@ License
 
 const Foam::Enum<Foam::parsing::errorType>
 Foam::parsing::errorNames
-{
+({
     { errorType::GENERAL, "General error parsing" },
     { errorType::RANGE, "Range error while parsing" },
     { errorType::TRAILING, "Trailing content found parsing" },
-};
+});
 
 
 // ************************************************************************* //
diff --git a/src/OpenFOAM/primitives/strings/regex/regExpCxx.C b/src/OpenFOAM/primitives/strings/regex/regExpCxx.C
index 0f99c82dc1a976d03ae6002f99232bd541c59906..f5dfe943c49ca5494686643be8e1c012e1aec47e 100644
--- a/src/OpenFOAM/primitives/strings/regex/regExpCxx.C
+++ b/src/OpenFOAM/primitives/strings/regex/regExpCxx.C
@@ -108,7 +108,7 @@ static std::string error_string(const std::regex_error& err)
 
 bool Foam::regExpCxx::set(const char* pattern, bool ignoreCase)
 {
-    clear();
+    clear();  // Also sets ok_ = false
 
     size_t len = (pattern ? strlen(pattern) : 0);
 
@@ -139,7 +139,7 @@ bool Foam::regExpCxx::set(const char* pattern, bool ignoreCase)
         try
         {
             re_.assign(pat, flags);
-            return true;
+            ok_ = true;
         }
         catch (const std::regex_error& err)
         {
@@ -151,13 +151,13 @@ bool Foam::regExpCxx::set(const char* pattern, bool ignoreCase)
         }
     }
 
-    return false;
+    return ok_;
 }
 
 
 bool Foam::regExpCxx::set(const std::string& pattern, bool ignoreCase)
 {
-    clear();
+    clear();  // Also sets ok_ = false
 
     auto len = pattern.size();
 
@@ -188,7 +188,7 @@ bool Foam::regExpCxx::set(const std::string& pattern, bool ignoreCase)
         try
         {
             re_.assign(pat, pattern.end(), flags);
-            return true;
+            ok_ = true;
         }
         catch (const std::regex_error& err)
         {
@@ -200,7 +200,7 @@ bool Foam::regExpCxx::set(const std::string& pattern, bool ignoreCase)
         }
     }
 
-    return false;
+    return ok_;
 }
 
 
diff --git a/src/OpenFOAM/primitives/strings/regex/regExpCxx.H b/src/OpenFOAM/primitives/strings/regex/regExpCxx.H
index a96ad8e84aa6f2223c98c3b1572dda322896d891..d56d16f927bd8a122334180b0d82bca85e9ec6f2 100644
--- a/src/OpenFOAM/primitives/strings/regex/regExpCxx.H
+++ b/src/OpenFOAM/primitives/strings/regex/regExpCxx.H
@@ -41,7 +41,7 @@ Description
 Note
     The C++11 regular expressions may be broken on some compilers.
     For example, gcc 4.8 is known to fail.
-    For these systems the POSIX implementation should be used.
+    For these systems the POSIX implementation or alternative must be used.
 
 SourceFiles
     regExpCxxI.H
@@ -66,7 +66,7 @@ namespace Foam
 
 class regExpCxx
 {
-    // Private data
+    // Private Data
 
         //- Regular expression (using char type)
         std::regex re_;
@@ -132,7 +132,7 @@ public:
     ~regExpCxx() = default;
 
 
-    // Member functions
+    // Member Functions
 
     // Access
 
diff --git a/src/OpenFOAM/primitives/strings/regex/regExpCxxI.H b/src/OpenFOAM/primitives/strings/regex/regExpCxxI.H
index 92d84a003782ac92ba5cb54858fb41301e6801c5..b60cbf1e8c9cfa2f571e316670d85673cb35a5a5 100644
--- a/src/OpenFOAM/primitives/strings/regex/regExpCxxI.H
+++ b/src/OpenFOAM/primitives/strings/regex/regExpCxxI.H
@@ -157,7 +157,8 @@ inline void Foam::regExpCxx::swap(regExpCxx& rgx)
 }
 
 
-inline std::string::size_type Foam::regExpCxx::find(const std::string& text) const
+inline std::string::size_type
+Foam::regExpCxx::find(const std::string& text) const
 {
     std::smatch mat;
     if (!text.empty() && std::regex_search(text, mat, re_))
diff --git a/src/Pstream/mpi/UPstream.C b/src/Pstream/mpi/UPstream.C
index 1ca6e5903ab1b387d661207731b3b4a8b901ab20..d291608731a549934bc83df513fc9d7440246c87 100644
--- a/src/Pstream/mpi/UPstream.C
+++ b/src/Pstream/mpi/UPstream.C
@@ -39,7 +39,7 @@ License
 #include <cstdlib>
 #include <csignal>
 
-#if defined(WM_SP)
+#if defined(WM_SP) || defined(WM_SPDP)
     #define MPI_SCALAR MPI_FLOAT
 #elif defined(WM_DP)
     #define MPI_SCALAR MPI_DOUBLE
diff --git a/src/TurbulenceModels/turbulenceModels/derivedFvPatchFields/wallFunctions/nutWallFunctions/nutLowReWallFunction/nutLowReWallFunctionFvPatchScalarField.C b/src/TurbulenceModels/turbulenceModels/derivedFvPatchFields/wallFunctions/nutWallFunctions/nutLowReWallFunction/nutLowReWallFunctionFvPatchScalarField.C
index 5faec29dccc912c7ac71edf1485e4a7d0700f705..edd82b2fcea4f43ba271255687dd597fb480ad17 100644
--- a/src/TurbulenceModels/turbulenceModels/derivedFvPatchFields/wallFunctions/nutWallFunctions/nutLowReWallFunction/nutLowReWallFunctionFvPatchScalarField.C
+++ b/src/TurbulenceModels/turbulenceModels/derivedFvPatchFields/wallFunctions/nutWallFunctions/nutLowReWallFunction/nutLowReWallFunctionFvPatchScalarField.C
@@ -114,7 +114,7 @@ tmp<scalarField> nutLowReWallFunctionFvPatchScalarField::yPlus() const
     const scalarField& y = turbModel.y()[patchi];
     const tmp<scalarField> tnuw = turbModel.nu(patchi);
     const scalarField& nuw = tnuw();
-    const fvPatchVectorField& Uw = turbModel.U().boundaryField()[patchi];
+    const fvPatchVectorField& Uw = U(turbModel).boundaryField()[patchi];
 
     return y*sqrt(nuw*mag(Uw.snGrad()))/nuw;
 }
diff --git a/src/TurbulenceModels/turbulenceModels/derivedFvPatchFields/wallFunctions/nutWallFunctions/nutUBlendedWallFunction/nutUBlendedWallFunctionFvPatchScalarField.C b/src/TurbulenceModels/turbulenceModels/derivedFvPatchFields/wallFunctions/nutWallFunctions/nutUBlendedWallFunction/nutUBlendedWallFunctionFvPatchScalarField.C
index 9bbb5ae89835a382c04cb6bc923942e9a8e120a3..1a362ab51a286249e619b3cbc60c74585efafc75 100644
--- a/src/TurbulenceModels/turbulenceModels/derivedFvPatchFields/wallFunctions/nutWallFunctions/nutUBlendedWallFunction/nutUBlendedWallFunctionFvPatchScalarField.C
+++ b/src/TurbulenceModels/turbulenceModels/derivedFvPatchFields/wallFunctions/nutWallFunctions/nutUBlendedWallFunction/nutUBlendedWallFunctionFvPatchScalarField.C
@@ -44,7 +44,7 @@ Foam::nutUBlendedWallFunctionFvPatchScalarField::calcNut() const
             internalField().group()
         )
     );
-    const fvPatchVectorField& Uw = turbModel.U().boundaryField()[patchi];
+    const fvPatchVectorField& Uw = U(turbModel).boundaryField()[patchi];
     const scalarField magGradU(mag(Uw.snGrad()));
     const tmp<scalarField> tnuw = turbModel.nu(patchi);
     const scalarField& nuw = tnuw();
@@ -80,7 +80,7 @@ Foam::nutUBlendedWallFunctionFvPatchScalarField::calcUTau
     const scalarField& nuw = tnuw();
 
     const vectorField n(patch().nf());
-    const fvPatchVectorField& Uw = turbModel.U().boundaryField()[patchi];
+    const fvPatchVectorField& Uw = U(turbModel).boundaryField()[patchi];
     vectorField Up(Uw.patchInternalField() - Uw);
     Up -= n*(n & Up);
     const scalarField magUp(mag(Up));
@@ -197,7 +197,7 @@ Foam::nutUBlendedWallFunctionFvPatchScalarField::yPlus() const
     const scalarField& y = turbModel.y()[patchi];
     const tmp<scalarField> tnuw = turbModel.nu(patchi);
     const scalarField& nuw = tnuw();
-    const fvPatchVectorField& Uw = turbModel.U().boundaryField()[patchi];
+    const fvPatchVectorField& Uw = U(turbModel).boundaryField()[patchi];
     const scalarField magGradU(mag(Uw.snGrad()));
 
     return y*calcUTau(magGradU)/nuw;
diff --git a/src/TurbulenceModels/turbulenceModels/derivedFvPatchFields/wallFunctions/nutWallFunctions/nutURoughWallFunction/nutURoughWallFunctionFvPatchScalarField.C b/src/TurbulenceModels/turbulenceModels/derivedFvPatchFields/wallFunctions/nutWallFunctions/nutURoughWallFunction/nutURoughWallFunctionFvPatchScalarField.C
index c0db4a5a5d725c089a2b38b76dc096b2bb83f4d9..2e3d5dcad7d0d5fbcfb8cbbd048361d7260a053e 100644
--- a/src/TurbulenceModels/turbulenceModels/derivedFvPatchFields/wallFunctions/nutWallFunctions/nutURoughWallFunction/nutURoughWallFunctionFvPatchScalarField.C
+++ b/src/TurbulenceModels/turbulenceModels/derivedFvPatchFields/wallFunctions/nutWallFunctions/nutURoughWallFunction/nutURoughWallFunctionFvPatchScalarField.C
@@ -51,7 +51,7 @@ tmp<scalarField> nutURoughWallFunctionFvPatchScalarField::calcNut() const
         )
     );
     const scalarField& y = turbModel.y()[patchi];
-    const fvPatchVectorField& Uw = turbModel.U().boundaryField()[patchi];
+    const fvPatchVectorField& Uw = U(turbModel).boundaryField()[patchi];
     const tmp<scalarField> tnuw = turbModel.nu(patchi);
     const scalarField& nuw = tnuw();
 
@@ -314,7 +314,7 @@ tmp<scalarField> nutURoughWallFunctionFvPatchScalarField::yPlus() const
             internalField().group()
         )
     );
-    const fvPatchVectorField& Uw = turbModel.U().boundaryField()[patchi];
+    const fvPatchVectorField& Uw = U(turbModel).boundaryField()[patchi];
     tmp<scalarField> magUp = mag(Uw.patchInternalField() - Uw);
 
     return calcYPlus(magUp());
diff --git a/src/TurbulenceModels/turbulenceModels/derivedFvPatchFields/wallFunctions/nutWallFunctions/nutUSpaldingWallFunction/nutUSpaldingWallFunctionFvPatchScalarField.C b/src/TurbulenceModels/turbulenceModels/derivedFvPatchFields/wallFunctions/nutWallFunctions/nutUSpaldingWallFunction/nutUSpaldingWallFunctionFvPatchScalarField.C
index bc4e59f187b76f263b91c4a6ae23d4acb7d6ed57..1e2d5d34ef30ab6a3f8adfd6cbdab357bee71d26 100644
--- a/src/TurbulenceModels/turbulenceModels/derivedFvPatchFields/wallFunctions/nutWallFunctions/nutUSpaldingWallFunction/nutUSpaldingWallFunctionFvPatchScalarField.C
+++ b/src/TurbulenceModels/turbulenceModels/derivedFvPatchFields/wallFunctions/nutWallFunctions/nutUSpaldingWallFunction/nutUSpaldingWallFunctionFvPatchScalarField.C
@@ -50,7 +50,7 @@ tmp<scalarField> nutUSpaldingWallFunctionFvPatchScalarField::calcNut() const
             internalField().group()
         )
     );
-    const fvPatchVectorField& Uw = turbModel.U().boundaryField()[patchi];
+    const fvPatchVectorField& Uw = U(turbModel).boundaryField()[patchi];
     const scalarField magGradU(mag(Uw.snGrad()));
     const tmp<scalarField> tnuw = turbModel.nu(patchi);
     const scalarField& nuw = tnuw();
@@ -120,7 +120,7 @@ tmp<scalarField> nutUSpaldingWallFunctionFvPatchScalarField::calcUTau
     );
     const scalarField& y = turbModel.y()[patchi];
 
-    const fvPatchVectorField& Uw = turbModel.U().boundaryField()[patchi];
+    const fvPatchVectorField& Uw = U(turbModel).boundaryField()[patchi];
     const scalarField magUp(mag(Uw.patchInternalField() - Uw));
 
     const tmp<scalarField> tnuw = turbModel.nu(patchi);
@@ -327,7 +327,7 @@ tmp<scalarField> nutUSpaldingWallFunctionFvPatchScalarField::yPlus() const
         )
     );
     const scalarField& y = turbModel.y()[patchi];
-    const fvPatchVectorField& Uw = turbModel.U().boundaryField()[patchi];
+    const fvPatchVectorField& Uw = U(turbModel).boundaryField()[patchi];
     const tmp<scalarField> tnuw = turbModel.nu(patchi);
     const scalarField& nuw = tnuw();
 
diff --git a/src/TurbulenceModels/turbulenceModels/derivedFvPatchFields/wallFunctions/nutWallFunctions/nutUTabulatedWallFunction/nutUTabulatedWallFunctionFvPatchScalarField.C b/src/TurbulenceModels/turbulenceModels/derivedFvPatchFields/wallFunctions/nutWallFunctions/nutUTabulatedWallFunction/nutUTabulatedWallFunctionFvPatchScalarField.C
index c99832acf517a8ecc3d3d18d5d634cd4c3da7306..90d2bc14745eaf01b0e290c06db848c478d9f494 100644
--- a/src/TurbulenceModels/turbulenceModels/derivedFvPatchFields/wallFunctions/nutWallFunctions/nutUTabulatedWallFunction/nutUTabulatedWallFunctionFvPatchScalarField.C
+++ b/src/TurbulenceModels/turbulenceModels/derivedFvPatchFields/wallFunctions/nutWallFunctions/nutUTabulatedWallFunction/nutUTabulatedWallFunctionFvPatchScalarField.C
@@ -51,7 +51,7 @@ tmp<scalarField> nutUTabulatedWallFunctionFvPatchScalarField::calcNut() const
         )
     );
     const scalarField& y = turbModel.y()[patchi];
-    const fvPatchVectorField& Uw = turbModel.U().boundaryField()[patchi];
+    const fvPatchVectorField& Uw = U(turbModel).boundaryField()[patchi];
     const scalarField magUp(mag(Uw.patchInternalField() - Uw));
     const scalarField magGradU(mag(Uw.snGrad()));
     const tmp<scalarField> tnuw = turbModel.nu(patchi);
@@ -193,7 +193,7 @@ tmp<scalarField> nutUTabulatedWallFunctionFvPatchScalarField::yPlus() const
         )
     );
     const scalarField& y = turbModel.y()[patchi];
-    const fvPatchVectorField& Uw = turbModel.U().boundaryField()[patchi];
+    const fvPatchVectorField& Uw = U(turbModel).boundaryField()[patchi];
     const scalarField magUp(mag(Uw.patchInternalField() - Uw));
     const tmp<scalarField> tnuw = turbModel.nu(patchi);
     const scalarField& nuw = tnuw();
diff --git a/src/TurbulenceModels/turbulenceModels/derivedFvPatchFields/wallFunctions/nutWallFunctions/nutUWallFunction/nutUWallFunctionFvPatchScalarField.C b/src/TurbulenceModels/turbulenceModels/derivedFvPatchFields/wallFunctions/nutWallFunctions/nutUWallFunction/nutUWallFunctionFvPatchScalarField.C
index 7924ec07d24fd14ddfb407180355d1561b2e1195..9d9cb2be8de2ec9ce90f532e45ee8b7c369d9db1 100644
--- a/src/TurbulenceModels/turbulenceModels/derivedFvPatchFields/wallFunctions/nutWallFunctions/nutUWallFunction/nutUWallFunctionFvPatchScalarField.C
+++ b/src/TurbulenceModels/turbulenceModels/derivedFvPatchFields/wallFunctions/nutWallFunctions/nutUWallFunction/nutUWallFunctionFvPatchScalarField.C
@@ -50,7 +50,7 @@ tmp<scalarField> nutUWallFunctionFvPatchScalarField::calcNut() const
             internalField().group()
         )
     );
-    const fvPatchVectorField& Uw = turbModel.U().boundaryField()[patchi];
+    const fvPatchVectorField& Uw = U(turbModel).boundaryField()[patchi];
     const scalarField magUp(mag(Uw.patchInternalField() - Uw));
     const tmp<scalarField> tnuw = turbModel.nu(patchi);
     const scalarField& nuw = tnuw();
@@ -187,7 +187,7 @@ tmp<scalarField> nutUWallFunctionFvPatchScalarField::yPlus() const
             internalField().group()
         )
     );
-    const fvPatchVectorField& Uw = turbModel.U().boundaryField()[patchi];
+    const fvPatchVectorField& Uw = U(turbModel).boundaryField()[patchi];
     const scalarField magUp(mag(Uw.patchInternalField() - Uw));
 
     return calcYPlus(magUp);
diff --git a/src/TurbulenceModels/turbulenceModels/derivedFvPatchFields/wallFunctions/nutWallFunctions/nutWallFunction/nutWallFunctionFvPatchScalarField.C b/src/TurbulenceModels/turbulenceModels/derivedFvPatchFields/wallFunctions/nutWallFunctions/nutWallFunction/nutWallFunctionFvPatchScalarField.C
index c01497432e30cd990a67626ed624ebb6d3771bdd..b2bc4d7a055c6efcb6f25f6e070f6e9eb9095599 100644
--- a/src/TurbulenceModels/turbulenceModels/derivedFvPatchFields/wallFunctions/nutWallFunctions/nutWallFunction/nutWallFunctionFvPatchScalarField.C
+++ b/src/TurbulenceModels/turbulenceModels/derivedFvPatchFields/wallFunctions/nutWallFunctions/nutWallFunction/nutWallFunctionFvPatchScalarField.C
@@ -29,6 +29,7 @@ License
 #include "fvPatchFieldMapper.H"
 #include "volFields.H"
 #include "wallFvPatch.H"
+#include "turbulenceModel.H"
 #include "addToRunTimeSelectionTable.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@@ -54,11 +55,32 @@ void Foam::nutWallFunctionFvPatchScalarField::checkType()
 }
 
 
+const Foam::volVectorField& Foam::nutWallFunctionFvPatchScalarField::U
+(
+    const turbulenceModel& turb
+) const
+{
+    if (UName_ == word::null)
+    {
+        return turb.U();
+    }
+    else
+    {
+        return db().lookupObject<volVectorField>(UName_);
+    }
+}
+
+
 void Foam::nutWallFunctionFvPatchScalarField::writeLocalEntries
 (
     Ostream& os
 ) const
 {
+    if (UName_ != word::null)
+    {
+        os.writeEntry("U", UName_);
+    }
+
     os.writeEntry("Cmu", Cmu_);
     os.writeEntry("kappa", kappa_);
     os.writeEntry("E", E_);
@@ -74,6 +96,7 @@ Foam::nutWallFunctionFvPatchScalarField::nutWallFunctionFvPatchScalarField
 )
 :
     fixedValueFvPatchScalarField(p, iF),
+    UName_(word::null),
     Cmu_(0.09),
     kappa_(0.41),
     E_(9.8),
@@ -92,6 +115,7 @@ Foam::nutWallFunctionFvPatchScalarField::nutWallFunctionFvPatchScalarField
 )
 :
     fixedValueFvPatchScalarField(ptf, p, iF, mapper),
+    UName_(ptf.UName_),
     Cmu_(ptf.Cmu_),
     kappa_(ptf.kappa_),
     E_(ptf.E_),
@@ -109,6 +133,7 @@ Foam::nutWallFunctionFvPatchScalarField::nutWallFunctionFvPatchScalarField
 )
 :
     fixedValueFvPatchScalarField(p, iF, dict),
+    UName_(dict.lookupOrDefault<word>("U", word::null)),
     Cmu_(dict.lookupOrDefault<scalar>("Cmu", 0.09)),
     kappa_(dict.lookupOrDefault<scalar>("kappa", 0.41)),
     E_(dict.lookupOrDefault<scalar>("E", 9.8)),
@@ -124,6 +149,7 @@ Foam::nutWallFunctionFvPatchScalarField::nutWallFunctionFvPatchScalarField
 )
 :
     fixedValueFvPatchScalarField(wfpsf),
+    UName_(wfpsf.UName_),
     Cmu_(wfpsf.Cmu_),
     kappa_(wfpsf.kappa_),
     E_(wfpsf.E_),
@@ -140,6 +166,7 @@ Foam::nutWallFunctionFvPatchScalarField::nutWallFunctionFvPatchScalarField
 )
 :
     fixedValueFvPatchScalarField(wfpsf, iF),
+    UName_(wfpsf.UName_),
     Cmu_(wfpsf.Cmu_),
     kappa_(wfpsf.kappa_),
     E_(wfpsf.E_),
diff --git a/src/TurbulenceModels/turbulenceModels/derivedFvPatchFields/wallFunctions/nutWallFunctions/nutWallFunction/nutWallFunctionFvPatchScalarField.H b/src/TurbulenceModels/turbulenceModels/derivedFvPatchFields/wallFunctions/nutWallFunctions/nutWallFunction/nutWallFunctionFvPatchScalarField.H
index baa161e77633e4e6bd74291404d310a14d98890a..ee590b87d1f926958aec24ff404381b30f61bc18 100644
--- a/src/TurbulenceModels/turbulenceModels/derivedFvPatchFields/wallFunctions/nutWallFunctions/nutWallFunction/nutWallFunctionFvPatchScalarField.H
+++ b/src/TurbulenceModels/turbulenceModels/derivedFvPatchFields/wallFunctions/nutWallFunctions/nutWallFunction/nutWallFunctionFvPatchScalarField.H
@@ -76,6 +76,8 @@ SourceFiles
 namespace Foam
 {
 
+class turbulenceModel;
+
 /*---------------------------------------------------------------------------*\
              Class nutWallFunctionFvPatchScalarField Declaration
 \*---------------------------------------------------------------------------*/
@@ -88,6 +90,11 @@ protected:
 
     // Protected data
 
+        //- Name of velocity field
+        //  Defult is null (not specified) in which case the velocity is
+        //  retrieved from the turbulence model
+        word UName_;
+
         //- Cmu coefficient
         scalar Cmu_;
 
@@ -103,6 +110,10 @@ protected:
 
     // Protected Member Functions
 
+        //- Helper to return the velocity field either from the turbulence
+        //- model (default) or the mesh database
+        virtual const volVectorField& U(const turbulenceModel& turb) const;
+
         //- Check the type of the patch
         virtual void checkType();
 
diff --git a/src/dummyThirdParty/metisDecomp/metis.h b/src/dummyThirdParty/metisDecomp/metis.h
index b594fc09b1d322c48448d78c4d93eb1feeb1b711..fe0c086e14ace1b75db0c74639b94c17324fdd39 100644
--- a/src/dummyThirdParty/metisDecomp/metis.h
+++ b/src/dummyThirdParty/metisDecomp/metis.h
@@ -27,14 +27,14 @@
 
 
 // Float type: OpenFOAM uses WM_SP, WM_DP, metis.h uses REALTYPEWIDTH
-#if defined(WM_SP)
+#if defined(WM_SP) || defined(WM_SPDP)
   typedef float real_t;
   #define REALTYPEWIDTH 32
 #elif defined(WM_DP)
   typedef double real_t;
   #define REALTYPEWIDTH 64
 #else
-  #error "Incorrect user-supplied value for WM_SP / WM_DP  (metis REALTYPEWIDTH)"
+  #error "Incorrect user-supplied value for WM_SP (WM_SPDP) / WM_DP  (metis REALTYPEWIDTH)"
 #endif
 
 
diff --git a/src/dynamicMesh/attachDetach/attachInterface.C b/src/dynamicMesh/attachDetach/attachInterface.C
index f381731b6b87305f3199e04f78b8acb7c5e05879..be2174036a9a29e2fa81fe3d6e67a3a8922f1626 100644
--- a/src/dynamicMesh/attachDetach/attachInterface.C
+++ b/src/dynamicMesh/attachDetach/attachInterface.C
@@ -114,6 +114,9 @@ void Foam::attachDetach::attachInterface
 
     const boolList& mfFlip = mesh.faceZones()[faceZoneID_.index()].flipMap();
 
+    // Keep track of which faces have been modified
+    bitSet faceModified(mesh.nFaces());
+
     forAll(masterFaceCells, facei)
     {
         // If slave neighbour is greater than master, face does not need
@@ -155,6 +158,7 @@ void Foam::attachDetach::attachInterface
                 )
             );
         }
+        faceModified[masterPatchStart + facei] = true;
     }
 
     // Renumber faces affected by point removal
@@ -175,7 +179,11 @@ void Foam::attachDetach::attachInterface
 
         forAll(curFaces, facei)
         {
-            if (!ref.faceRemoved(curFaces[facei]))
+            if
+            (
+               !ref.faceRemoved(curFaces[facei])
+            && !faceModified[curFaces[facei]]
+            )
             {
                 facesToModifyMap.insert(curFaces[facei]);
             }
diff --git a/src/fileFormats/vtk/core/foamVtkCore.C b/src/fileFormats/vtk/core/foamVtkCore.C
index c8b41b924c2de40b8e4925ab266918286e057976..48c0e8115353f35af7758b7a79474bc7abde470d 100644
--- a/src/fileFormats/vtk/core/foamVtkCore.C
+++ b/src/fileFormats/vtk/core/foamVtkCore.C
@@ -32,12 +32,12 @@ const Foam::Enum
     Foam::vtk::fileTag
 >
 Foam::vtk::fileExtension
-{
+({
     { fileTag::POLY_DATA, "vtp" },
     { fileTag::UNSTRUCTURED_GRID, "vtu" },
     { fileTag::MULTI_BLOCK, "vtm" },
     // { fileTag::COLLECTION, "pvd" },
-};
+});
 
 
 const Foam::Enum
@@ -45,12 +45,12 @@ const Foam::Enum
     Foam::vtk::fileTag
 >
 Foam::vtk::fileContentVersions
-{
+({
     { fileTag::POLY_DATA, "0.1" },
     { fileTag::UNSTRUCTURED_GRID, "0.1" },
     { fileTag::MULTI_BLOCK, "1.0" },
     // { fileTag::COLLECTION, "0.1" },
-};
+});
 
 
 const Foam::Enum
diff --git a/src/fileFormats/vtk/file/foamVtkFileWriter.C b/src/fileFormats/vtk/file/foamVtkFileWriter.C
index 524446cffed396256feb9b8de0c3ff366d45ecef..82dc600ecbcab6533c3f81e1479e1088589d4b16 100644
--- a/src/fileFormats/vtk/file/foamVtkFileWriter.C
+++ b/src/fileFormats/vtk/file/foamVtkFileWriter.C
@@ -33,7 +33,7 @@ const Foam::Enum
     Foam::vtk::fileWriter::outputState
 >
 Foam::vtk::fileWriter::stateNames
-{
+({
     { outputState::CLOSED, "closed" },
     { outputState::OPENED, "opened" },
     { outputState::DECLARED, "declared" },
@@ -41,7 +41,7 @@ Foam::vtk::fileWriter::stateNames
     { outputState::PIECE, "Piece" },
     { outputState::CELL_DATA, "CellData" },
     { outputState::POINT_DATA, "PointData" },
-};
+});
 
 
 // * * * * * * * * * * * * Protected Member Functions  * * * * * * * * * * * //
diff --git a/src/finiteArea/fields/faPatchFields/faPatchField/faPatchField.C b/src/finiteArea/fields/faPatchFields/faPatchField/faPatchField.C
index 436845ca36777ae5d315887d7c3bf7583a6474d3..e3aec27f3b199a7497113d19dfe429cb3cd507b0 100644
--- a/src/finiteArea/fields/faPatchFields/faPatchField/faPatchField.C
+++ b/src/finiteArea/fields/faPatchFields/faPatchField/faPatchField.C
@@ -40,7 +40,8 @@ Foam::faPatchField<Type>::faPatchField
     Field<Type>(p.size()),
     patch_(p),
     internalField_(iF),
-    updated_(false)
+    updated_(false),
+    patchType_(word::null)
 {}
 
 
@@ -55,7 +56,8 @@ Foam::faPatchField<Type>::faPatchField
     Field<Type>(f),
     patch_(p),
     internalField_(iF),
-    updated_(false)
+    updated_(false),
+    patchType_(word::null)
 {}
 
 
@@ -71,7 +73,8 @@ Foam::faPatchField<Type>::faPatchField
     Field<Type>(ptf, mapper),
     patch_(p),
     internalField_(iF),
-    updated_(false)
+    updated_(false),
+    patchType_(word::null)
 {}
 
 
@@ -86,7 +89,8 @@ Foam::faPatchField<Type>::faPatchField
     Field<Type>(p.size()),
     patch_(p),
     internalField_(iF),
-    updated_(false)
+    updated_(false),
+    patchType_(dict.lookupOrDefault<word>("patchType", word::null))
 {
     if (dict.found("value"))
     {
@@ -111,7 +115,8 @@ Foam::faPatchField<Type>::faPatchField
     Field<Type>(ptf),
     patch_(ptf.patch_),
     internalField_(ptf.internalField_),
-    updated_(false)
+    updated_(false),
+    patchType_(ptf.patchType_)
 {}
 
 
@@ -125,7 +130,8 @@ Foam::faPatchField<Type>::faPatchField
     Field<Type>(ptf),
     patch_(ptf.patch_),
     internalField_(iF),
-    updated_(false)
+    updated_(false),
+    patchType_(ptf.patchType_)
 {}
 
 
@@ -200,6 +206,11 @@ template<class Type>
 void Foam::faPatchField<Type>::write(Ostream& os) const
 {
     os.writeEntry("type", type());
+
+    if (patchType_.size())
+    {
+        os.writeEntry("patchType", patchType_);
+    }
 }
 
 
diff --git a/src/finiteArea/fields/faPatchFields/faPatchField/faPatchField.H b/src/finiteArea/fields/faPatchFields/faPatchField/faPatchField.H
index 62ff60dc471049e380ff44cbd8be361d4f51c607..eca163cdc40038d1678313a2d5902b0223f11992 100644
--- a/src/finiteArea/fields/faPatchFields/faPatchField/faPatchField.H
+++ b/src/finiteArea/fields/faPatchFields/faPatchField/faPatchField.H
@@ -94,6 +94,11 @@ class faPatchField
         //  the construction of the matrix
         bool updated_;
 
+        //- Optional patch type, used to allow specified boundary conditions
+        //  to be applied to constraint patches by providing the constraint
+        //  patch type as 'patchType'
+        word patchType_;
+
 
 public:
 
@@ -217,7 +222,18 @@ public:
         //  (does not set the patch field values)
         static tmp<faPatchField<Type>> New
         (
-            const word&,
+            const word& patchFieldType,
+            const word& actualPatchType,
+            const faPatch&,
+            const DimensionedField<Type, areaMesh>&
+        );
+
+        //- Return a pointer to a new patchField created on freestore given
+        //  patch and internal field
+        //  (does not set the patch field values)
+        static tmp<faPatchField<Type>> New
+        (
+            const word& patchFieldType,
             const faPatch&,
             const DimensionedField<Type, areaMesh>&
         );
@@ -280,6 +296,18 @@ public:
                 return internalField_;
             }
 
+            //- Optional patch type
+            const word& patchType() const
+            {
+                return patchType_;
+            }
+
+            //- Optional patch type
+            word& patchType()
+            {
+                return patchType_;
+            }
+
             //- Return the type of the calculated for of faPatchField
             static const word& calculatedType();
 
diff --git a/src/finiteArea/fields/faPatchFields/faPatchField/faPatchFieldNew.C b/src/finiteArea/fields/faPatchFields/faPatchField/faPatchFieldNew.C
index 5189bb807370a4978303251de369d53148de1105..7c73e7d2355bf4cba0c81fe2d9cf3ef314b0502d 100644
--- a/src/finiteArea/fields/faPatchFields/faPatchField/faPatchFieldNew.C
+++ b/src/finiteArea/fields/faPatchFields/faPatchField/faPatchFieldNew.C
@@ -31,6 +31,7 @@ template<class Type>
 Foam::tmp<Foam::faPatchField<Type>> Foam::faPatchField<Type>::New
 (
     const word& patchFieldType,
+    const word& actualPatchType,
     const faPatch& p,
     const DimensionedField<Type, areaMesh>& iF
 )
@@ -52,17 +53,47 @@ Foam::tmp<Foam::faPatchField<Type>> Foam::faPatchField<Type>::New
 
     auto patchTypeCstrIter = patchConstructorTablePtr_->cfind(p.type());
 
-    if (patchTypeCstrIter.found())
+    if
+    (
+        actualPatchType == word::null
+     || actualPatchType != p.type()
+    )
     {
-        return patchTypeCstrIter()(p, iF);
+        if (patchTypeCstrIter.found())
+        {
+            return patchTypeCstrIter()(p, iF);
+        }
+        else
+        {
+            return cstrIter()(p, iF);
+        }
     }
     else
     {
-        return cstrIter()(p, iF);
+        tmp<faPatchField<Type>> tfap = cstrIter()(p, iF);
+
+        // Check if constraint type override and store patchType if so
+        if (patchTypeCstrIter.found())
+        {
+            tfap.ref().patchType() = actualPatchType;
+        }
+        return tfap;
     }
 }
 
 
+template<class Type>
+Foam::tmp<Foam::faPatchField<Type>> Foam::faPatchField<Type>::New
+(
+    const word& patchFieldType,
+    const faPatch& p,
+    const DimensionedField<Type, areaMesh>& iF
+)
+{
+    return New(patchFieldType, word::null, p, iF);
+}
+
+
 template<class Type>
 Foam::tmp<Foam::faPatchField<Type>> Foam::faPatchField<Type>::New
 (
diff --git a/src/functionObjects/Allwmake b/src/functionObjects/Allwmake
index fa4da4d414e623807096d0a3512b392ca84059cf..4ef262db1160c52d4dbdbb788d1b1296a33844cd 100755
--- a/src/functionObjects/Allwmake
+++ b/src/functionObjects/Allwmake
@@ -6,6 +6,7 @@ cd ${0%/*} || exit 1                        # Run from this directory
 
 wmake $targetType field
 wmake $targetType forces
+wmake $targetType initialisation
 wmake $targetType lagrangian
 wmake $targetType utilities
 wmake $targetType solvers
diff --git a/src/functionObjects/doc/functionObjects.dox b/src/functionObjects/doc/functionObjects.dox
index db8eadd56e901a2638a3e8b93d832758d5972d17..cbe93387ddde2a08b8aa7ae7d93674b2329387ac 100644
--- a/src/functionObjects/doc/functionObjects.dox
+++ b/src/functionObjects/doc/functionObjects.dox
@@ -41,6 +41,7 @@ The current range of features comprises of:
 - \ref grpFieldFunctionObjects
 - \ref grpForcesFunctionObjects
 - \ref grpGraphicsFunctionObjects
+- \ref grpInitialisationFunctionObjects
 - \ref grpLagrangianFunctionObjects
 - \ref grpSolversFunctionObjects
 - \ref grpUtilitiesFunctionObjects
diff --git a/src/functionObjects/field/Make/files b/src/functionObjects/field/Make/files
index 9e1d2eec8704dac016ae73b1039771222f8687ae..ac70390ecdc17a504d61dd6fcc54692158f001cf 100644
--- a/src/functionObjects/field/Make/files
+++ b/src/functionObjects/field/Make/files
@@ -60,6 +60,7 @@ ddt/ddt.C
 mag/mag.C
 magSqr/magSqr.C
 vorticity/vorticity.C
+lambVector/lambVector.C
 enstrophy/enstrophy.C
 Q/Q.C
 Lambda2/Lambda2.C
diff --git a/src/functionObjects/field/ddt2/ddt2.C b/src/functionObjects/field/ddt2/ddt2.C
index 9fe5cb4728106b8ab13862149aa345c817bafa65..83998083541585fbcacf42a189368203c85d338d 100644
--- a/src/functionObjects/field/ddt2/ddt2.C
+++ b/src/functionObjects/field/ddt2/ddt2.C
@@ -50,13 +50,15 @@ namespace functionObjects
 
 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
 
-bool Foam::functionObjects::ddt2::checkFormatName(const word& str)
+bool Foam::functionObjects::ddt2::checkFormatName
+(
+    const std::string& str
+)
 {
-    if (str.find("@@") == string::npos)
+    if (std::string::npos == str.find("@@"))
     {
         WarningInFunction
-            << "Bad result naming "
-            << "(no '@@' token found), deactivating."
+            << "Bad result naming (no '@@' token found)."
             << nl << endl;
 
         return false;
@@ -64,10 +66,8 @@ bool Foam::functionObjects::ddt2::checkFormatName(const word& str)
     else if (str == "@@")
     {
         WarningInFunction
-            << "Bad result naming "
-            << "(only a '@@' token found), deactivating."
-            << nl
-            << endl;
+            << "Bad result naming (only a '@@' token found)."
+            << nl << endl;
 
         return false;
     }
@@ -145,7 +145,12 @@ bool Foam::functionObjects::ddt2::read(const dictionary& dict)
         ( mag_ ? "mag(ddt(@@))" : "magSqr(ddt(@@))" )
     );
 
-    if (checkFormatName(resultName_))
+    // Expect '@@' token for result, unless a single (non-regex) source field
+    if
+    (
+        (selectFields_.size() == 1 && selectFields_.first().isLiteral())
+     || checkFormatName(resultName_)
+    )
     {
         blacklist_.set
         (
diff --git a/src/functionObjects/field/ddt2/ddt2.H b/src/functionObjects/field/ddt2/ddt2.H
index cf50a8c1f2d3ed3b6a84e9ef75685c31f9308186..31f54e89a51467da862cda373eee0dda408b695c 100644
--- a/src/functionObjects/field/ddt2/ddt2.H
+++ b/src/functionObjects/field/ddt2/ddt2.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  |
 -------------------------------------------------------------------------------
 License
@@ -62,7 +62,8 @@ Usage
 
     A list of fields can contain exact names or regular expressions.
     The token '\@\@' in the result name is replaced by the name of the source
-    field.
+    field. In the special case of a single source field (specified as
+    a non-regex), the '\@\@' token checking is suppressed.
 
     The function object will skip over fields that appear to have
     already been processed (ie, their names are similar to the output names).
@@ -100,7 +101,7 @@ class ddt2
 {
     // Private data
 
-        //- Name of fields to process
+        //- Name of fields to process.
         wordRes selectFields_;
 
         //- Formatting for the result fields.
@@ -120,8 +121,8 @@ class ddt2
 
     // Private Member Functions
 
-        //- Check that the word contains the appropriate substitution token(s).
-        static bool checkFormatName(const word& str);
+        //- Check that string contains the appropriate substitution token(s).
+        static bool checkFormatName(const std::string& str);
 
 
         //- Accept unless field name appears to have already been processed
diff --git a/src/functionObjects/field/fieldValues/surfaceFieldValue/surfaceFieldValue.C b/src/functionObjects/field/fieldValues/surfaceFieldValue/surfaceFieldValue.C
index ef06076e30ffcf33d70d1dc61930b745434fc6ec..f64c2a8c206402fa838563892777b5f500e9904f 100644
--- a/src/functionObjects/field/fieldValues/surfaceFieldValue/surfaceFieldValue.C
+++ b/src/functionObjects/field/fieldValues/surfaceFieldValue/surfaceFieldValue.C
@@ -1091,4 +1091,22 @@ bool Foam::functionObjects::fieldValues::surfaceFieldValue::write()
 }
 
 
+void Foam::functionObjects::fieldValues::surfaceFieldValue::updateMesh
+(
+    const mapPolyMesh& mpm
+)
+{
+    needsUpdate_ = true;
+}
+
+
+void Foam::functionObjects::fieldValues::surfaceFieldValue::movePoints
+(
+    const polyMesh& mesh
+)
+{
+    needsUpdate_ = true;
+}
+
+
 // ************************************************************************* //
diff --git a/src/functionObjects/field/fieldValues/surfaceFieldValue/surfaceFieldValue.H b/src/functionObjects/field/fieldValues/surfaceFieldValue/surfaceFieldValue.H
index 2e29dbef9bbb29527a0606a4826e91050920ada7..ff5bfce8e732cb715811f8fe015b25dde06d24f4 100644
--- a/src/functionObjects/field/fieldValues/surfaceFieldValue/surfaceFieldValue.H
+++ b/src/functionObjects/field/fieldValues/surfaceFieldValue/surfaceFieldValue.H
@@ -556,6 +556,12 @@ public:
 
         //- Calculate and write
         virtual bool write();
+
+        //- Update for changes of mesh
+        virtual void updateMesh(const mapPolyMesh& mpm);
+
+        //- Update for changes of mesh
+        virtual void movePoints(const polyMesh& mesh);
 };
 
 
diff --git a/src/functionObjects/field/fluxSummary/fluxSummary.H b/src/functionObjects/field/fluxSummary/fluxSummary.H
index f1e7f81deb7bc9fc9c9ef2a9232acd8303eb468e..17788597311f7b110d5c31e99974eb379f5682ee 100644
--- a/src/functionObjects/field/fluxSummary/fluxSummary.H
+++ b/src/functionObjects/field/fluxSummary/fluxSummary.H
@@ -64,6 +64,8 @@ Usage
         log         | Write flux data to standard output    | no  | yes
         mode        | Mode to generate faces to test        | yes |
         scaleFactor | Optional factor to scale result       | no  | 1
+        tolerance   | Tolerance for the reference direction | no  | 0.8
+        phi         | Surface flux field                    | no  | phi
     \endtable
 
     The mode is one of:
@@ -75,6 +77,9 @@ Usage
 
     Output data is written to files of the form \<timeDir\>/\<faceZoneName\>.dat
 
+Note
+    For surface and direction, can use phi = 'U' for determining the fluxes.
+
 See also
     Foam::functionObjects::fvMeshFunctionObject
     Foam::functionObjects::writeFile
diff --git a/src/functionObjects/field/lambVector/lambVector.C b/src/functionObjects/field/lambVector/lambVector.C
new file mode 100644
index 0000000000000000000000000000000000000000..d7e0513bc9753c859a36d01711bcbd1085e75f8c
--- /dev/null
+++ b/src/functionObjects/field/lambVector/lambVector.C
@@ -0,0 +1,70 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2019 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 <http://www.gnu.org/licenses/>.
+
+\*---------------------------------------------------------------------------*/
+
+#include "lambVector.H"
+#include "fvcCurl.H"
+#include "fvcDiv.H"
+#include "addToRunTimeSelectionTable.H"
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+namespace Foam
+{
+namespace functionObjects
+{
+    defineTypeNameAndDebug(lambVector, 0);
+    addToRunTimeSelectionTable(functionObject, lambVector, dictionary);
+}
+}
+
+// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
+
+bool Foam::functionObjects::lambVector::calc()
+{
+    if (foundObject<volVectorField>(fieldName_))
+    {
+        const volVectorField& U = lookupObject<volVectorField>(fieldName_);
+        return store(resultName_, fvc::curl(U)^U);
+    }
+
+    return false;
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::functionObjects::lambVector::lambVector
+(
+    const word& name,
+    const Time& runTime,
+    const dictionary& dict
+)
+:
+    fieldExpression(name, runTime, dict, "U")
+{
+    setResultName(typeName, fieldName_);
+}
+
+// ************************************************************************* //
diff --git a/src/functionObjects/field/lambVector/lambVector.H b/src/functionObjects/field/lambVector/lambVector.H
new file mode 100644
index 0000000000000000000000000000000000000000..73c51e49671d61b8b9706796c8423aa06346a161
--- /dev/null
+++ b/src/functionObjects/field/lambVector/lambVector.H
@@ -0,0 +1,121 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2019 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 <http://www.gnu.org/licenses/>.
+
+Class
+    Foam::functionObjects::lambVector
+
+Group
+    grpFieldFunctionObjects
+
+Description
+    Calculates Lamb vector, i.e. the cross product of vorticity and velocity.
+    Calculation of the divergence of the Lamb vector can be performed by using
+    'div' functionObject on this 'lambVector' functionObject.
+
+    The field is stored on the mesh database so that it can be retrieved
+    and used for other applications.
+
+Usage
+    \verbatim
+    lambVector1
+    {
+        type        lambVector;
+        libs        ("libfieldFunctionObjects.so");
+        field       UMean;
+        ... Base options of fieldExpression ...
+    }
+    \endverbatim
+
+    Where the entries comprise:
+    \table
+        Property     | Description             | Required    | Default value
+        type         | Type name: lambVector   | yes         |
+        field        | Name of volVectorField  | no          | U
+    \endtable
+
+See also
+    Foam::functionObjects::fieldExpression
+
+SourceFiles
+    lambVector.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef functionObjects_lambVector_H
+#define functionObjects_lambVector_H
+
+#include "fieldExpression.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+namespace functionObjects
+{
+
+/*---------------------------------------------------------------------------*\
+                          Class lambVector Declaration
+\*---------------------------------------------------------------------------*/
+
+class lambVector
+:
+    public fieldExpression
+{
+    // Private Member Functions
+
+        //- Calculate the lambVector field and return true if successful
+        virtual bool calc();
+
+
+public:
+
+    //- Runtime type information
+    TypeName("lambVector");
+
+
+    // Constructors
+
+        //- Construct from Time and dictionary
+        lambVector
+        (
+            const word& name,
+            const Time& runTime,
+            const dictionary& dict
+        );
+
+
+    //- Destructor
+    virtual ~lambVector() = default;
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace functionObjects
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/functionObjects/field/zeroGradient/zeroGradient.C b/src/functionObjects/field/zeroGradient/zeroGradient.C
index e1e79010c8e319e2690fd6f67c34c8575a5f86eb..3383c8f83c3ae3e5cb098aa53b9484c04be3f805 100644
--- a/src/functionObjects/field/zeroGradient/zeroGradient.C
+++ b/src/functionObjects/field/zeroGradient/zeroGradient.C
@@ -49,13 +49,15 @@ namespace functionObjects
 
 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
 
-bool Foam::functionObjects::zeroGradient::checkFormatName(const word& str)
+bool Foam::functionObjects::zeroGradient::checkFormatName
+(
+    const std::string& str
+)
 {
-    if (str.find("@@") == string::npos)
+    if (std::string::npos == str.find("@@"))
     {
         WarningInFunction
-            << "Bad result naming "
-            << "(no '@@' token found), deactivating."
+            << "Bad result naming (no '@@' token found)."
             << nl << endl;
 
         return false;
@@ -63,10 +65,8 @@ bool Foam::functionObjects::zeroGradient::checkFormatName(const word& str)
     else if (str == "@@")
     {
         WarningInFunction
-            << "Bad result naming "
-            << "(only a '@@' token found), deactivating."
-            << nl
-            << endl;
+            << "Bad result naming (only a '@@' token found)."
+            << nl << endl;
 
         return false;
     }
@@ -118,7 +118,13 @@ bool Foam::functionObjects::zeroGradient::read(const dictionary& dict)
     Info<< type() << " fields: " << selectFields_ << nl;
 
     resultName_ = dict.lookupOrDefault<word>("result", type() + "(@@)");
-    return checkFormatName(resultName_);
+
+    // Require '@@' token for result, unless a single (non-regex) source field
+    return
+    (
+        (selectFields_.size() == 1 && selectFields_.first().isLiteral())
+     || checkFormatName(resultName_)
+    );
 }
 
 
diff --git a/src/functionObjects/field/zeroGradient/zeroGradient.H b/src/functionObjects/field/zeroGradient/zeroGradient.H
index 04f610648c80cd6cc51b24de9109a30d0a546b58..da57e674ac52234fea6ce7a1ba0a5f9eadbe44dd 100644
--- a/src/functionObjects/field/zeroGradient/zeroGradient.H
+++ b/src/functionObjects/field/zeroGradient/zeroGradient.H
@@ -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  |
 -------------------------------------------------------------------------------
 License
@@ -58,7 +58,8 @@ Usage
 
     A list of fields can contain exact names or regular expressions.
     The token '\@\@' in the result name is replaced by the name of the source
-    field.
+    field. In the special case of a single source field (specified as
+    a non-regex), the '\@\@' token checking is suppressed.
 
     The function object will skip over fields that would not benefit
     - ie, only processor, empty, zeroGradient, symmetry patches.
@@ -95,20 +96,20 @@ class zeroGradient
 {
     // Private data
 
-        //- Name of fields to process
+        //- Name of fields to process.
         wordRes selectFields_;
 
         //- Formatting for the result fields.
         word resultName_;
 
-        //- Hashed names of result fields, and their type
+        //- Hashed names of result fields, and their type.
         HashTable<word> results_;
 
 
     // Private Member Functions
 
-        //- Check that the word contains the appropriate substitution token(s).
-        static bool checkFormatName(const word& str);
+        //- Check that string contains the appropriate substitution token(s).
+        static bool checkFormatName(const std::string& str);
 
 
         //- Accept unless field only has constraint patches
diff --git a/src/functionObjects/graphics/runTimePostProcessing/contourFilter.C b/src/functionObjects/graphics/runTimePostProcessing/contourFilter.C
index 2a6eb421a343e6fdd57bbe8b73a825927cfdb311..bab9048d680370e7475c5f6686711a52e54b670d 100644
--- a/src/functionObjects/graphics/runTimePostProcessing/contourFilter.C
+++ b/src/functionObjects/graphics/runTimePostProcessing/contourFilter.C
@@ -183,6 +183,12 @@ addGeometry
     colourFieldInfo.reduce();
 
 
+    DebugInfo
+        << "    Field " << fieldName_ << ' ' << fieldInfo.info() << nl
+        << "    Field " << colourFieldName_ << ' ' << colourFieldInfo.info()
+        << endl;
+
+
     // Not rendered on this processor?
     // This is where we stop, but could also have an MPI barrier
     if (!renderer)
diff --git a/src/functionObjects/graphics/runTimePostProcessing/fieldVisualisationBase.C b/src/functionObjects/graphics/runTimePostProcessing/fieldVisualisationBase.C
index a8ee5dd4551f1675bcdd38ad68bc2e588bac1ae6..a23c5e38ac9bff3d687618f7f4f7616d70619331 100644
--- a/src/functionObjects/graphics/runTimePostProcessing/fieldVisualisationBase.C
+++ b/src/functionObjects/graphics/runTimePostProcessing/fieldVisualisationBase.C
@@ -515,6 +515,7 @@ setField
             auto lut = vtkSmartPointer<vtkLookupTable>::New();
             setColourMap(lut);
             lut->SetVectorMode(vtkScalarsToColors::MAGNITUDE);
+            lut->SetTableRange(range_.first(), range_.second());
 
             // Configure the mapper
             const char* fieldName = colourFieldName.c_str();
@@ -741,7 +742,7 @@ fieldVisualisationBase
 :
     colours_(colours),
     fieldName_(dict.get<word>("field")),
-    smooth_(dict.lookupOrDefault("smooth", false)),
+    smooth_(dict.getOrDefault("smooth", false)),
     colourBy_(cbColour),
     colourMap_(cmRainbow),
     range_(),
diff --git a/src/functionObjects/graphics/runTimePostProcessing/functionObjectBase.C b/src/functionObjects/graphics/runTimePostProcessing/functionObjectBase.C
index c44fecc56fee28aa6148cdfe6b40bd42a13fad6a..84b3465b9ebee53960da0624f40d0ed1d590963d 100644
--- a/src/functionObjects/graphics/runTimePostProcessing/functionObjectBase.C
+++ b/src/functionObjects/graphics/runTimePostProcessing/functionObjectBase.C
@@ -76,8 +76,8 @@ Foam::functionObjects::runTimePostPro::functionObjectBase::functionObjectBase
     fieldVisualisationBase(dict, colours),
     state_(state),
     functionObjectName_(dict.get<word>("functionObject")),
-    liveObject_(dict.lookupOrDefault("liveObject", true)),
-    clearObjects_(dict.lookupOrDefault("clearObjects", false))
+    liveObject_(dict.getOrDefault("liveObject", true)),
+    clearObjects_(dict.getOrDefault("clearObjects", false))
 {}
 
 
diff --git a/src/functionObjects/graphics/runTimePostProcessing/functionObjectCloud.C b/src/functionObjects/graphics/runTimePostProcessing/functionObjectCloud.C
index 54e71f0444cff104e7945e1f76f54075532e8ca0..e7dbab1e81f3ebc1f3ab3a9c643800e5cf5ff461 100644
--- a/src/functionObjects/graphics/runTimePostProcessing/functionObjectCloud.C
+++ b/src/functionObjects/graphics/runTimePostProcessing/functionObjectCloud.C
@@ -153,8 +153,7 @@ addGeometryFromFile
             else
             {
                 DebugInfo
-                    << "    Resolved cloud file "
-                    << inputFileName_ << endl;
+                    << "    Resolved cloud file " << inputFileName_ << endl;
             }
         }
         else
@@ -198,6 +197,12 @@ addGeometryFromFile
         fieldSummary colourFieldInfo =
             queryFieldSummary(colourFieldName_, polyData);
 
+        DebugInfo
+            << "    Field " << fieldName_ << ' ' << scaleFieldInfo.info() << nl
+            << "    Field " << colourFieldName_ << ' ' << colourFieldInfo.info()
+            << endl;
+
+
         // No reduction
 
         auto mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
diff --git a/src/functionObjects/graphics/runTimePostProcessing/functionObjectSurface.C b/src/functionObjects/graphics/runTimePostProcessing/functionObjectSurface.C
index 801305f8c788f8e7fd86cbe55a8e70173ddfea3b..bc67c6273a23939de12b6a5407b1cb181e544337 100644
--- a/src/functionObjects/graphics/runTimePostProcessing/functionObjectSurface.C
+++ b/src/functionObjects/graphics/runTimePostProcessing/functionObjectSurface.C
@@ -129,7 +129,8 @@ addGeometry
         return false;
     }
 
-    DebugInfo << "    Resolve surface " << functionObjectName_ << endl;
+    DebugInfo
+        << "    Find surface " << functionObjectName_ << endl;
 
     const polySurface* surf =
     (
@@ -181,12 +182,11 @@ addGeometry
             << functionObjectName_
             << endl;
 
-        if (debug)
-        {
-            Info<< "    Available surfaces:" << nl
-                << geometryBase::parent_.storedObjects()
-                    .sortedNames<polySurface>() << endl;
-        }
+        DebugInfo
+            << "    Available surfaces:" << nl
+            << geometryBase::parent_.storedObjects()
+                .sortedNames<polySurface>() << endl;
+
         return false;
     }
 
@@ -252,6 +252,9 @@ addGeometry
     fieldSummary fieldInfo = queryFieldSummary(fieldName_, multiPiece);
     fieldInfo.reduce();
 
+    DebugInfo
+        << "    Field " << fieldName_ << ' ' << fieldInfo.info() << endl;
+
 
     // Not rendered on this processor?
     // This is where we stop, but could also have an MPI barrier
@@ -370,7 +373,8 @@ addGeometryFromFile
             }
             else
             {
-                DebugInfo << "    Resolved surface " << fName << endl;
+                DebugInfo
+                    << "    Resolved surface " << fName << endl;
             }
         }
         else
@@ -401,6 +405,9 @@ addGeometryFromFile
     fieldSummary fieldInfo = queryFieldSummary(fieldName_, polyData);
     // No reduction (serial)
 
+    DebugInfo
+        << "    Field " << fieldName_ << ' ' << fieldInfo.info() << endl;
+
 
     // Render
 
@@ -472,7 +479,8 @@ addGeometryToScene
     }
     else
     {
-        DebugInfo << "Using file source only" << nl;
+        DebugInfo
+            << "Using file source only" << nl;
     }
 
     // File source
diff --git a/src/functionObjects/graphics/runTimePostProcessing/geometryBase.C b/src/functionObjects/graphics/runTimePostProcessing/geometryBase.C
index bac6e4fb06ec0ee7a7b93117d043068f89289e61..90c33fa30e115f6c28646adcdf5d2904f097c531 100644
--- a/src/functionObjects/graphics/runTimePostProcessing/geometryBase.C
+++ b/src/functionObjects/graphics/runTimePostProcessing/geometryBase.C
@@ -39,7 +39,6 @@ namespace functionObjects
 {
 namespace runTimePostPro
 {
-
     defineDebugSwitchWithName(geometryBase, "runTimePostPro::geometryBase", 0);
 }
 }
@@ -99,10 +98,20 @@ Foam::functionObjects::runTimePostPro::geometryBase::geometryBase
 :
     parent_(parent),
     name_(dict.dictName()),
-    visible_(dict.lookupOrDefault("visible", true)),
+    visible_(dict.getOrDefault("visible", true)),
+    parallel_
+    (
+        // User input can only disable parallel here
+        #ifdef FOAM_USING_VTK_MPI
+        Pstream::parRun() && parent.parallel()
+     && dict.getOrDefault("parallel", parent.parallel())
+        #else
+        false
+        #endif
+    ),
     renderMode_
     (
-        renderModeTypeNames.lookupOrDefault("renderMode", dict, rmGouraud)
+        renderModeTypeNames.getOrDefault("renderMode", dict, rmGouraud)
     ),
     opacity_(nullptr),
     colours_(colours)
@@ -136,7 +145,7 @@ Foam::functionObjects::runTimePostPro::geometryBase::parent() const
 bool Foam::functionObjects::runTimePostPro::geometryBase::
 needsCollective() const
 {
-    return parent_.needsCollective();
+    return Pstream::parRun() && (!parent_.parallel() || !parallel_);
 }
 
 
@@ -147,12 +156,6 @@ Foam::functionObjects::runTimePostPro::geometryBase::name() const
 }
 
 
-bool Foam::functionObjects::runTimePostPro::geometryBase::visible() const
-{
-    return visible_;
-}
-
-
 Foam::scalar Foam::functionObjects::runTimePostPro::geometryBase::opacity
 (
     const scalar position
diff --git a/src/functionObjects/graphics/runTimePostProcessing/geometryBase.H b/src/functionObjects/graphics/runTimePostProcessing/geometryBase.H
index 6fdb2c5ba5129ce7d55a46c23fde05c3c265acd0..f171108b1016739c193bda7916a9748c4dc12eb7 100644
--- a/src/functionObjects/graphics/runTimePostProcessing/geometryBase.H
+++ b/src/functionObjects/graphics/runTimePostProcessing/geometryBase.H
@@ -29,10 +29,11 @@ Description
 
     Dictionary controls
     \table
-        Property    | Description                          | Required | Default
-        visible     | Display the object                   | no  | yes
-        renderMode  | Shading (flat/gouraud/phong)         | no  | gouraud
-        opacity     | Object opacity                       | no  | 1.0
+        Property    | Description                           | Required | Default
+        visible     | Display the object                    | no  | yes
+        renderMode  | Shading (flat/gouraud/phong)          | no  | gouraud
+        opacity     | Object opacity                        | no  | 1.0
+        parallel    | Allow parallel rendering              | no  | true
     \endtable
 
 SourceFiles
@@ -102,6 +103,9 @@ protected:
         //- Visible flag
         bool visible_;
 
+        //- Allow parallel rendering
+        bool parallel_;
+
         //- Render mode
         renderModeType renderMode_;
 
@@ -146,8 +150,6 @@ public:
 
     // Member Functions
 
-    // Access
-
         //- Return the reference to the parent function object
         const runTimePostProcessing& parent() const;
 
@@ -159,7 +161,16 @@ public:
         const word& name() const;
 
         //- Return the visible flag
-        bool visible() const;
+        bool visible() const
+        {
+            return visible_;
+        }
+
+        //- Allow parallel rendering
+        bool parallel() const
+        {
+            return parallel_;
+        }
 
         //- Return the opacity
         scalar opacity(const scalar position) const;
diff --git a/src/functionObjects/graphics/runTimePostProcessing/geometryCloud.C b/src/functionObjects/graphics/runTimePostProcessing/geometryCloud.C
index 350c714f8bf5ac217048e866948dfacd2ab5918c..c60ac2fa9beeb31e8bd0060c1fec1719e1872a08 100644
--- a/src/functionObjects/graphics/runTimePostProcessing/geometryCloud.C
+++ b/src/functionObjects/graphics/runTimePostProcessing/geometryCloud.C
@@ -183,6 +183,9 @@ addGeometry
         return true;
     }
 
+    DebugInfo
+        << "    Render cloud " << cloudName_ << endl;
+
 
     // Rendering
 
diff --git a/src/functionObjects/graphics/runTimePostProcessing/geometryPatches.C b/src/functionObjects/graphics/runTimePostProcessing/geometryPatches.C
index c3e711b5afac86f7093d5fcc0e6ed1115723afa8..499984e1f1d44dcb78b2b2510dee2d626eb3375b 100644
--- a/src/functionObjects/graphics/runTimePostProcessing/geometryPatches.C
+++ b/src/functionObjects/graphics/runTimePostProcessing/geometryPatches.C
@@ -77,7 +77,7 @@ Foam::functionObjects::runTimePostPro::geometryPatches::geometryPatches
     geometrySurface(parent, dict, colours, List<fileName>()),
     fieldVisualisationBase(dict, colours),
     selectPatches_(),
-    nearCellValue_(dict.lookupOrDefault("nearCellValue", false))
+    nearCellValue_(dict.getOrDefault("nearCellValue", false))
 {
     dict.readEntry("patches", selectPatches_);
 }
@@ -204,6 +204,8 @@ void Foam::functionObjects::runTimePostPro::geometryPatches::addGeometryToScene
     fieldSummary fieldInfo = queryFieldSummary(fieldName_, multiPiece);
     fieldInfo.reduce();
 
+    DebugInfo
+        << "    Field " << fieldName_ << ' ' << fieldInfo.info() << endl;
 
     // Not rendering on this processor?
     // This is where we stop, but could also have a MPI barrier
diff --git a/src/functionObjects/graphics/runTimePostProcessing/runTimePostProcessing.C b/src/functionObjects/graphics/runTimePostProcessing/runTimePostProcessing.C
index f514b39b714ab220388aad3cb8fef649ec9fa2df..8d0deb0e2b42747c8f57e877337a3c357609657e 100644
--- a/src/functionObjects/graphics/runTimePostProcessing/runTimePostProcessing.C
+++ b/src/functionObjects/graphics/runTimePostProcessing/runTimePostProcessing.C
@@ -85,7 +85,14 @@ static void addGeometryToScene
 {
     for (Type& obj : objects)
     {
-        obj.addGeometryToScene(position, renderer);
+        if (Pstream::master() || obj.parallel())
+        {
+            obj.addGeometryToScene(position, renderer);
+        }
+        else
+        {
+            obj.addGeometryToScene(position, nullptr);
+        }
     }
 }
 
@@ -303,7 +310,7 @@ bool Foam::functionObjects::runTimePostProcessing::read(const dictionary& dict)
     fvMeshFunctionObject::read(dict);
 
     #ifdef FOAM_USING_VTK_MPI
-    parallel_ = (Pstream::parRun() && dict.lookupOrDefault("parallel", true));
+    parallel_ = (Pstream::parRun() && dict.getOrDefault("parallel", true));
     #else
     parallel_ = false;
     #endif
@@ -311,7 +318,7 @@ bool Foam::functionObjects::runTimePostProcessing::read(const dictionary& dict)
     Info<< type() << " " << name() << ": reading post-processing data ("
         << (parallel_ ? "parallel" : "serial") << " rendering)" << endl;
 
-    if (dict.lookupOrDefault("debug", false))
+    if (dict.getOrDefault("debug", false))
     {
         runTimePostPro::geometryBase::debug = 1;
         Info<< "    debugging on" << endl;
diff --git a/src/functionObjects/graphics/runTimePostProcessing/runTimePostProcessing.H b/src/functionObjects/graphics/runTimePostProcessing/runTimePostProcessing.H
index 21ae24b147b7c70e7bf29a87d4b65184baf50a43..33ca86134d0ff65898b32ea14c848a508a2f0d1d 100644
--- a/src/functionObjects/graphics/runTimePostProcessing/runTimePostProcessing.H
+++ b/src/functionObjects/graphics/runTimePostProcessing/runTimePostProcessing.H
@@ -97,9 +97,10 @@ Description
 
     Dictionary controls
     \table
-        Property    | Description                          | Required | Default
-        type        | Type-name: runTimePostProcessing     | yes |
-        debug       | Additional debug information         | no  | false
+        Property    | Description                           | Required | Default
+        type        | Type-name: runTimePostProcessing      | yes |
+        debug       | Additional debug information          | no  | false
+        parallel    | Allow parallel rendering              | no  | true
     \endtable
 
 SourceFiles
@@ -162,7 +163,7 @@ class runTimePostProcessing
         //- Output instance
         outputType output_;
 
-        //- Parallel rendering
+        //- Allow parallel rendering
         bool parallel_;
 
         //- Scene manager
@@ -220,7 +221,7 @@ public:
 
     // Member Functions
 
-        //- Parallel rendering
+        //- Allow parallel rendering
         bool parallel() const
         {
             return parallel_;
diff --git a/src/functionObjects/graphics/runTimePostProcessing/scene.C b/src/functionObjects/graphics/runTimePostProcessing/scene.C
index edbb43c20681be3cbeb8c321e8cdbc0de8ba2624..30026b9999d113f9e420341f3d116d1ade455f5d 100644
--- a/src/functionObjects/graphics/runTimePostProcessing/scene.C
+++ b/src/functionObjects/graphics/runTimePostProcessing/scene.C
@@ -45,39 +45,35 @@ void Foam::functionObjects::runTimePostPro::scene::readCamera
     const dictionary& dict
 )
 {
-    if (dict.readIfPresent("nFrameTotal", nFrameTotal_))
-    {
-        if (nFrameTotal_ < 1)
-        {
-            FatalIOErrorInFunction(dict)
-                << "nFrameTotal must be 1 or greater"
-                << exit(FatalIOError);
-        }
-    }
+    nFrameTotal_ = dict.getCheckOrDefault<label>
+    (
+        "nFrameTotal",
+        1,
+        labelMinMax::ge(1)
+    );
 
-    if (dict.readIfPresent("startPosition", startPosition_))
+    if
+    (
+        dict.readCheckIfPresent
+        (
+            "startPosition",
+            startPosition_,
+            scalarMinMax::zero_one()
+        )
+    )
     {
-        if ((startPosition_ < 0) || (startPosition_ > 1))
-        {
-            FatalIOErrorInFunction(dict)
-                << "startPosition must be in the range 0-1"
-                << exit(FatalIOError);
-        }
-        else
-        {
-            position_ = startPosition_;
-        }
+        position_ = startPosition_;
     }
 
     if (nFrameTotal_ > 1)
     {
-        scalar endPosition = dict.lookupOrDefault<scalar>("endPosition", 1);
-        if ((endPosition < 0) || (endPosition > 1))
-        {
-            FatalIOErrorInFunction(dict)
-                << "endPosition must be in the range 0-1"
-                << exit(FatalIOError);
-        }
+        scalar endPosition = dict.getCheckOrDefault<scalar>
+        (
+            "endPosition",
+            1,
+            scalarMinMax::zero_one()
+        );
+
         dPosition_ = (endPosition - startPosition_)/scalar(nFrameTotal_ - 1);
     }
 
@@ -86,7 +82,7 @@ void Foam::functionObjects::runTimePostPro::scene::readCamera
     cameraUp_ = Function1<vector>::New("up", dict);
 
     dict.readIfPresent("clipBox", clipBox_);
-    dict.readEntry("parallelProjection", parallelProjection_);
+    parallelProjection_ = dict.getOrDefault("parallelProjection", true);
     if (!parallelProjection_)
     {
         if (dict.found("viewAngle"))
diff --git a/src/functionObjects/graphics/runTimePostProcessing/surface.C b/src/functionObjects/graphics/runTimePostProcessing/surface.C
index 62f11d0e605828264677db842a86193e35d14561..98c799f8f03003d5df0816e7a9f55c08ae1a4c97 100644
--- a/src/functionObjects/graphics/runTimePostProcessing/surface.C
+++ b/src/functionObjects/graphics/runTimePostProcessing/surface.C
@@ -204,7 +204,7 @@ Foam::functionObjects::runTimePostPro::surface::surface
     (
         representationTypeNames.get("representation", dict)
     ),
-    featureEdges_(dict.lookupOrDefault("featureEdges", false)),
+    featureEdges_(dict.getOrDefault("featureEdges", false)),
     surfaceColour_(nullptr),
     edgeColour_(nullptr),
     surfaceActor_(),
diff --git a/src/functionObjects/graphics/runTimePostProcessing/text.C b/src/functionObjects/graphics/runTimePostProcessing/text.C
index 688e77486b207ac8eca21cf9b7d5f581c4ae5599..47b7914f070863c6d88815dac77c5934fc094a00 100644
--- a/src/functionObjects/graphics/runTimePostProcessing/text.C
+++ b/src/functionObjects/graphics/runTimePostProcessing/text.C
@@ -67,12 +67,12 @@ Foam::functionObjects::runTimePostPro::text::text
     colour_(nullptr),
     halign_
     (
-        halignTypeNames.lookupOrDefault("halign", dict, halignType::LEFT)
+        halignTypeNames.getOrDefault("halign", dict, halignType::LEFT)
     ),
     bold_(dict.get<bool>("bold")),
-    italic_(dict.lookupOrDefault("italic", false)),
-    shadow_(dict.lookupOrDefault("shadow", false)),
-    timeStamp_(dict.lookupOrDefault("timeStamp", false))
+    italic_(dict.getOrDefault("italic", false)),
+    shadow_(dict.getOrDefault("shadow", false)),
+    timeStamp_(dict.getOrDefault("timeStamp", false))
 {
     if (!dict.readIfPresent("positions", positions_))
     {
diff --git a/src/functionObjects/initialisation/Make/files b/src/functionObjects/initialisation/Make/files
new file mode 100644
index 0000000000000000000000000000000000000000..d57050c0c57094a070d902bec07f6c748ae636e8
--- /dev/null
+++ b/src/functionObjects/initialisation/Make/files
@@ -0,0 +1,3 @@
+hydrostaticPressure/hydrostaticPressure.C
+
+LIB = $(FOAM_LIBBIN)/libinitialisationFunctionObjects
diff --git a/src/functionObjects/initialisation/Make/options b/src/functionObjects/initialisation/Make/options
new file mode 100644
index 0000000000000000000000000000000000000000..2372619dd32be16a846abf76cdabcb5a3550c9c1
--- /dev/null
+++ b/src/functionObjects/initialisation/Make/options
@@ -0,0 +1,43 @@
+EXE_INC = \
+    -I$(LIB_SRC)/finiteVolume/lnInclude \
+    -I$(LIB_SRC)/meshTools/lnInclude \
+    -I$(LIB_SRC)/lagrangian/basic/lnInclude \
+    -I$(LIB_SRC)/lagrangian/distributionModels/lnInclude \
+    -I$(LIB_SRC)/fileFormats/lnInclude \
+    -I$(LIB_SRC)/sampling/lnInclude \
+    -I$(LIB_SRC)/surfMesh/lnInclude \
+    -I$(LIB_SRC)/thermophysicalModels/basic/lnInclude \
+    -I$(LIB_SRC)/transportModels \
+    -I$(LIB_SRC)/transportModels/compressible/lnInclude \
+    -I$(LIB_SRC)/TurbulenceModels/turbulenceModels/lnInclude \
+    -I$(LIB_SRC)/TurbulenceModels/incompressible/lnInclude \
+    -I$(LIB_SRC)/TurbulenceModels/compressible/lnInclude \
+    -I$(LIB_SRC)/transportModels/compressible/lnInclude \
+    -I$(LIB_SRC)/thermophysicalModels/basic/lnInclude \
+    -I$(LIB_SRC)/thermophysicalModels/solidThermo/lnInclude \
+    -I$(LIB_SRC)/thermophysicalModels/chemistryModel/lnInclude \
+    -I$(LIB_SRC)/thermophysicalModels/reactionThermo/lnInclude \
+    -I$(LIB_SRC)/thermophysicalModels/specie/lnInclude \
+    -I$(LIB_SRC)/finiteVolume/lnInclude \
+    -I$(LIB_SRC)/meshTools/lnInclude \
+    -I$(LIB_SRC)/sampling/lnInclude \
+    -I$(LIB_SRC)/surfMesh/lnInclude \
+    -I$(LIB_SRC)/fvAgglomerationMethods/pairPatchAgglomeration/lnInclude
+
+LIB_LIBS = \
+    -lfiniteVolume \
+    -lmeshTools \
+    -llagrangian \
+    -ldistributionModels \
+    -lsampling \
+    -lsurfMesh \
+    -lfluidThermophysicalModels \
+    -lsolidThermo \
+    -lincompressibleTransportModels \
+    -lturbulenceModels \
+    -lcompressibleTransportModels \
+    -lincompressibleTurbulenceModels \
+    -lcompressibleTurbulenceModels \
+    -lchemistryModel \
+    -lreactionThermophysicalModels \
+    -lpairPatchAgglomeration
diff --git a/src/functionObjects/initialisation/hydrostaticPressure/hydrostaticPressure.C b/src/functionObjects/initialisation/hydrostaticPressure/hydrostaticPressure.C
new file mode 100644
index 0000000000000000000000000000000000000000..1b7e2505c71de60be44821e0ab9d5fac8b3df45a
--- /dev/null
+++ b/src/functionObjects/initialisation/hydrostaticPressure/hydrostaticPressure.C
@@ -0,0 +1,243 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  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 <http://www.gnu.org/licenses/>.
+
+\*---------------------------------------------------------------------------*/
+
+#include "hydrostaticPressure.H"
+#include "basicThermo.H"
+#include "uniformDimensionedFields.H"
+#include "volFields.H"
+#include "surfaceInterpolate.H"
+#include "fvcDiv.H"
+#include "fvmLaplacian.H"
+#include "fvcSnGrad.H"
+#include "constrainPressure.H"
+
+#include "addToRunTimeSelectionTable.H"
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+namespace Foam
+{
+namespace functionObjects
+{
+    defineTypeNameAndDebug(hydrostaticPressure, 0);
+
+    addToRunTimeSelectionTable
+    (
+        functionObject,
+        hydrostaticPressure,
+        dictionary
+    );
+}
+}
+
+
+Foam::dimensionedScalar
+Foam::functionObjects::hydrostaticPressure::pRef() const
+{
+    if (pRefName_ == "none")
+    {
+        return dimensionedScalar("pRef", dimPressure, pRefValue_);
+    }
+    else
+    {
+        return mesh_.lookupObject<uniformDimensionedScalarField>(pRefName_);
+    }
+}
+
+
+void Foam::functionObjects::hydrostaticPressure::calculateAndWrite()
+{
+    const auto& pRef = this->pRef();
+    const auto& U = mesh_.lookupObject<volVectorField>(UName_);
+    const auto& gh = mesh_.lookupObject<volScalarField>(ghName_);
+    const auto& ghf = mesh_.lookupObject<surfaceScalarField>(ghfName_);
+    auto& rho = mesh_.lookupObjectRef<volScalarField>(rhoName_);
+    auto& thermo = mesh_.lookupObjectRef<basicThermo>(basicThermo::dictName);
+    auto& p_rgh = mesh_.lookupObjectRef<volScalarField>(p_rghName_);
+    auto& ph_rgh = mesh_.lookupObjectRef<volScalarField>(ph_rghName_);
+
+    auto& p = thermo.p();
+
+    Info<< "Performing hydrostatic pressure initialisation";
+    if (mesh_.name() != polyMesh::defaultRegion)
+    {
+        Info<< "for region " << mesh_.name();
+    }
+
+
+    if (thermo.incompressible())
+    {
+        Info<< ": incompressible" << endl;
+
+        // Constant density and temperature
+
+        thermo.correct();
+        rho = thermo.rho();
+        p = ph_rgh + rho*gh + pRef;
+        p_rgh = ph_rgh;
+    }
+    else
+    {
+        Info<< ": compressible" << endl;
+
+        p = ph_rgh + rho*gh + pRef;
+        thermo.correct();
+        rho = thermo.rho();
+
+        for (label i=0; i<nCorrectors_; ++i)
+        {
+            surfaceScalarField rhof("rhof", fvc::interpolate(rho));
+
+            surfaceScalarField phig
+            (
+                "phig",
+               -rhof*ghf*fvc::snGrad(rho)*mesh_.magSf()
+            );
+
+            // Update the pressure BCs to ensure flux consistency
+            constrainPressure(ph_rgh, rho, U, phig, rhof);
+
+            fvScalarMatrix ph_rghEqn
+            (
+                fvm::laplacian(rhof, ph_rgh) == fvc::div(phig)
+            );
+
+            ph_rghEqn.relax();
+
+            ph_rghEqn.solve();
+
+            p = ph_rgh + rho*gh + pRef;
+            thermo.correct();
+            rho = thermo.rho();
+
+            Info<< "Hydrostatic pressure variation "
+                << (max(ph_rgh) - min(ph_rgh)).value() << endl;
+        }
+
+        p_rgh = ph_rgh;
+
+        Log << "    writing field " << ph_rgh.name() << nl;
+        ph_rgh.write();
+    }
+
+    Log << "    writing field " << rho.name() << nl;
+    rho.write();
+
+    Log << "    writing field " << p_rgh.name() << nl;
+    p_rgh.write();
+
+    Log << "    writing field " << p.name() << nl;
+    p.write();
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::functionObjects::hydrostaticPressure::hydrostaticPressure
+(
+    const word& name,
+    const Time& runTime,
+    const dictionary& dict
+)
+:
+    fvMeshFunctionObject(name, runTime, dict),
+    p_rghName_("p_rgh"),
+    ph_rghName_("ph_rgh"),
+    pRefName_("pRef"),
+    pRefValue_(0),
+    rhoName_("rho"),
+    UName_("U"),
+    ghName_("gh"),
+    ghfName_("ghf"),
+    nCorrectors_(5)
+{
+    if (read(dict))
+    {
+        // Read and store the initial ph_rgh field
+        volScalarField* ph_rghPtr =
+            new volScalarField
+            (
+                IOobject
+                (
+                    ph_rghName_,
+                    runTime.timeName(),
+                    mesh_,
+                    IOobject::MUST_READ,
+                    IOobject::AUTO_WRITE // To enable restart
+                ),
+                mesh_
+            );
+
+        mesh_.objectRegistry::store(ph_rghPtr);
+
+        bool reInitialise = dict.lookupOrDefault<bool>("reInitialise", false);
+
+        if (runTime.timeIndex() == 0 || reInitialise)
+        {
+            calculateAndWrite();
+        }
+    }
+}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+bool Foam::functionObjects::hydrostaticPressure::read(const dictionary& dict)
+{
+    if (fvMeshFunctionObject::read(dict))
+    {
+        dict.readIfPresent("p_rgh", p_rghName_);
+        dict.readIfPresent("ph_rgh", ph_rghName_);
+        dict.readIfPresent("pRef", pRefName_);
+        dict.readIfPresent("rho", rhoName_);
+        dict.readIfPresent("U", UName_);
+        dict.readIfPresent("gh", ghName_);
+        dict.readIfPresent("ghf", ghfName_);
+        dict.readIfPresent("nCorrectors", nCorrectors_);
+
+        if (pRefName_ == "none")
+        {
+            pRefValue_ = dict.get<scalar>("pRefValue");
+        }
+        return true;
+    }
+
+    return false;
+}
+
+
+bool Foam::functionObjects::hydrostaticPressure::execute()
+{
+    return true;
+}
+
+
+bool Foam::functionObjects::hydrostaticPressure::write()
+{
+    return true;
+}
+
+
+// ************************************************************************* //
diff --git a/src/functionObjects/initialisation/hydrostaticPressure/hydrostaticPressure.H b/src/functionObjects/initialisation/hydrostaticPressure/hydrostaticPressure.H
new file mode 100644
index 0000000000000000000000000000000000000000..d14228fe1e00ba9ecabc0869e21d60297ff8d20a
--- /dev/null
+++ b/src/functionObjects/initialisation/hydrostaticPressure/hydrostaticPressure.H
@@ -0,0 +1,176 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  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 <http://www.gnu.org/licenses/>.
+
+Class
+    Foam::functionObjects::hydrostaticPressure
+
+Group
+    grpInitialisationFunctionObjects
+
+Description
+    Calculates and outputs the pressure fields p_rgh and ph_rgh
+
+Usage
+    Example of function object specification to calculate hydrostatic pressure:
+    \verbatim
+    hydrostaticPressure1
+    {
+        type        hydrostaticPressure;
+        libs        ("libinitialisationFunctionObjects.so");
+        ...
+    }
+    \endverbatim
+
+    Where the entries comprise:
+    \table
+        Property     | Description             | Required    | Default value
+        log          | Log to standard output  | no          | yes
+        p_rgh        | Name of p_rgh field     | no          | p_rgh
+        ph_rgh       | Name of ph_rgh field    | no          | ph_rgh
+        pRef         | Name of pressure ref field | no       | pRef
+        rho          | Name of density field   | no          | rho
+        U            | Name of velocity field  | no          | U
+        gh           | Name of gravity*height volume field  | no | gh
+        ghf          | Name of gravity*height surface field | no | ghf
+        nCorrectors  | Number of correctors when solving ph_rgh | no | 5
+    \endtable
+
+Note
+    Calculates the hydrostatic pressure on construction/re-initialisation;
+    the execute and write functions are not used.
+
+SourceFiles
+    hydrostaticPressure.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef functionObjects_hydrostaticPressure_H
+#define functionObjects_hydrostaticPressure_H
+
+#include "fvMeshFunctionObject.H"
+#include "uniformDimensionedFields.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+namespace functionObjects
+{
+
+/*---------------------------------------------------------------------------*\
+                     Class hydrostaticPressure Declaration
+\*---------------------------------------------------------------------------*/
+
+class hydrostaticPressure
+:
+    public fvMeshFunctionObject
+{
+protected:
+
+    // Protected data
+
+        //- Name of p - rho*g*h field, default is "p_rgh"
+        word p_rghName_;
+
+        //- Name of p_hydrostatic - rho*g*h field, default is "ph_rgh"
+        word ph_rghName_;
+
+        //- Name of uniform pressure reference field, default is "pRef"
+        //  Set to "none" to set to zero
+        word pRefName_;
+
+        //- Reference pressure if pRef is set to "none"
+        scalar pRefValue_;
+
+        //- Name of density field, default is "rho"
+        word rhoName_;
+
+        //- Name of velocity field, default is "ph_rgh"
+        word UName_;
+
+        //- Name of g*h volume field, default is "gh"
+        word ghName_;
+
+        //- Name of g*h surface field, default is "ghf"
+        word ghfName_;
+
+        //- Number of correctors when solving for ph_rgh
+        label nCorrectors_;
+
+
+    // Protected Member Functions
+
+        //- Helper function to return the reference pressure
+        //  Returns zero if pRefName = none; otherwise returns the value
+        //  from the mesh database
+        dimensionedScalar pRef() const;
+
+        //- Calculate the fields and write
+        void calculateAndWrite();
+
+
+public:
+
+    //- Runtime type information
+    TypeName("hydrostaticPressure");
+
+
+    // Constructors
+
+        //- Construct from Time and dictionary
+        hydrostaticPressure
+        (
+            const word& name,
+            const Time& runTime,
+            const dictionary& dict
+        );
+
+
+    //- Destructor
+    virtual ~hydrostaticPressure() = default;
+
+
+    // Member Functions
+
+        //- Read the hydrostaticPressure data
+        virtual bool read(const dictionary& dict);
+
+        //- Calculate the p_rgh field
+        virtual bool execute();
+
+        //- Write the p_rgh and derived fields
+        virtual bool write();
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace functionObjects
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/functionObjects/utilities/Make/files b/src/functionObjects/utilities/Make/files
index 79c11e83e2cd33ec431208cd11428eced7ab4367..c3f384ee69607379d282b00876c1da1174bfcc3a 100644
--- a/src/functionObjects/utilities/Make/files
+++ b/src/functionObjects/utilities/Make/files
@@ -15,6 +15,7 @@ removeRegisteredObject/removeRegisteredObject.C
 parProfiling/parProfiling.C
 
 solverInfo/solverInfo.C
+timeInfo/timeInfo.C
 
 runTimeControl/runTimeControl.C
 runTimeControl/runTimeCondition/runTimeCondition/runTimeCondition.C
diff --git a/src/functionObjects/utilities/parProfiling/parProfiling.C b/src/functionObjects/utilities/parProfiling/parProfiling.C
index ade16fb0516b122c1c22f261b0153aedb4a31974..5c6513dcd8eb38087039750f63a0a52a9a694678 100644
--- a/src/functionObjects/utilities/parProfiling/parProfiling.C
+++ b/src/functionObjects/utilities/parProfiling/parProfiling.C
@@ -183,28 +183,21 @@ void Foam::functionObjects::parProfiling::report()
         const statData& allToAllStats = times[1];
 
         scalar reduceAvg = reduceStats[2].second()/Pstream::nProcs();
-        scalar reduceRelMin =
-            (reduceStats[0].second()-reduceAvg)/(reduceAvg + VSMALL);
-        scalar reduceRelMax =
-            (reduceStats[1].second()-reduceAvg)/(reduceAvg + VSMALL);
-
         scalar allToAllAvg = allToAllStats[2].second()/Pstream::nProcs();
-        scalar allToAllRelMin =
-            (allToAllStats[0].second()-allToAllAvg)/(allToAllAvg + VSMALL);
-        scalar allToAllRelMax =
-            (allToAllStats[1].second()-allToAllAvg)/(allToAllAvg + VSMALL);
 
         Info<< type() << ':' << nl
-            << "\treduce    : avg = " << reduceAvg << 's' << nl
-            << "\t            min = " << reduceRelMin*100
-            << "% (processor " << reduceStats[0].first() << ')' << nl
-            << "\t            max = +" << reduceRelMax*100
-            << "% (processor " << reduceStats[1].first() << ')' << nl
-            << "\tall-all   : avg = " << allToAllAvg << 's' << nl
-            << "\t            min = " << allToAllRelMin*100
-            << "% (processor " << allToAllStats[0].first() << ')' << nl
-            << "\t            max = +" << allToAllRelMax*100
-            << "% (processor " << allToAllStats[1].first() << ')' << endl;
+            << incrIndent
+            << indent << "reduce    : avg = " << reduceAvg << 's' << nl
+            << indent << "            min = " << reduceStats[0].second()
+            << "s (processor " << reduceStats[0].first() << ')' << nl
+            << indent << "            max = " << reduceStats[1].second()
+            << "s (processor " << reduceStats[1].first() << ')' << nl
+            << indent << "all-all   : avg = " << allToAllAvg << 's' << nl
+            << indent << "            min = " << allToAllStats[0].second()
+            << "s (processor " << allToAllStats[0].first() << ')' << nl
+            << indent << "            max = " << allToAllStats[1].second()
+            << "s (processor " << allToAllStats[1].first() << ')'
+            << decrIndent << endl;
     }
 }
 
@@ -224,7 +217,6 @@ bool Foam::functionObjects::parProfiling::write()
 
 bool Foam::functionObjects::parProfiling::end()
 {
-    report();
     profilingPstream::disable();
     return true;
 }
diff --git a/src/functionObjects/utilities/parProfiling/parProfiling.H b/src/functionObjects/utilities/parProfiling/parProfiling.H
index 32b055bc5479c4378518ec3ba8b56bf64d3f5bf7..1b7dbf28dbffc3562f36f05ebca3fde39085ac8c 100644
--- a/src/functionObjects/utilities/parProfiling/parProfiling.H
+++ b/src/functionObjects/utilities/parProfiling/parProfiling.H
@@ -30,6 +30,20 @@ Group
 Description
     Simple (simplistic) mpi-profiling.
 
+Usage
+    Example of function object specification:
+    \verbatim
+    profiling
+    {
+        type  parProfiling;
+        libs  ("libutilityFunctionObjects.so");
+
+        // Report stats on exit only (instead of every time step)
+        executeControl  onEnd;
+        writeControl    none;
+    }
+    \endverbatim
+
 SourceFiles
     parProfiling.C
 
diff --git a/src/functionObjects/utilities/runTimeControl/runTimeCondition/averageCondition/averageCondition.C b/src/functionObjects/utilities/runTimeControl/runTimeCondition/averageCondition/averageCondition.C
index f5fe7d556ea009a28b126e67f4863fc8cac90a0f..1f2d4d62646165550845b6fae0b58bda2f362cb6 100644
--- a/src/functionObjects/utilities/runTimeControl/runTimeCondition/averageCondition/averageCondition.C
+++ b/src/functionObjects/utilities/runTimeControl/runTimeCondition/averageCondition/averageCondition.C
@@ -48,11 +48,11 @@ const Foam::Enum
     Foam::functionObjects::runTimeControls::averageCondition::windowType
 >
 Foam::functionObjects::runTimeControls::averageCondition::windowTypeNames
-{
+({
     { windowType::NONE, "none" },
     { windowType::APPROXIMATE, "approximate" },
     { windowType::EXACT, "exact" }
-};
+});
 
 
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
diff --git a/src/functionObjects/utilities/timeInfo/timeInfo.C b/src/functionObjects/utilities/timeInfo/timeInfo.C
new file mode 100644
index 0000000000000000000000000000000000000000..ba5767de8e50d9cdb37d265b94aea184cfc930ec
--- /dev/null
+++ b/src/functionObjects/utilities/timeInfo/timeInfo.C
@@ -0,0 +1,131 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2019 OpenCFD Ltd.
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+                            | Copyright (C) 2018 OpenFOAM Foundation
+-------------------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+\*---------------------------------------------------------------------------*/
+
+#include "timeInfo.H"
+#include "addToRunTimeSelectionTable.H"
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+namespace Foam
+{
+namespace functionObjects
+{
+    defineTypeNameAndDebug(timeInfo, 0);
+
+    addToRunTimeSelectionTable
+    (
+        functionObject,
+        timeInfo,
+        dictionary
+    );
+}
+}
+
+
+// * * * * * * * * * * * * * Protected Member Functions  * * * * * * * * * * //
+
+void Foam::functionObjects::timeInfo::writeFileHeader(Ostream& os)
+{
+    writeCommented(os, "Time");
+    writeTabbed(os, "cpuTime");
+    writeTabbed(os, "clockTime");
+
+    if (perTimeStep_)
+    {
+        writeTabbed(os, "cpu/step");
+        writeTabbed(os, "clock/step");
+    }
+
+    os << nl;
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::functionObjects::timeInfo::timeInfo
+(
+    const word& name,
+    const Time& runTime,
+    const dictionary& dict
+)
+:
+    timeFunctionObject(name, runTime),
+    writeFile(time_, name, typeName, dict),
+    cpuTime0_(Zero),
+    clockTime0_(Zero),
+    perTimeStep_(false)
+{
+    read(dict);
+    writeFileHeader(file());
+}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+bool Foam::functionObjects::timeInfo::read(const dictionary& dict)
+{
+    timeFunctionObject::read(dict);
+    writeFile::read(dict);
+
+    perTimeStep_ = dict.lookupOrDefault("perTimeStep", false);
+    return true;
+}
+
+
+bool Foam::functionObjects::timeInfo::execute()
+{
+    return true;
+}
+
+
+bool Foam::functionObjects::timeInfo::write()
+{
+    if (Pstream::master())
+    {
+        writeTime(file());
+
+        const scalar cpuTimeNow(time_.elapsedCpuTime());
+        const scalar clockTimeNow(time_.elapsedClockTime());
+
+        file()
+            << tab << cpuTimeNow
+            << tab << clockTimeNow;
+
+        if (perTimeStep_)
+        {
+            file()
+                << tab << (cpuTimeNow - cpuTime0_)
+                << tab << (clockTimeNow - clockTime0_);
+
+            cpuTime0_ = cpuTimeNow;
+            clockTime0_ = clockTimeNow;
+        }
+
+        file() << nl;
+    }
+
+    return true;
+}
+
+
+// ************************************************************************* //
diff --git a/src/functionObjects/utilities/timeInfo/timeInfo.H b/src/functionObjects/utilities/timeInfo/timeInfo.H
new file mode 100644
index 0000000000000000000000000000000000000000..ca27a8d89c5de32c87a0445aa8fbe33f6895768c
--- /dev/null
+++ b/src/functionObjects/utilities/timeInfo/timeInfo.H
@@ -0,0 +1,161 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2019 OpenCFD Ltd.
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+                            | Copyright (C) 2018 OpenFOAM Foundation
+-------------------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+Class
+    Foam::functionObjects::timeInfo
+
+Description
+    Writes the run time (time-step), cpuTime and clockTime -
+    optionally with cpuTime and clockTime change for each time step.
+
+    Example of function object specification:
+    \verbatim
+    time
+    {
+        type            timeInfo;
+
+        libs            ("libutilityFunctionObjects.so");
+
+        writeControl    timeStep;
+        writeInterval   1;
+
+        perTimeStep     no;
+    }
+    \endverbatim
+
+    Where the entries comprise:
+    \table
+        Property      | Description                         | Required | Default
+        type          | Type name: timeInfo                 | yes |
+        writeToFile   | Write information to file           | no  | yes
+        perTimeStep   | Write value per interval/step       | no  | no
+    \endtable
+
+    The initial per-step value is likely to be inaccurate and should
+    mostly be ignored.
+
+See also
+    Foam::functionObject
+    Foam::timeFunctionObject
+    Foam::functionObjects::writeFile
+
+SourceFiles
+    timeInfo.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef functionObjects_timeInfo_H
+#define functionObjects_timeInfo_H
+
+#include "timeFunctionObject.H"
+#include "writeFile.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+namespace functionObjects
+{
+
+/*---------------------------------------------------------------------------*\
+                          Class timeInfo Declaration
+\*---------------------------------------------------------------------------*/
+
+class timeInfo
+:
+    public timeFunctionObject,
+    public writeFile
+{
+    // Private Member Data
+
+        //- The cpuTime from last write/time-step (for perTimeStep)
+        scalar cpuTime0_;
+
+        //- The clockTime from last write/time-step (for perTimeStep)
+        scalar clockTime0_;
+
+        //- Flag to write cpuTime and clockTime per time-step
+        bool perTimeStep_;
+
+
+protected:
+
+    // Protected Member Functions
+
+        //- Output file header information
+        virtual void writeFileHeader(Ostream& os);
+
+        //- No copy construct
+        timeInfo(const timeInfo&) = delete;
+
+        //- No copy assignment
+        void operator=(const timeInfo&) = delete;
+
+
+public:
+
+    //- Runtime type information
+    TypeName("timeInfo");
+
+
+    // Constructors
+
+        //- Construct from Time and dictionary
+        timeInfo
+        (
+            const word& name,
+            const Time& runTime,
+            const dictionary& dict
+        );
+
+
+    //- Destructor
+    virtual ~timeInfo() = default;
+
+
+    // Member Functions
+
+        //- Read the controls
+        virtual bool read(const dictionary& dict);
+
+        //- Execute, does nothing
+        virtual bool execute();
+
+        //- Write the timeInfo
+        virtual bool write();
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace functionObjects
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
+
diff --git a/src/functionObjects/utilities/writeDictionary/writeDictionary.C b/src/functionObjects/utilities/writeDictionary/writeDictionary.C
index 83a078c69ee2864d632fd35a42acebc5db351302..de17247d089c31e3bd7474bd0bef3db310c692cb 100644
--- a/src/functionObjects/utilities/writeDictionary/writeDictionary.C
+++ b/src/functionObjects/utilities/writeDictionary/writeDictionary.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) 2013-2017 OpenFOAM Foundation
@@ -51,11 +51,43 @@ namespace functionObjects
 
 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
 
+void Foam::functionObjects::writeDictionary::writeHeader()
+{
+    if (firstChange_)
+    {
+        Info<< type() << " " << name() << " write:" << nl << endl;
+
+        IOobject::writeDivider(Info);
+        Info<< endl;
+        firstChange_ = false;
+    }
+}
+
+
+void Foam::functionObjects::writeDictionary::checkDictionary
+(
+    const dictionary& dict,
+    const label dicti
+)
+{
+    if (dict.digest() != digests_[dicti])
+    {
+        writeHeader();
+
+        digests_[dicti] = dict.digest();
+
+        Info<< dict.dictName() << dict << nl;
+
+        IOobject::writeDivider(Info);
+        Info<< endl;
+    }
+}
+
+
 bool Foam::functionObjects::writeDictionary::tryDirectory
 (
-    const label dicti,
     const word& location,
-    bool& firstDict
+    const label dicti
 )
 {
     IOobject dictIO
@@ -70,25 +102,7 @@ bool Foam::functionObjects::writeDictionary::tryDirectory
 
     if (dictIO.typeHeaderOk<IOdictionary>(true))
     {
-        IOdictionary dict(dictIO);
-
-        if (dict.digest() != digests_[dicti])
-        {
-            if (firstDict)
-            {
-                Info<< type() << " " << name() << " write:" << nl << endl;
-
-                IOobject::writeDivider(Info);
-                Info<< endl;
-                firstDict = false;
-            }
-
-            Info<< dict.dictName() << dict << nl;
-
-            IOobject::writeDivider(Info);
-
-            digests_[dicti] = dict.digest();
-        }
+        checkDictionary(IOdictionary(dictIO), dicti);
 
         return true;
     }
@@ -108,19 +122,14 @@ Foam::functionObjects::writeDictionary::writeDictionary
 :
     regionFunctionObject(name, runTime, dict),
     dictNames_(),
-    digests_()
+    digests_(),
+    firstChange_(true)
 {
     read(dict);
     execute();
 }
 
 
-// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
-
-Foam::functionObjects::writeDictionary::~writeDictionary()
-{}
-
-
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
 bool Foam::functionObjects::writeDictionary::read(const dictionary& dict)
@@ -159,55 +168,39 @@ bool Foam::functionObjects::writeDictionary::execute()
 
 bool Foam::functionObjects::writeDictionary::write()
 {
-    bool firstDict = true;
-    forAll(dictNames_, i)
+    firstChange_ = true;
+
+    forAll(dictNames_, dicti)
     {
-        const dictionary* dictptr =
-            obr_.findObject<dictionary>(dictNames_[i]);
+        const IOdictionary* dictptr =
+            obr_.lookupObjectPtr<IOdictionary>(dictNames_[dicti]);
 
         if (dictptr)
         {
-            const dictionary& dict = *dictptr;
-
-            if (dict.digest() != digests_[i])
-            {
-                if (firstDict)
-                {
-                    Info<< type() << " " << name() << " write:" << nl << endl;
-
-                    IOobject::writeDivider(Info);
-                    Info<< endl;
-                    firstDict = false;
-                }
-
-                digests_[i] = dict.digest();
-
-                Info<< dict.dictName() << dict << nl;
-                IOobject::writeDivider(Info);
-                Info<< endl;
-            }
+            checkDictionary(*dictptr, dicti);
         }
         else
         {
-            bool processed = tryDirectory(i, obr_.time().timeName(), firstDict);
+            bool processed = tryDirectory(obr_.time().timeName(), dicti);
 
             if (!processed)
             {
-                processed = tryDirectory(i, obr_.time().constant(), firstDict);
+                processed = tryDirectory(obr_.time().constant(), dicti);
             }
 
             if (!processed)
             {
-                processed = tryDirectory(i, obr_.time().system(), firstDict);
+                processed = tryDirectory(obr_.time().system(), dicti);
             }
 
             if (!processed)
             {
-                Info<< "    Unable to locate dictionary " << dictNames_[i]
+                writeHeader();
+
+                Info<< "    Unable to locate dictionary " << dictNames_[dicti]
                     << nl << endl;
-            }
-            else
-            {
+
+                IOobject::writeDivider(Info);
                 Info<< endl;
             }
         }
diff --git a/src/functionObjects/utilities/writeDictionary/writeDictionary.H b/src/functionObjects/utilities/writeDictionary/writeDictionary.H
index c55933479a372fa8be7c36ae97dbb94e4a6d813e..c7e7d91a5ce7243c82204cdff1e385749c5d3b96 100644
--- a/src/functionObjects/utilities/writeDictionary/writeDictionary.H
+++ b/src/functionObjects/utilities/writeDictionary/writeDictionary.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) 2013-2016 OpenFOAM Foundation
@@ -67,21 +67,21 @@ class writeDictionary
         //- List of changed dictionaries (only those registered to database)
         List<SHA1Digest> digests_;
 
+        //- Flag to indicate the first time that a dictionary is been changed
+        //- (per call to execute)
+        bool firstChange_;
 
-    // Private Member Functions
 
-        //- Helper function to write the dictionary if found at location
-        bool tryDirectory
-        (
-            const label dicti,
-            const word& location,
-            bool& firstDict
-        );
+    // Private Member Functions
 
+        //- Write the output header
+        void writeHeader();
 
-private:
+        //- Helper to check and write the dictionary if its sha1 has changed
+        void checkDictionary(const dictionary& dict, const label dicti);
 
-    // Private member functions
+        //- Helper to write the dictionary if found at location
+        bool tryDirectory(const word& location, const label dicti);
 
         //- No copy construct
         writeDictionary(const writeDictionary&) = delete;
@@ -108,7 +108,7 @@ public:
 
 
     //- Destructor
-    virtual ~writeDictionary();
+    virtual ~writeDictionary() = default;
 
 
     // Member Functions
diff --git a/src/meshTools/edgeMesh/edgeMeshFormats/edgeMesh/edgeMeshFormat.C b/src/meshTools/edgeMesh/edgeMeshFormats/edgeMesh/edgeMeshFormat.C
index 8effdf0309eea7983edf16596d3861cfdcc9dbac..a5982d638902b5ee49846ce13636478bdfa42b9a 100644
--- a/src/meshTools/edgeMesh/edgeMeshFormats/edgeMesh/edgeMeshFormat.C
+++ b/src/meshTools/edgeMesh/edgeMeshFormats/edgeMesh/edgeMeshFormat.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           |
+    \\  /    A nd           | Copyright (C) 2017-2019 OpenCFD Ltd.
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
                             | Copyright (C) 2011-2017 OpenFOAM Foundation
@@ -52,10 +52,6 @@ bool Foam::fileFormats::edgeMeshFormat::read
 {
     clear();
 
-    fileName dir = filename.path();
-    fileName caseName = dir.name();
-    fileName rootPath = dir.path();
-
     // Construct dummy time to use as an objectRegistry
     Time dummyTime
     (
@@ -117,10 +113,7 @@ bool Foam::fileFormats::edgeMeshFormat::read
             << exit(FatalError);
     }
 
-    // read points:
     is  >> pointLst;
-
-    // read edges:
     is  >> edgeLst;
 
     return true;
diff --git a/src/meshTools/edgeMesh/extendedEdgeMesh/extendedEdgeMeshFormats/extendedEdgeMeshFormat/extendedEdgeMeshFormat.C b/src/meshTools/edgeMesh/extendedEdgeMesh/extendedEdgeMeshFormats/extendedEdgeMeshFormat/extendedEdgeMeshFormat.C
index fb52a8a00c246d9b5a17ca922e8663a152fa3e6f..9070943bc23b85251b834fa25031f22fd21e12c6 100644
--- a/src/meshTools/edgeMesh/extendedEdgeMesh/extendedEdgeMeshFormats/extendedEdgeMeshFormat/extendedEdgeMeshFormat.C
+++ b/src/meshTools/edgeMesh/extendedEdgeMesh/extendedEdgeMeshFormats/extendedEdgeMeshFormat/extendedEdgeMeshFormat.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) 2013-2017 OpenFOAM Foundation
@@ -50,10 +50,6 @@ bool Foam::fileFormats::extendedEdgeMeshFormat::read
 {
     clear();
 
-    fileName dir = filename.path();
-    fileName caseName = dir.name();
-    fileName rootPath = dir.path();
-
     // Construct dummy time to use as an objectRegistry
     Time dummyTime
     (
diff --git a/src/overset/cellCellStencil/cellVolumeWeight/cellVolumeWeightCellCellStencil.C b/src/overset/cellCellStencil/cellVolumeWeight/cellVolumeWeightCellCellStencil.C
index 121c8c724433881ccc76fc2c9a2374677480dae3..4f02c9d466c48c7dffa7d2fcf728ef939b51c584 100644
--- a/src/overset/cellCellStencil/cellVolumeWeight/cellVolumeWeightCellCellStencil.C
+++ b/src/overset/cellCellStencil/cellVolumeWeight/cellVolumeWeightCellCellStencil.C
@@ -35,6 +35,7 @@ License
 #include "oversetFvPatch.H"
 #include "zeroGradientFvPatchFields.H"
 #include "syncTools.H"
+#include "dynamicOversetFvMesh.H"
 
 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
 
@@ -1116,7 +1117,12 @@ bool Foam::cellCellStencils::cellVolumeWeight::update()
         {
             patchTypes[cellI] = allPatchTypes[cellI];
         }
-        patchTypes.correctBoundaryConditions();
+        //patchTypes.correctBoundaryConditions();
+        dynamicOversetFvMesh::correctBoundaryConditions
+        <
+            volScalarField,
+            oversetFvPatchField<scalar>
+        >(patchTypes.boundaryFieldRef(), false);
         patchTypes.write();
     }
     if (debug)
@@ -1141,7 +1147,12 @@ bool Foam::cellCellStencils::cellVolumeWeight::update()
         {
             volTypes[cellI] = allCellTypes[cellI];
         }
-        volTypes.correctBoundaryConditions();
+        //volTypes.correctBoundaryConditions();
+        dynamicOversetFvMesh::correctBoundaryConditions
+        <
+            volScalarField,
+            oversetFvPatchField<scalar>
+        >(volTypes.boundaryFieldRef(), false);
         volTypes.write();
     }
 
@@ -1185,7 +1196,12 @@ bool Foam::cellCellStencils::cellVolumeWeight::update()
     cellStencil_.transfer(allStencil);
     cellInterpolationWeights_.transfer(allWeights);
     cellInterpolationWeight_.transfer(allWeight);
-    cellInterpolationWeight_.correctBoundaryConditions();
+    //cellInterpolationWeight_.correctBoundaryConditions();
+    dynamicOversetFvMesh::correctBoundaryConditions
+    <
+        volScalarField,
+        oversetFvPatchField<scalar>
+    >(cellInterpolationWeight_.boundaryFieldRef(), false);
 
     DynamicList<label> interpolationCells;
     forAll(cellStencil_, cellI)
diff --git a/src/overset/cellCellStencil/inverseDistance/inverseDistanceCellCellStencil.C b/src/overset/cellCellStencil/inverseDistance/inverseDistanceCellCellStencil.C
index 9bb6c6fef8548122a78015fa7673da98aa8ec829..a595d80d15c4889520427226109d48ed661490a9 100644
--- a/src/overset/cellCellStencil/inverseDistance/inverseDistanceCellCellStencil.C
+++ b/src/overset/cellCellStencil/inverseDistance/inverseDistanceCellCellStencil.C
@@ -37,6 +37,7 @@ License
 #include "waveMethod.H"
 
 #include "regionSplit.H"
+#include "dynamicOversetFvMesh.H"
 //#include "minData.H"
 //#include "FaceCellWave.H"
 
@@ -2152,7 +2153,11 @@ bool Foam::cellCellStencils::inverseDistance::update()
         new mapDistribute(globalCells, cellStencil_, compactMap)
     );
     cellInterpolationWeight_.transfer(allWeight);
-    cellInterpolationWeight_.correctBoundaryConditions();
+    dynamicOversetFvMesh::correctBoundaryConditions
+    <
+        volScalarField,
+        oversetFvPatchField<scalar>
+    >(cellInterpolationWeight_.boundaryFieldRef(), false);
 
 
     if (debug&2)
@@ -2226,7 +2231,11 @@ bool Foam::cellCellStencils::inverseDistance::update()
             (
                 createField(mesh_, "maxMagWeight", maxMagWeight)
             );
-            tfld.ref().correctBoundaryConditions();
+            dynamicOversetFvMesh::correctBoundaryConditions
+            <
+                volScalarField,
+                oversetFvPatchField<scalar>
+            >(tfld.ref().boundaryFieldRef(), false);
             tfld().write();
         }
 
@@ -2236,7 +2245,12 @@ bool Foam::cellCellStencils::inverseDistance::update()
             (
                 createField(mesh_, "cellTypes", cellTypes_)
             );
-            tfld.ref().correctBoundaryConditions();
+            //tfld.ref().correctBoundaryConditions();
+            dynamicOversetFvMesh::correctBoundaryConditions
+            <
+                volScalarField,
+                oversetFvPatchField<scalar>
+            >(tfld.ref().boundaryFieldRef(), false);
             tfld().write();
         }
 
diff --git a/src/overset/cellCellStencil/trackingInverseDistance/trackingInverseDistanceCellCellStencil.C b/src/overset/cellCellStencil/trackingInverseDistance/trackingInverseDistanceCellCellStencil.C
index db10a358c455d2eac13230fb4164d62774ea91a2..a4c315dd81577c344b7d9d78cfafc79e02732582 100644
--- a/src/overset/cellCellStencil/trackingInverseDistance/trackingInverseDistanceCellCellStencil.C
+++ b/src/overset/cellCellStencil/trackingInverseDistance/trackingInverseDistanceCellCellStencil.C
@@ -34,6 +34,7 @@ License
 #include "syncTools.H"
 #include "treeBoundBoxList.H"
 #include "voxelMeshSearch.H"
+#include "dynamicOversetFvMesh.H"
 
 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
 
@@ -961,7 +962,12 @@ bool Foam::cellCellStencils::trackingInverseDistance::update()
         )
     );
     cellInterpolationWeight_.transfer(allWeight);
-    cellInterpolationWeight_.correctBoundaryConditions();
+    //cellInterpolationWeight_.correctBoundaryConditions();
+    dynamicOversetFvMesh::correctBoundaryConditions
+    <
+        volScalarField,
+        oversetFvPatchField<scalar>
+    >(cellInterpolationWeight_.boundaryFieldRef(), false);
 
 
     if (debug & 2)
@@ -1024,7 +1030,12 @@ bool Foam::cellCellStencils::trackingInverseDistance::update()
         {
             volTypes[celli] = cellTypes_[celli];
         }
-        volTypes.correctBoundaryConditions();
+        //volTypes.correctBoundaryConditions();
+        dynamicOversetFvMesh::correctBoundaryConditions
+        <
+            volScalarField,
+            oversetFvPatchField<scalar>
+        >(volTypes.boundaryFieldRef(), false);
         volTypes.write();
 
         // Dump stencil
diff --git a/src/overset/dynamicOversetFvMesh/dynamicOversetFvMesh.C b/src/overset/dynamicOversetFvMesh/dynamicOversetFvMesh.C
index a8530dfba10570d7ba0ec1feb916119b3bd855e7..a5491a723fa4ced79581dba95f003b6767e24662 100644
--- a/src/overset/dynamicOversetFvMesh/dynamicOversetFvMesh.C
+++ b/src/overset/dynamicOversetFvMesh/dynamicOversetFvMesh.C
@@ -106,13 +106,14 @@ bool Foam::dynamicOversetFvMesh::updateAddressing() const
     forAll(stencil, celli)
     {
         const labelList& nbrs = stencil[celli];
-        stencilPatches_[celli].setSize(nbrs.size(), -1);
+        stencilPatches_[celli].setSize(nbrs.size());
+        stencilPatches_[celli] = -1;
 
         forAll(nbrs, nbri)
         {
-            const label nbrCelli = nbrs[nbri];
             if (stencilFaces_[celli][nbri] == -1)
             {
+                const label nbrCelli = nbrs[nbri];
                 label globalNbr = globalCellIDs[nbrCelli];
                 label proci = globalNumbering.whichProcID(globalNbr);
                 label remoteCelli = globalNumbering.toLocal(proci, globalNbr);
@@ -164,10 +165,12 @@ bool Foam::dynamicOversetFvMesh::updateAddressing() const
     {
         if (proci < Pstream::myProcNo() && procOwner[proci].size())
         {
-            //Pout<< "Adding interface " << nbri
-            //    << " to receive my " << procOwner[proci]
-            //    << " from " << proci << endl;
-
+            if (debug)
+            {
+                Pout<< "Adding interface " << nbri
+                    << " to receive my " << procOwner[proci].size()
+                    << " from " << proci << endl;
+            }
             procToInterface[proci] = nbri;
             remoteStencilInterfaces_.set
             (
@@ -184,9 +187,12 @@ bool Foam::dynamicOversetFvMesh::updateAddressing() const
         }
         else if (proci > Pstream::myProcNo() && mySendCells[proci].size())
         {
-            //Pout<< "Adding interface " << nbri
-            //    << " to send my " << mySendCells[proci]
-            //    << " to " << proci << endl;
+            if (debug)
+            {
+                Pout<< "Adding interface " << nbri
+                    << " to send my " << mySendCells[proci].size()
+                    << " to " << proci << endl;
+            }
             remoteStencilInterfaces_.set
             (
                 nbri++,
@@ -205,9 +211,12 @@ bool Foam::dynamicOversetFvMesh::updateAddressing() const
     {
         if (proci > Pstream::myProcNo() && procOwner[proci].size())
         {
-            //Pout<< "Adding interface " << nbri
-            //    << " to receive my " << procOwner[proci]
-            //    << " from " << proci << endl;
+            if (debug)
+            {
+                Pout<< "Adding interface " << nbri
+                    << " to receive my " << procOwner[proci].size()
+                    << " from " << proci << endl;
+            }
             procToInterface[proci] = nbri;
             remoteStencilInterfaces_.set
             (
@@ -218,15 +227,18 @@ bool Foam::dynamicOversetFvMesh::updateAddressing() const
                     Pstream::myProcNo(),
                     proci,
                     tensorField(0),
-                    Pstream::msgType()+2
+                    Pstream::msgType()+3
                 )
             );
         }
         else if (proci < Pstream::myProcNo() && mySendCells[proci].size())
         {
-            //Pout<< "Adding interface " << nbri
-            //    << " to send my " << mySendCells[proci]
-            //    << " to " << proci << endl;
+            if (debug)
+            {
+                Pout<< "Adding interface " << nbri
+                    << " to send my " << mySendCells[proci].size()
+                    << " to " << proci << endl;
+            }
             remoteStencilInterfaces_.set
             (
                 nbri++,
@@ -236,7 +248,7 @@ bool Foam::dynamicOversetFvMesh::updateAddressing() const
                     Pstream::myProcNo(),
                     proci,
                     tensorField(0),
-                    Pstream::msgType()+2
+                    Pstream::msgType()+3
                 )
             );
         }
@@ -345,6 +357,71 @@ bool Foam::dynamicOversetFvMesh::updateAddressing() const
 }
 
 
+Foam::scalar Foam::dynamicOversetFvMesh::cellAverage
+(
+    const labelList& types,
+    const labelList& nbrTypes,
+    const scalarField& norm,
+    const scalarField& nbrNorm,
+    const label celli,
+    bitSet& isFront
+) const
+{
+    const labelList& own = faceOwner();
+    const labelList& nei = faceNeighbour();
+    const cell& cFaces = cells()[celli];
+
+    scalar avg = 0.0;
+    label n = 0;
+    label nFront = 0;
+    for (const label facei : cFaces)
+    {
+        if (isInternalFace(facei))
+        {
+            label nbrCelli = (own[facei] == celli ? nei[facei] : own[facei]);
+            if (norm[nbrCelli] == -GREAT)
+            {
+                // Invalid neighbour. Add to front
+                if (isFront.set(facei))
+                {
+                    nFront++;
+                }
+            }
+            else
+            {
+                // Valid neighbour. Add to average
+                avg += norm[nbrCelli];
+                n++;
+            }
+        }
+        else
+        {
+            if (nbrNorm[facei-nInternalFaces()] == -GREAT)
+            {
+                if (isFront.set(facei))
+                {
+                    nFront++;
+                }
+            }
+            else
+            {
+                avg += nbrNorm[facei-nInternalFaces()];
+                n++;
+            }
+        }
+    }
+
+    if (n > 0)
+    {
+        return avg/n;
+    }
+    else
+    {
+        return norm[celli];
+    }
+}
+
+
 void Foam::dynamicOversetFvMesh::writeAgglomeration
 (
     const GAMGAgglomeration& agglom
@@ -363,7 +440,8 @@ void Foam::dynamicOversetFvMesh::writeAgglomeration
                 this->time().timeName(),
                 *this,
                 IOobject::NO_READ,
-                IOobject::AUTO_WRITE
+                IOobject::NO_WRITE,
+                false
             ),
             *this,
             dimensionedScalar(dimless, Zero)
@@ -418,7 +496,8 @@ void Foam::dynamicOversetFvMesh::writeAgglomeration
                     this->time().timeName(),
                     *this,
                     IOobject::NO_READ,
-                    IOobject::AUTO_WRITE
+                    IOobject::NO_WRITE,
+                    false
                 ),
                 *this,
                 dimensionedScalar(dimless, Zero)
@@ -634,28 +713,13 @@ bool Foam::dynamicOversetFvMesh::writeObject
         const labelIOList& zoneID = overlap.zoneID();
         const labelListList& cellStencil = overlap.cellStencil();
 
+        // Get remote zones
         labelList donorZoneID(zoneID);
         overlap.cellInterpolationMap().distribute(donorZoneID);
 
-        forAll(cellStencil, cellI)
-        {
-            const labelList& stencil = cellStencil[cellI];
-            if (stencil.size())
-            {
-                donorZoneID[cellI] = zoneID[stencil[0]];
-                for (label i = 1; i < stencil.size(); i++)
-                {
-                    if (zoneID[stencil[i]] != donorZoneID[cellI])
-                    {
-                        WarningInFunction << "Mixed donor meshes for cell "
-                            << cellI << " at " << C()[cellI]
-                            << " donors:" << UIndirectList<point>(C(), stencil)
-                            << endl;
-                        donorZoneID[cellI] = -2;
-                    }
-                }
-            }
-        }
+        // Get remote cellCentres
+        pointField cc(C());
+        overlap.cellInterpolationMap().distribute(cc);
 
         volScalarField volDonorZoneID
         (
@@ -672,9 +736,25 @@ bool Foam::dynamicOversetFvMesh::writeObject
             dimensionedScalar("minOne", dimless, scalar(-1)),
             zeroGradientFvPatchScalarField::typeName
         );
-        forAll(donorZoneID, celli)
+
+        forAll(cellStencil, cellI)
         {
-            volDonorZoneID[celli] = donorZoneID[celli];
+            const labelList& stencil = cellStencil[cellI];
+            if (stencil.size())
+            {
+                volDonorZoneID[cellI] = donorZoneID[stencil[0]];
+                for (label i = 1; i < stencil.size(); i++)
+                {
+                    if (donorZoneID[stencil[i]] != volDonorZoneID[cellI])
+                    {
+                        WarningInFunction << "Mixed donor meshes for cell "
+                            << cellI << " at " << C()[cellI]
+                            << " donors:" << UIndirectList<point>(cc, stencil)
+                            << endl;
+                        volDonorZoneID[cellI] = -2;
+                    }
+                }
+            }
         }
         //- Do not correctBoundaryConditions since re-interpolates!
         //volDonorZoneID.correctBoundaryConditions();
diff --git a/src/overset/dynamicOversetFvMesh/dynamicOversetFvMesh.H b/src/overset/dynamicOversetFvMesh/dynamicOversetFvMesh.H
index ff499f7142b778e3c6c542f03f1868bce75ed657..d87a7b61f28a33348a408d903f3e8aa12d9f1e82 100644
--- a/src/overset/dynamicOversetFvMesh/dynamicOversetFvMesh.H
+++ b/src/overset/dynamicOversetFvMesh/dynamicOversetFvMesh.H
@@ -128,15 +128,6 @@ protected:
         //template<class GeoField, class PatchType>
         //lduInterfaceFieldPtrsList scalarInterfaces(const GeoField& psi) const;
 
-        //- Correct boundary conditions of certain type (typeOnly = true)
-        //  or explicitly not of the type (typeOnly = false)
-        template<class GeoField, class PatchType>
-        static void correctBoundaryConditions
-        (
-            typename GeoField::Boundary& bfld,
-            const bool typeOnly
-        );
-
         //- Determine normalisation for interpolation. This equals the
         //  original diagonal except stabilised for zero diagonals (possible
         //  in hole cells)
@@ -155,6 +146,17 @@ protected:
         template<class GeoField>
         static void correctCoupledBoundaryConditions(GeoField& fld);
 
+        //- Average norm of valid neighbours
+        scalar cellAverage
+        (
+            const labelList& types,
+            const labelList& nbrTypes,
+            const scalarField& norm,
+            const scalarField& nbrNorm,
+            const label celli,
+            bitSet& isFront
+        ) const;
+
         //- Debug: dump agglomeration
         void writeAgglomeration
         (
@@ -358,6 +360,15 @@ public:
         //- Debug: check halo swap is ok
         template<class GeoField>
         static void checkCoupledBC(const GeoField& fld);
+
+        //- Correct boundary conditions of certain type (typeOnly = true)
+        //  or explicitly not of the type (typeOnly = false)
+        template<class GeoField, class PatchType>
+        static void correctBoundaryConditions
+        (
+            typename GeoField::Boundary& bfld,
+            const bool typeOnly
+        );
 };
 
 
diff --git a/src/overset/dynamicOversetFvMesh/dynamicOversetFvMeshTemplates.C b/src/overset/dynamicOversetFvMesh/dynamicOversetFvMeshTemplates.C
index a875867238e71ce61d84dca317a01c610edc302d..2d54a3cbb654bc71dd2480d00138447276f8f2da 100644
--- a/src/overset/dynamicOversetFvMesh/dynamicOversetFvMeshTemplates.C
+++ b/src/overset/dynamicOversetFvMesh/dynamicOversetFvMeshTemplates.C
@@ -30,6 +30,7 @@ License
 #include "calculatedProcessorFvPatchField.H"
 #include "lduInterfaceFieldPtrsList.H"
 #include "processorFvPatch.H"
+#include "syncTools.H"
 
 // * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * * * //
 
@@ -155,11 +156,10 @@ Foam::tmp<Foam::scalarField> Foam::dynamicOversetFvMesh::normalisation
     tmp<scalarField> tnorm(tmp<scalarField>::New(m.diag()));
     scalarField& norm = tnorm.ref();
 
-    // Add boundary coeffs to duplicate behaviour of fvMatrix
+    // Add boundary coeffs to duplicate behaviour of fvMatrix::addBoundaryDiag
     const FieldField<Field, Type>& internalCoeffs = m.internalCoeffs();
     for (direction cmpt=0; cmpt<pTraits<Type>::nComponents; cmpt++)
     {
-        //m.addBoundaryDiag(norm, cmpt);
         forAll(internalCoeffs, patchi)
         {
             const labelUList& fc = lduAddr().patchAddr(patchi);
@@ -172,19 +172,152 @@ Foam::tmp<Foam::scalarField> Foam::dynamicOversetFvMesh::normalisation
         }
     }
 
-    forAll(norm, celli)
+    // Count number of problematic cells
+    label nZeroDiag = 0;
+    for (const scalar n : norm)
     {
-        scalar& n = norm[celli];
-        if (mag(n) < SMALL)
+        if (magSqr(n) < sqr(SMALL))
         {
-            n = 1.0; //?
+            nZeroDiag++;
         }
-        else
+    }
+
+    reduce(nZeroDiag, sumOp<label>());
+
+    if (debug)
+    {
+        Pout<< "For field " << m.psi().name() << " have zero diagonals for "
+            << nZeroDiag << " cells" << endl;
+    }
+
+    if (nZeroDiag > 0)
+    {
+        // Walk out the norm across hole cells
+
+        const labelList& own = faceOwner();
+        const labelList& nei = faceNeighbour();
+        const cellCellStencilObject& overlap = Stencil::New(*this);
+        const labelUList& types = overlap.cellTypes();
+
+        label nHoles = 0;
+        scalarField extrapolatedNorm(norm);
+        forAll(types, celli)
+        {
+            if (types[celli] == cellCellStencil::HOLE)
+            {
+                extrapolatedNorm[celli] = -GREAT;
+                nHoles++;
+            }
+        }
+
+        bitSet isFront(nFaces());
+        for (label facei = 0; facei < nInternalFaces(); facei++)
+        {
+            label ownType = types[own[facei]];
+            label neiType = types[nei[facei]];
+            if
+            (
+                (ownType == cellCellStencil::HOLE)
+             != (neiType == cellCellStencil::HOLE)
+            )
+            {
+                isFront.set(facei);
+            }
+        }
+        labelList nbrTypes;
+        syncTools::swapBoundaryCellList(*this, types, nbrTypes);
+        for (label facei = nInternalFaces(); facei < nFaces(); facei++)
+        {
+            label ownType = types[own[facei]];
+            label neiType = nbrTypes[facei-nInternalFaces()];
+            if
+            (
+                (ownType == cellCellStencil::HOLE)
+             != (neiType == cellCellStencil::HOLE)
+            )
+            {
+                isFront.set(facei);
+            }
+        }
+
+
+        while (true)
+        {
+            scalarField nbrNorm;
+            syncTools::swapBoundaryCellList(*this, extrapolatedNorm, nbrNorm);
+
+            bitSet newIsFront(nFaces());
+            scalarField newNorm(extrapolatedNorm);
+
+            label nChanged = 0;
+            for (const label facei : isFront)
+            {
+                if (extrapolatedNorm[own[facei]] == -GREAT)
+                {
+                    // Average owner cell, add faces to newFront
+                    newNorm[own[facei]] = cellAverage
+                    (
+                        types,
+                        nbrTypes,
+                        extrapolatedNorm,
+                        nbrNorm,
+                        own[facei],
+                        newIsFront
+                    );
+                    nChanged++;
+                }
+                if
+                (
+                    isInternalFace(facei)
+                 && extrapolatedNorm[nei[facei]] == -GREAT
+                )
+                {
+                    // Average nei cell, add faces to newFront
+                    newNorm[nei[facei]] = cellAverage
+                    (
+                        types,
+                        nbrTypes,
+                        extrapolatedNorm,
+                        nbrNorm,
+                        nei[facei],
+                        newIsFront
+                    );
+                    nChanged++;
+                }
+            }
+
+            reduce(nChanged, sumOp<label>());
+            if (nChanged == 0)
+            {
+                break;
+            }
+
+            // Transfer new front
+            extrapolatedNorm.transfer(newNorm);
+            isFront.transfer(newIsFront);
+            syncTools::syncFaceList(*this, isFront, maxEqOp<unsigned int>());
+        }
+
+
+        forAll(norm, celli)
         {
-            // Restore original diagonal
-            n = m.diag()[celli];
+            scalar& n = norm[celli];
+            if (mag(n) < SMALL)
+            {
+                n = extrapolatedNorm[celli];
+            }
+            else
+            {
+                // Use original diagonal
+                n = m.diag()[celli];
+            }
         }
     }
+    else
+    {
+        // Use original diagonal
+        norm = m.diag();
+    }
     return tnorm;
 }
 
@@ -546,6 +679,38 @@ Foam::SolverPerformance<Type> Foam::dynamicOversetFvMesh::solve
     // Calculate stabilised diagonal as normalisation for interpolation
     const scalarField norm(normalisation(m));
 
+    if (debug)
+    {
+        volScalarField scale
+        (
+            IOobject
+            (
+                m.psi().name() + "_normalisation",
+                this->time().timeName(),
+                *this,
+                IOobject::NO_READ,
+                IOobject::NO_WRITE,
+                false
+            ),
+            *this,
+            dimensionedScalar(dimless, Zero)
+        );
+        scale.ref().field() = norm;
+        correctBoundaryConditions
+        <
+            volScalarField,
+            oversetFvPatchField<scalar>
+        >(scale.boundaryFieldRef(), false);
+        scale.write();
+
+        if (debug)
+        {
+            Pout<< "dynamicOversetFvMesh::solve() :"
+                << " writing matrix normalisation for field " << m.psi().name()
+                << " to " << scale.name() << endl;
+        }
+    }
+
 
     // Switch to extended addressing (requires mesh::update() having been
     // called)
diff --git a/src/parallel/decompose/decompositionMethods/Make/files b/src/parallel/decompose/decompositionMethods/Make/files
index 575366dfaecab4c7d967f0a77cd0ab8d5ef9c5d1..59d3154da7bb9a9a232ed7e6883592a82f5a183d 100644
--- a/src/parallel/decompose/decompositionMethods/Make/files
+++ b/src/parallel/decompose/decompositionMethods/Make/files
@@ -6,6 +6,7 @@ manualDecomp/manualDecomp.C
 multiLevelDecomp/multiLevelDecomp.C
 metisLikeDecomp/metisLikeDecomp.C
 structuredDecomp/structuredDecomp.C
+randomDecomp/randomDecomp.C
 noDecomp/noDecomp.C
 
 
diff --git a/src/parallel/decompose/decompositionMethods/randomDecomp/randomDecomp.C b/src/parallel/decompose/decompositionMethods/randomDecomp/randomDecomp.C
new file mode 100644
index 0000000000000000000000000000000000000000..aa55e77e925d335afb8481e67cd970a8c40582e1
--- /dev/null
+++ b/src/parallel/decompose/decompositionMethods/randomDecomp/randomDecomp.C
@@ -0,0 +1,111 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2019 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 <http://www.gnu.org/licenses/>.
+
+\*---------------------------------------------------------------------------*/
+
+#include "randomDecomp.H"
+#include "Random.H"
+#include "addToRunTimeSelectionTable.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+    defineTypeNameAndDebug(randomDecomp, 0);
+
+    addToRunTimeSelectionTable
+    (
+        decompositionMethod,
+        randomDecomp,
+        dictionary
+    );
+
+    addToRunTimeSelectionTable
+    (
+        decompositionMethod,
+        randomDecomp,
+        dictionaryRegion
+    );
+}
+
+
+// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
+
+Foam::labelList Foam::randomDecomp::decompose(const label nCells) const
+{
+    Random rndGen(0);
+
+    labelList finalDecomp(nCells);
+
+    for (label& val : finalDecomp)
+    {
+        val = rndGen.position<label>(0, nDomains_ - 1);
+    }
+
+    return finalDecomp;
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::randomDecomp::randomDecomp(const dictionary& decompDict)
+:
+    decompositionMethod(decompDict)
+{}
+
+
+Foam::randomDecomp::randomDecomp
+(
+    const dictionary& decompDict,
+    const word& regionName
+)
+:
+    decompositionMethod(decompDict, regionName)
+{}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+Foam::labelList Foam::randomDecomp::decompose
+(
+    const polyMesh& mesh,
+    const pointField&,
+    const scalarField&
+) const
+{
+    return decompose(mesh.nCells());  // or cc.size()
+}
+
+
+Foam::labelList Foam::randomDecomp::decompose
+(
+    const labelListList& globalCellCells,
+    const pointField&,
+    const scalarField&
+) const
+{
+    return decompose(globalCellCells.size());  // or cc.size()
+}
+
+
+// ************************************************************************* //
diff --git a/src/parallel/decompose/decompositionMethods/randomDecomp/randomDecomp.H b/src/parallel/decompose/decompositionMethods/randomDecomp/randomDecomp.H
new file mode 100644
index 0000000000000000000000000000000000000000..69da66ba33b400fe9f39d3bf1a73af027f548a77
--- /dev/null
+++ b/src/parallel/decompose/decompositionMethods/randomDecomp/randomDecomp.H
@@ -0,0 +1,121 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2019 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 <http://www.gnu.org/licenses/>.
+
+Class
+    Foam::randomDecomp
+
+Description
+    Decomposition according to pseudo-random number generator.
+
+SourceFiles
+    randomDecomp.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef randomDecomp_H
+#define randomDecomp_H
+
+#include "decompositionMethod.H"
+
+namespace Foam
+{
+
+/*---------------------------------------------------------------------------*\
+                        Class randomDecomp Declaration
+\*---------------------------------------------------------------------------*/
+
+class randomDecomp
+:
+    public decompositionMethod
+{
+    // Private Member Functions
+
+        //- Random distribution on the 0-nCells interval
+        labelList decompose(const label nCells) const;
+
+        //- No copy construct
+        void operator=(const randomDecomp&) = delete;
+
+        //- No copy assignment
+        randomDecomp(const randomDecomp&) = delete;
+
+
+public:
+
+    //- Runtime type information
+    TypeName("random");
+
+
+    // Constructors
+
+        //- Construct given the decomposition dictionary
+        randomDecomp(const dictionary& decompDict);
+
+        //- Construct for decomposition dictionary and region name
+        randomDecomp
+        (
+            const dictionary& decompDict,
+            const word& regionName
+        );
+
+
+    //- Destructor
+    virtual ~randomDecomp() = default;
+
+
+    // Member Functions
+
+        //- Does not care about proc boundaries
+        virtual bool parallelAware() const
+        {
+            return true;
+        }
+
+        //- Return for every coordinate the wanted processor number.
+        virtual labelList decompose
+        (
+            const polyMesh& mesh,
+            const pointField& cc,
+            const scalarField& cWeights
+        ) const;
+
+        //- Return for every coordinate the wanted processor number.
+        //  Explicitly provided connectivity - does not use mesh_.
+        virtual labelList decompose
+        (
+            const labelListList& globalCellCells,
+            const pointField& cc,
+            const scalarField& cWeights
+        ) const;
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/parallel/distributed/distributedTriSurfaceMesh/distributedTriSurfaceMesh.C b/src/parallel/distributed/distributedTriSurfaceMesh/distributedTriSurfaceMesh.C
index 86379e1752abf53c8ae34b070bfd5e1c3f16398f..ea6c35585debf9ce3b0e70dceb4ec5e17a765cec 100644
--- a/src/parallel/distributed/distributedTriSurfaceMesh/distributedTriSurfaceMesh.C
+++ b/src/parallel/distributed/distributedTriSurfaceMesh/distributedTriSurfaceMesh.C
@@ -303,26 +303,25 @@ bool Foam::distributedTriSurfaceMesh::read()
     }
     else
     {
-        procBb_[Pstream::myProcNo()] =
-            List<treeBoundBox>(dict_.lookup("bounds"));
+        dict_.readEntry("bounds", procBb_[Pstream::myProcNo()]);
         Pstream::gatherList(procBb_);
         Pstream::scatterList(procBb_);
 
         // Wanted distribution type
-        distType_ = distributionTypeNames_.lookup("distributionType", dict_);
+        distType_ = distributionTypeNames_.get("distributionType", dict_);
 
         // Merge distance
-        mergeDist_ = readScalar(dict_.lookup("mergeDistance"));
+        dict_.readEntry("mergeDistance", mergeDist_);
 
         // Distribution type
-        surfaceClosed_ = dict_.lookupOrDefault<bool>("closed", false);
+        surfaceClosed_ = dict_.getOrDefault<bool>("closed", false);
 
-        outsideVolType_ = volumeType::UNKNOWN;
-        word volType;
-        if (dict_.readIfPresent<word>("outsideVolumeType", volType))
-        {
-            outsideVolType_ = volumeType::names[volType];
-        }
+        outsideVolType_ = volumeType::names.getOrDefault
+        (
+            "outsideVolumeType",
+            dict_,
+            volumeType::UNKNOWN
+        );
     }
 
     return true;
@@ -2669,7 +2668,7 @@ Foam::distributedTriSurfaceMesh::distributedTriSurfaceMesh
     // Optionally override settings from provided dictionary
     {
         // Wanted distribution type
-        distType_ = distributionTypeNames_.lookupOrDefault
+        distributionTypeNames_.readIfPresent
         (
             "distributionType",
             dict_,
@@ -2686,7 +2685,7 @@ Foam::distributedTriSurfaceMesh::distributedTriSurfaceMesh
             surfaceClosed_ = closed;
         }
 
-        outsideVolType_ = volumeType::names.lookupOrDefault
+        outsideVolType_ = volumeType::names.getOrDefault
         (
             "outsideVolumeType",
             dict_,
diff --git a/src/randomProcesses/noise/noiseFFT/noiseFFT.C b/src/randomProcesses/noise/noiseFFT/noiseFFT.C
index 856182fa0a53282d096b7b868c28b29c915e1216..7204224dc78cdc37d27a29c0056cb9cdb0ce8a6f 100644
--- a/src/randomProcesses/noise/noiseFFT/noiseFFT.C
+++ b/src/randomProcesses/noise/noiseFFT/noiseFFT.C
@@ -443,8 +443,7 @@ Foam::graph Foam::noiseFFT::PSD(const graph& gPSDf) const
 Foam::graph Foam::noiseFFT::octaves
 (
     const graph& g,
-    const labelUList& freqBandIDs,
-    bool integrate
+    const labelUList& freqBandIDs
 ) const
 {
     if (freqBandIDs.size() < 2)
@@ -478,22 +477,12 @@ Foam::graph Foam::noiseFFT::octaves
 
         if (fb0 == fb1) continue;
 
-        if (integrate)
+        for (label freqI = fb0; freqI < fb1; ++freqI)
         {
-            for (label freqI = fb0; freqI < fb1; ++freqI)
-            {
-                label f0 = f[freqI];
-                label f1 = f[freqI + 1];
-                scalar dataAve = 0.5*(data[freqI] + data[freqI + 1]);
-                octData[bandI] += dataAve*(f1 - f0);
-            }
-        }
-        else
-        {
-            for (label freqI = fb0; freqI < fb1; ++freqI)
-            {
-                octData[bandI] += data[freqI];
-            }
+            label f0 = f[freqI];
+            label f1 = f[freqI + 1];
+            scalar dataAve = 0.5*(data[freqI] + data[freqI + 1]);
+            octData[bandI] += dataAve*(f1 - f0);
         }
     }
 
diff --git a/src/randomProcesses/noise/noiseFFT/noiseFFT.H b/src/randomProcesses/noise/noiseFFT/noiseFFT.H
index 35cecf87f3cb76b1b0ed676af4e72d8965a64132..9c39854ac6e408768d988013d300fec238a40278 100644
--- a/src/randomProcesses/noise/noiseFFT/noiseFFT.H
+++ b/src/randomProcesses/noise/noiseFFT/noiseFFT.H
@@ -177,8 +177,7 @@ public:
         graph octaves
         (
             const graph& g,
-            const labelUList& freqBandIDs,
-            bool integrate
+            const labelUList& freqBandIDs
         ) const;
 
         //- Convert the db into Pa
diff --git a/src/randomProcesses/noise/noiseModels/pointNoise/pointNoise.C b/src/randomProcesses/noise/noiseModels/pointNoise/pointNoise.C
index 3e0c491292d84c6e7712c9f086b732f92645f03f..3eba67f032fc385225390f591c9826f4a1166594 100644
--- a/src/randomProcesses/noise/noiseModels/pointNoise/pointNoise.C
+++ b/src/randomProcesses/noise/noiseModels/pointNoise/pointNoise.C
@@ -183,22 +183,8 @@ void pointNoise::processData
         // 1/3 octave data
         // ---------------
 
-        // PSD [Pa^2/Hz]
-        graph PSD13f(nfft.octaves(PSDf, octave13BandIDs, false));
-
         // Integrated PSD = P(rms)^2 [Pa^2]
-        graph Prms13f2(nfft.octaves(PSDf, octave13BandIDs, true));
-
-        graph PSD13g
-        (
-            "PSD13_dB_Hz(fm)",
-            "fm [Hz]",
-            "PSD(fm) [dB_Hz]",
-            octave13FreqCentre,
-            noiseFFT::PSD(PSD13f.y())
-        );
-        Info<< "    Creating graph for " << PSD13g.title() << endl;
-        PSD13g.write(outDir, graph::wordify(PSD13g.title()), graphFormat_);
+        graph Prms13f(nfft.octaves(PSDf, octave13BandIDs));
 
         graph SPL13g
         (
@@ -206,7 +192,7 @@ void pointNoise::processData
             "fm [Hz]",
             "SPL(fm) [dB]",
             octave13FreqCentre,
-            noiseFFT::SPL(Prms13f2.y())
+            noiseFFT::SPL(Prms13f.y())
         );
         Info<< "    Creating graph for " << SPL13g.title() << endl;
         SPL13g.write(outDir, graph::wordify(SPL13g.title()), graphFormat_);
diff --git a/src/randomProcesses/noise/noiseModels/surfaceNoise/surfaceNoise.C b/src/randomProcesses/noise/noiseModels/surfaceNoise/surfaceNoise.C
index b97622dd4ae65c4500c81849cbfcb4686ba9bca8..b047f00db325c093706bc3f052b104e83dd4ffb6 100644
--- a/src/randomProcesses/noise/noiseModels/surfaceNoise/surfaceNoise.C
+++ b/src/randomProcesses/noise/noiseModels/surfaceNoise/surfaceNoise.C
@@ -536,12 +536,10 @@ void surfaceNoise::calculate()
             bandSize = octave13BandIDs.size() - 1;
         }
 
-        List<scalarField> surfPSD13f(bandSize);
-        List<scalarField> surfPrms13f2(bandSize);
-        forAll(surfPSD13f, freqI)
+        List<scalarField> surfPrms13f(bandSize);
+        forAll(surfPrms13f, freqI)
         {
-            surfPSD13f[freqI].setSize(nLocalFace);
-            surfPrms13f2[freqI].setSize(nLocalFace);
+            surfPrms13f[freqI].setSize(nLocalFace);
         }
 
         const windowModel& win = windowModelPtr_();
@@ -566,17 +564,13 @@ void surfaceNoise::calculate()
                     surfPSDf[i][faceI] = PSDf.y()[freqI];
                 }
 
-                // PSD [Pa^2/Hz]
-                graph PSD13f(nfft.octaves(PSDf, octave13BandIDs, false));
-
                 // Integrated PSD = P(rms)^2 [Pa^2]
-                graph Prms13f2(nfft.octaves(PSDf, octave13BandIDs, true));
+                graph Prms13f(nfft.octaves(PSDf, octave13BandIDs));
 
                 // Store the 1/3 octave results in slot for face of surface
-                forAll(surfPSD13f, freqI)
+                forAll(surfPrms13f, freqI)
                 {
-                    surfPSD13f[freqI][faceI] = PSD13f.y()[freqI];
-                    surfPrms13f2[freqI][faceI] = Prms13f2.y()[freqI];
+                    surfPrms13f[freqI][faceI] = Prms13f.y()[freqI];
                 }
             }
         }
@@ -739,70 +733,35 @@ void surfaceNoise::calculate()
         {
             fileName outDir(outDirBase/"oneThirdOctave");
 
-            scalarField PSDfAve(surfPSD13f.size(), Zero);
-            scalarField Prms13f2Ave(surfPSD13f.size(), Zero);
+            scalarField PSDfAve(surfPrms13f.size(), Zero);
+            scalarField Prms13fAve(surfPrms13f.size(), Zero);
 
-            forAll(surfPSD13f, i)
+            forAll(surfPrms13f, i)
             {
-                PSDfAve[i] = writeSurfaceData
-                (
-                    outDir,
-                    fNameBase,
-                    "PSD13f",
-                    octave13FreqCentre[i],
-                    surfPSD13f[i],
-                    procFaceOffset,
-                    writeOctaves_
-                );
-                writeSurfaceData
-                (
-                    outDir,
-                    fNameBase,
-                    "PSD13",
-                    octave13FreqCentre[i],
-                    noiseFFT::PSD(surfPSD13f[i]),
-                    procFaceOffset,
-                    writeOctaves_
-                );
                 writeSurfaceData
                 (
                     outDir,
                     fNameBase,
                     "SPL13",
                     octave13FreqCentre[i],
-                    noiseFFT::SPL(surfPrms13f2[i]),
+                    noiseFFT::SPL(surfPrms13f[i]),
                     procFaceOffset,
                     writeOctaves_
                 );
 
-                Prms13f2Ave[i] =
-                    surfaceAverage(surfPrms13f2[i], procFaceOffset);
+                Prms13fAve[i] =
+                    surfaceAverage(surfPrms13f[i], procFaceOffset);
             }
 
             if (Pstream::master())
             {
-                graph PSD13g
-                (
-                    "Average PSD13_dB_Hz(fm)",
-                    "fm [Hz]",
-                    "PSD(fm) [dB_Hz]",
-                    octave13FreqCentre,
-                    noiseFFT::PSD(PSDfAve)
-                );
-                PSD13g.write
-                (
-                    outDir,
-                    graph::wordify(PSD13g.title()),
-                    graphFormat_
-                );
-
                 graph SPL13g
                 (
                     "Average SPL13_dB(fm)",
                     "fm [Hz]",
                     "SPL(fm) [dB]",
                     octave13FreqCentre,
-                    noiseFFT::SPL(Prms13f2Ave)
+                    noiseFFT::SPL(Prms13fAve)
                 );
                 SPL13g.write
                 (
diff --git a/src/regionModels/surfaceFilmModels/submodels/kinematic/filmThermoModel/filmThermoModel/filmThermoModelNew.C b/src/regionModels/surfaceFilmModels/submodels/kinematic/filmThermoModel/filmThermoModel/filmThermoModelNew.C
index f311eb4761b4181dfc95b4cf11bf4ab568fa8627..a814b96852882849d7f5e9efca58c8b799c48683 100644
--- a/src/regionModels/surfaceFilmModels/submodels/kinematic/filmThermoModel/filmThermoModel/filmThermoModelNew.C
+++ b/src/regionModels/surfaceFilmModels/submodels/kinematic/filmThermoModel/filmThermoModel/filmThermoModelNew.C
@@ -44,7 +44,7 @@ autoPtr<filmThermoModel> filmThermoModel::New
     const dictionary& dict
 )
 {
-    word modelType(dict.get<word>("filmThermoModel"));
+    const word modelType(dict.get<word>("filmThermoModel"));
 
     Info<< "    Selecting filmThermoModel " << modelType << endl;
 
diff --git a/src/surfMesh/writers/ensight/ensightSurfaceWriterCollated.C b/src/surfMesh/writers/ensight/ensightSurfaceWriterCollated.C
index 727cd66b64086317eea2cf9ed08167188c56bf85..92e8fd31789d29339c16323ee02f9a26cce664e6 100644
--- a/src/surfMesh/writers/ensight/ensightSurfaceWriterCollated.C
+++ b/src/surfMesh/writers/ensight/ensightSurfaceWriterCollated.C
@@ -25,7 +25,42 @@ License
 
 \*---------------------------------------------------------------------------*/
 
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+// Compare time values with tolerance
+static const equalOp<scalar> equalTimes(ROOTSMALL);
+
+// Use ListOps findLower (with tolerance), to find the location of the next
+// time-related index.
+static label findTimeIndex(const UList<scalar>& list, const scalar val)
+{
+    label idx =
+        findLower
+        (
+            list,
+            val,
+            0,
+            [](const scalar a, const scalar b)
+            {
+                return (a < b) && (Foam::mag(b - a) > ROOTSMALL);
+            }
+        );
+
+    if (idx < 0 || !equalTimes(list[idx], val))
+    {
+        ++idx;
+    }
+
+    return idx;
+}
+
+} // End namespace Foam
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
 Foam::fileName Foam::surfaceWriters::ensightWriter::writeCollated()
 {
@@ -119,22 +154,18 @@ Foam::fileName Foam::surfaceWriters::ensightWriter::writeCollated
                     dict.readIfPresent("meshes", meshes);
                     dict.readIfPresent("times", times);
 
-                    timeIndex = 1+findLower(times, timeValue);
+                    timeIndex = findTimeIndex(times, timeValue);
 
                     if (meshChanged)
                     {
                         meshValue = timeValue;
-                        meshIndex = 1+findLower(meshes, meshValue);
+                        meshIndex = findTimeIndex(meshes, meshValue);
                     }
                     else if (meshes.size())
                     {
                         meshIndex = meshes.size()-1;
                         meshValue = meshes.last();
                     }
-                    else
-                    {
-                        meshIndex = 0;
-                    }
                 }
             }
 
@@ -142,11 +173,11 @@ Foam::fileName Foam::surfaceWriters::ensightWriter::writeCollated
             meshes.resize(meshIndex+1, -1);
             times.resize(timeIndex+1, -1);
 
-            if (meshes[meshIndex] != meshValue)
-            {
-                stateChanged = true;
-            }
-            if (times[timeIndex] != timeValue)
+            if
+            (
+                !equalTimes(meshes[meshIndex], meshValue)
+             || !equalTimes(times[timeIndex], timeValue)
+            )
             {
                 stateChanged = true;
             }
diff --git a/src/thermophysicalModels/radiation/submodels/boundaryRadiationProperties/boundaryRadiationPropertiesPatch.C b/src/thermophysicalModels/radiation/submodels/boundaryRadiationProperties/boundaryRadiationPropertiesPatch.C
index 6d1082805540074d91156501d50a9c5c07756dca..e96f92639398ad46567d8c42e165a16ec81bc11f 100644
--- a/src/thermophysicalModels/radiation/submodels/boundaryRadiationProperties/boundaryRadiationPropertiesPatch.C
+++ b/src/thermophysicalModels/radiation/submodels/boundaryRadiationProperties/boundaryRadiationPropertiesPatch.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2015-2018 OpenCFD Ltd.
+    \\  /    A nd           | Copyright (C) 2015-2019 OpenCFD Ltd.
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -51,7 +51,7 @@ Foam::radiation::boundaryRadiationPropertiesPatch::New
     const polyPatch& pp
 )
 {
-    word modelType(dict.lookupCompat("type", {{"mode", 1812}}));
+    const word modelType(dict.getCompat<word>("type", {{"mode", 1812}}));
 
     Info<< "Selecting boundary radiation Model: "
         << modelType << endl;
diff --git a/src/waveModels/derivedPointPatchFields/waveMaker/waveMakerPointPatchVectorField.C b/src/waveModels/derivedPointPatchFields/waveMaker/waveMakerPointPatchVectorField.C
index 6bd34c6ad9b7767f82ad53e11c4b4ed66bb60747..320d70a9547d8f00db3f419b9f52af844e67dca7 100644
--- a/src/waveModels/derivedPointPatchFields/waveMaker/waveMakerPointPatchVectorField.C
+++ b/src/waveModels/derivedPointPatchFields/waveMaker/waveMakerPointPatchVectorField.C
@@ -117,7 +117,7 @@ Foam::waveMakerPointPatchVectorField::waveMakerPointPatchVectorField
 )
 :
     fixedValuePointPatchField<vector>(p, iF, dict, false),
-    motionType_(motionTypeNames.lookup("motionType", dict)),
+    motionType_(motionTypeNames.get("motionType", dict)),
     n_(dict.get<vector>("n")),
     gHat_(Zero),
     initialDepth_(dict.get<scalar>("initialDepth")),
diff --git a/src/waveModels/waveModel/waveModelNew.C b/src/waveModels/waveModel/waveModelNew.C
index 5d452594cbfbd15cbc3db349c16611dcbbde61e2..6c07dc29b778243c6f18d925ea6018da3b157eac 100644
--- a/src/waveModels/waveModel/waveModelNew.C
+++ b/src/waveModels/waveModel/waveModelNew.C
@@ -48,7 +48,7 @@ Foam::autoPtr<Foam::waveModel> Foam::waveModel::New
         )
     );
 
-    word modelType = "none";
+    word modelType("none");
     dictionary patchDict;
     if (waveDict.found(patch.name()))
     {
diff --git a/tutorials/IO/systemCall/system/systemCall b/tutorials/IO/systemCall/system/systemCall
index f8d4debf5c7d628e1d1304c4318b17b060aa5b0e..91a9fe441f368bc325bbeba3c4f581cf73ebfffc 100644
--- a/tutorials/IO/systemCall/system/systemCall
+++ b/tutorials/IO/systemCall/system/systemCall
@@ -3,7 +3,7 @@
 system
 {
     type    systemCall;
-    libs    ("libutilityFunctionObjects.so");
+    libs    ("utilityFunctionObjects");
 
     // Execute on the master process only
     master  true;
diff --git a/tutorials/combustion/fireFoam/LES/compartmentFire/constant/boundaryRadiationProperties b/tutorials/combustion/fireFoam/LES/compartmentFire/constant/boundaryRadiationProperties
index c0d2e8686409b1019af4fbf25e11e2ce004e16bc..57594a617537391e65c308254292b42a6d7e980b 100644
--- a/tutorials/combustion/fireFoam/LES/compartmentFire/constant/boundaryRadiationProperties
+++ b/tutorials/combustion/fireFoam/LES/compartmentFire/constant/boundaryRadiationProperties
@@ -29,5 +29,4 @@ inlet
     absorptivity    0.9;
 }
 
-
 // ************************************************************************* //
diff --git a/tutorials/combustion/fireFoam/LES/flameSpreadWaterSuppressionPanel/constant/boundaryRadiationProperties b/tutorials/combustion/fireFoam/LES/flameSpreadWaterSuppressionPanel/constant/boundaryRadiationProperties
index 59430dda024f6ccf841f6124d16296ce7a2964a5..0d8498890407abddf2e8ea948a2a206cacaa73b6 100644
--- a/tutorials/combustion/fireFoam/LES/flameSpreadWaterSuppressionPanel/constant/boundaryRadiationProperties
+++ b/tutorials/combustion/fireFoam/LES/flameSpreadWaterSuppressionPanel/constant/boundaryRadiationProperties
@@ -15,6 +15,13 @@ FoamFile
 }
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
+".*"
+{
+    type            lookup;
+    emissivity      1.0;
+    absorptivity    1.0;
+    transmissivity  0.0;
+}
 
 region0_to_pyrolysisRegion_coupledWall
 {
@@ -25,13 +32,4 @@ region0_to_pyrolysisRegion_coupledWall
     }
 }
 
-".*"
-{
-    type            lookup;
-    emissivity      1.0;
-    absorptivity    1.0;
-    transmissivity  0.0;
-}
-
-
 // ************************************************************************* //
diff --git a/tutorials/combustion/fireFoam/LES/oppositeBurningPanels/constant/boundaryRadiationProperties b/tutorials/combustion/fireFoam/LES/oppositeBurningPanels/constant/boundaryRadiationProperties
index 397bae330be4d515616c62d2732c287c4527702a..c0cd21bce3c41209ad5ab3129491e795d18785c4 100644
--- a/tutorials/combustion/fireFoam/LES/oppositeBurningPanels/constant/boundaryRadiationProperties
+++ b/tutorials/combustion/fireFoam/LES/oppositeBurningPanels/constant/boundaryRadiationProperties
@@ -15,7 +15,6 @@ FoamFile
 }
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
-
 ".*"
 {
     type            lookup;
@@ -31,5 +30,4 @@ FoamFile
     }
 }
 
-
 // ************************************************************************* //
diff --git a/tutorials/combustion/fireFoam/LES/smallPoolFire2D/constant/boundaryRadiationProperties b/tutorials/combustion/fireFoam/LES/smallPoolFire2D/constant/boundaryRadiationProperties
index 0873938f8c8dba76f0d25694e8e9d626f0d6b6f8..5a0d6c2cc26a96b9cc619b5b2da6241e0d06e72e 100644
--- a/tutorials/combustion/fireFoam/LES/smallPoolFire2D/constant/boundaryRadiationProperties
+++ b/tutorials/combustion/fireFoam/LES/smallPoolFire2D/constant/boundaryRadiationProperties
@@ -39,5 +39,4 @@ inlet
     emissivity      1.0;
 }
 
-
 // ************************************************************************* //
diff --git a/tutorials/combustion/fireFoam/LES/smallPoolFire3D/constant/boundaryRadiationProperties b/tutorials/combustion/fireFoam/LES/smallPoolFire3D/constant/boundaryRadiationProperties
index 3d597f2a67b1dcbe37f5b894165576d7439cc57d..dab7e2979881746903e8ee1e6af48b06ea752c46 100644
--- a/tutorials/combustion/fireFoam/LES/smallPoolFire3D/constant/boundaryRadiationProperties
+++ b/tutorials/combustion/fireFoam/LES/smallPoolFire3D/constant/boundaryRadiationProperties
@@ -21,5 +21,4 @@ FoamFile
     emissivity      1.0;
 }
 
-
 // ************************************************************************* //
diff --git a/tutorials/combustion/reactingFoam/RAS/SandiaD_LTS/constant/boundaryRadiationProperties b/tutorials/combustion/reactingFoam/RAS/SandiaD_LTS/constant/boundaryRadiationProperties
index 76b5b1030b548b40d26b8849703d3921fa99d67e..be4b67e973be237ffa88af0ea05bbdaafd6cf3f1 100644
--- a/tutorials/combustion/reactingFoam/RAS/SandiaD_LTS/constant/boundaryRadiationProperties
+++ b/tutorials/combustion/reactingFoam/RAS/SandiaD_LTS/constant/boundaryRadiationProperties
@@ -17,10 +17,9 @@ FoamFile
 
 ".*"
 {
-    mode            lookup;
+    type            lookup;
     emissivity      1;
     absorptivity    0;
 }
 
-
 // ************************************************************************* //
diff --git a/tutorials/finiteArea/sphereSurfactantFoam/sphereTransport/Allclean b/tutorials/finiteArea/sphereSurfactantFoam/sphereTransport/Allclean
index 9752129998f9807d006d1c05e2408d9e0cfe3442..b1673ba4c14beebd264413db6ade7d30bae841e6 100755
--- a/tutorials/finiteArea/sphereSurfactantFoam/sphereTransport/Allclean
+++ b/tutorials/finiteArea/sphereSurfactantFoam/sphereTransport/Allclean
@@ -4,6 +4,8 @@ cd ${0%/*} || exit 1                        # Run from this directory
 
 cleanTimeDirectories
 
+cleanPostProcessing
+
 cleanFaMesh
 
 rm -rf processor*
diff --git a/tutorials/finiteArea/surfactantFoam/planeTransport/Allclean b/tutorials/finiteArea/surfactantFoam/planeTransport/Allclean
index e9770805391896dd2ae5b3aeddf3c2818d914152..b1673ba4c14beebd264413db6ade7d30bae841e6 100755
--- a/tutorials/finiteArea/surfactantFoam/planeTransport/Allclean
+++ b/tutorials/finiteArea/surfactantFoam/planeTransport/Allclean
@@ -4,6 +4,10 @@ cd ${0%/*} || exit 1                        # Run from this directory
 
 cleanTimeDirectories
 
+cleanPostProcessing
+
 cleanFaMesh
 
+rm -rf processor*
+
 #------------------------------------------------------------------------------
diff --git a/tutorials/finiteArea/surfactantFoam/planeTransport/system/areaWrite b/tutorials/finiteArea/surfactantFoam/planeTransport/system/areaWrite
index 0b7aec7ca74d74b063e1d8470ec54a27488106f6..efcffa063a96ef785ffd92712b54cab95abd439c 100644
--- a/tutorials/finiteArea/surfactantFoam/planeTransport/system/areaWrite
+++ b/tutorials/finiteArea/surfactantFoam/planeTransport/system/areaWrite
@@ -9,6 +9,7 @@ areaWrite
 
     writeControl    writeTime;
     writeInterval   1;
+    // verbose         true;
 
     // Fields to output (words or regex)
     fields  (".*");
diff --git a/tutorials/heatTransfer/buoyantPimpleFoam/thermocoupleTestCase/constant/boundaryRadiationProperties b/tutorials/heatTransfer/buoyantPimpleFoam/thermocoupleTestCase/constant/boundaryRadiationProperties
index c7aace78679c552d4237aa07d9c46c5d900daec9..01ed536a7d85a29969f440b9addb85714283eb50 100644
--- a/tutorials/heatTransfer/buoyantPimpleFoam/thermocoupleTestCase/constant/boundaryRadiationProperties
+++ b/tutorials/heatTransfer/buoyantPimpleFoam/thermocoupleTestCase/constant/boundaryRadiationProperties
@@ -22,5 +22,4 @@ FoamFile
     absorptivity    1.0;
 }
 
-
 // ************************************************************************* //
diff --git a/tutorials/heatTransfer/buoyantSimpleFoam/hotRadiationRoom/constant/boundaryRadiationProperties b/tutorials/heatTransfer/buoyantSimpleFoam/hotRadiationRoom/constant/boundaryRadiationProperties
index c7aace78679c552d4237aa07d9c46c5d900daec9..01ed536a7d85a29969f440b9addb85714283eb50 100644
--- a/tutorials/heatTransfer/buoyantSimpleFoam/hotRadiationRoom/constant/boundaryRadiationProperties
+++ b/tutorials/heatTransfer/buoyantSimpleFoam/hotRadiationRoom/constant/boundaryRadiationProperties
@@ -22,5 +22,4 @@ FoamFile
     absorptivity    1.0;
 }
 
-
 // ************************************************************************* //
diff --git a/tutorials/heatTransfer/buoyantSimpleFoam/hotRadiationRoomFvDOM/constant/boundaryRadiationProperties b/tutorials/heatTransfer/buoyantSimpleFoam/hotRadiationRoomFvDOM/constant/boundaryRadiationProperties
index c7aace78679c552d4237aa07d9c46c5d900daec9..01ed536a7d85a29969f440b9addb85714283eb50 100644
--- a/tutorials/heatTransfer/buoyantSimpleFoam/hotRadiationRoomFvDOM/constant/boundaryRadiationProperties
+++ b/tutorials/heatTransfer/buoyantSimpleFoam/hotRadiationRoomFvDOM/constant/boundaryRadiationProperties
@@ -22,5 +22,4 @@ FoamFile
     absorptivity    1.0;
 }
 
-
 // ************************************************************************* //
diff --git a/tutorials/heatTransfer/buoyantSimpleFoam/simpleCarSolarPanel/constant/boundaryRadiationProperties b/tutorials/heatTransfer/buoyantSimpleFoam/simpleCarSolarPanel/constant/boundaryRadiationProperties
index 0ab2c1e8494e929481f0c4971641e75cdc17f32c..29f0e981c64c27768abf5cb84444a512985bc239 100755
--- a/tutorials/heatTransfer/buoyantSimpleFoam/simpleCarSolarPanel/constant/boundaryRadiationProperties
+++ b/tutorials/heatTransfer/buoyantSimpleFoam/simpleCarSolarPanel/constant/boundaryRadiationProperties
@@ -73,3 +73,5 @@ ZMin
         emissivity      (0.3 0.7);
     };
 }
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionSimpleFoam/multiRegionHeaterRadiation/constant/bottomAir/boundaryRadiationProperties b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/multiRegionHeaterRadiation/constant/bottomAir/boundaryRadiationProperties
index 5886f0d2c477f9572a90ed5746e21476c02d689c..3bffba0aa68b937a9cf9abd41063306488e4b2cd 100644
--- a/tutorials/heatTransfer/chtMultiRegionSimpleFoam/multiRegionHeaterRadiation/constant/bottomAir/boundaryRadiationProperties
+++ b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/multiRegionHeaterRadiation/constant/bottomAir/boundaryRadiationProperties
@@ -15,7 +15,6 @@ FoamFile
 }
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
-
 ".*"
 {
     type            lookup;
diff --git a/tutorials/incompressible/simpleFoam/pipeCyclic/system/controlDict b/tutorials/incompressible/simpleFoam/pipeCyclic/system/controlDict
index 7c7299ea03464c3ca3eb019ff281e2ae0d8fcc63..644a080d011ab4f2f29770c5b711e51f6c54bf1a 100644
--- a/tutorials/incompressible/simpleFoam/pipeCyclic/system/controlDict
+++ b/tutorials/incompressible/simpleFoam/pipeCyclic/system/controlDict
@@ -49,6 +49,7 @@ functions
 {
     #include "coordinateTransform"
     #include "momentum"
+    #include "timeInfo"
 }
 
 
diff --git a/tutorials/incompressible/simpleFoam/pipeCyclic/system/timeInfo b/tutorials/incompressible/simpleFoam/pipeCyclic/system/timeInfo
new file mode 100644
index 0000000000000000000000000000000000000000..ba6558a1aaebd9f1ced62ecc87cfffa0b5b6d0ab
--- /dev/null
+++ b/tutorials/incompressible/simpleFoam/pipeCyclic/system/timeInfo
@@ -0,0 +1,15 @@
+// -*- C++ -*-
+// Record execution/clock time
+time
+{
+    type    timeInfo;
+    libs    ("libutilityFunctionObjects.so");
+    log     true;
+
+    // writeToFile     true;
+
+    perTimeStep     true;
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/incompressible/simpleFoam/windAroundBuildings/system/profiling b/tutorials/incompressible/simpleFoam/windAroundBuildings/system/profiling
index b0865c6bb6653f1a0ba6736091fe2c9e60c77348..f66e2e99ed5304ac1a1b56e4df536e232a0a4a3b 100644
--- a/tutorials/incompressible/simpleFoam/windAroundBuildings/system/profiling
+++ b/tutorials/incompressible/simpleFoam/windAroundBuildings/system/profiling
@@ -12,8 +12,9 @@ profiling
 
     libs  ("libutilityFunctionObjects.so");
 
-    executeControl  none;
-    writeControl    writeTime;
+    // Report stats on exit only (instead of every time step)
+    executeControl  onEnd;
+    writeControl    none;
 }
 
 
diff --git a/tutorials/lagrangian/coalChemistryFoam/simplifiedSiwek/constant/boundaryRadiationProperties b/tutorials/lagrangian/coalChemistryFoam/simplifiedSiwek/constant/boundaryRadiationProperties
index adabddc64188ef6f23cb385dbd62e6e6bf912a39..0760baff80b429384b2b49740fbbfe62b119ad32 100644
--- a/tutorials/lagrangian/coalChemistryFoam/simplifiedSiwek/constant/boundaryRadiationProperties
+++ b/tutorials/lagrangian/coalChemistryFoam/simplifiedSiwek/constant/boundaryRadiationProperties
@@ -15,10 +15,9 @@ FoamFile
 }
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
-
 ".*"
 {
-    mode            lookup;
+    type            lookup;
     emissivity      1.0;
     absorptivity    0.0;
 }
diff --git a/tutorials/multiphase/icoReactingMultiPhaseInterFoam/evaporationMultiComponent/system/fvSchemes b/tutorials/multiphase/icoReactingMultiPhaseInterFoam/evaporationMultiComponent/system/fvSchemes
index c5bf5a5d6880938bde72aa824b258eda28c88b71..3c4a74298db7aff433e4d1f2016834876719ec9b 100644
--- a/tutorials/multiphase/icoReactingMultiPhaseInterFoam/evaporationMultiComponent/system/fvSchemes
+++ b/tutorials/multiphase/icoReactingMultiPhaseInterFoam/evaporationMultiComponent/system/fvSchemes
@@ -27,12 +27,12 @@ gradSchemes
 
 divSchemes
 {
-    div(rhoPhi,U)            Gauss linearUpwind grad(U);
-    "div\(phi,alpha.*\)"      Gauss vanLeer;
-    "div\(phir,alpha.*\)"     Gauss linear;
+    div(rhoPhi,U)           Gauss linearUpwind grad(U);
+    "div\(phi,alpha.*\)"    Gauss vanLeer;
+    "div\(phir,alpha.*\)"   Gauss linear;
 
-    "div\(Yiphir,alpha.*)"   Gauss linear;
-    "div\(phi,.*.gas*\)"     Gauss vanLeer;
+    "div\(Yiphir,alpha.*\)" Gauss linear;
+    "div\(phi,.*\.gas.*\)"  Gauss vanLeer;
 
     div(((rho*nuEff)*dev2(T(grad(U))))) Gauss linear;
 
diff --git a/tutorials/multiphase/icoReactingMultiPhaseInterFoam/inertMultiphaseMultiComponent/system/fvSchemes b/tutorials/multiphase/icoReactingMultiPhaseInterFoam/inertMultiphaseMultiComponent/system/fvSchemes
index 78b069f2db4553d1a25af04d65bf0dd5f3957c08..aa694eed03eed42aaa29a50f4677bc32b3f5de9d 100644
--- a/tutorials/multiphase/icoReactingMultiPhaseInterFoam/inertMultiphaseMultiComponent/system/fvSchemes
+++ b/tutorials/multiphase/icoReactingMultiPhaseInterFoam/inertMultiphaseMultiComponent/system/fvSchemes
@@ -27,18 +27,18 @@ gradSchemes
 
 divSchemes
 {
-    default             none;
+    default         none;
 
-    div(rhoPhi,U)          Gauss linearUpwind gradU;
+    div(rhoPhi,U)           Gauss linearUpwind gradU;
 
-    "div\(phi,alpha.*\)"      Gauss vanLeer;
-    "div\(phir,alpha.*\)"     Gauss linear;
+    "div\(phi,alpha.*\)"        Gauss vanLeer;
+    "div\(phir,alpha.*\)"       Gauss linear;
 
-    "div\(phi,alpha.*\)"     Gauss vanLeer;
-    "div\(Yiphir,alpha.*)"   Gauss vanLeer;
+    "div\(phi,alpha.*\)"        Gauss vanLeer;
+    "div\(Yiphir,alpha.*\)"     Gauss vanLeer;
 
-    "div\(phi,.*.gas*\)"     Gauss vanLeer;
-    "div\(phi,.*.liquid*\)"  Gauss vanLeer;
+    "div\(phi,.*\.gas.*\)"      Gauss vanLeer;
+    "div\(phi,.*\.liquid.*\)"   Gauss vanLeer;
 
     div(((rho*nuEff)*dev2(T(grad(U))))) Gauss linear;
 
diff --git a/tutorials/multiphase/potentialFreeSurfaceDyMFoam/oscillatingBox/system/controlDict b/tutorials/multiphase/potentialFreeSurfaceDyMFoam/oscillatingBox/system/controlDict
index 7c0f55a5292c4c6aa70850cac1bb4c84348612d5..d64a9cf072ab331d8927b0d75836b6f0daf4fe4e 100644
--- a/tutorials/multiphase/potentialFreeSurfaceDyMFoam/oscillatingBox/system/controlDict
+++ b/tutorials/multiphase/potentialFreeSurfaceDyMFoam/oscillatingBox/system/controlDict
@@ -15,6 +15,8 @@ FoamFile
 }
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
+libs            ("libfvMotionSolvers.so");
+
 application     potentialFreeSurfaceDyMFoam;
 
 startFrom       startTime;
diff --git a/wmake/makefiles/files b/wmake/makefiles/files
index 52a0b2db5658a3ce5d5b994baf0a238e8b989e15..fb825976c9343a934ff95f8672bc1d065f4bfbe9 100644
--- a/wmake/makefiles/files
+++ b/wmake/makefiles/files
@@ -35,6 +35,12 @@ SFILES          = $(OBJECTS_DIR)/sourceFiles
 
 sinclude $(OPTIONS)
 
+#------------------------------------------------------------------------------
+# Directory containing the wmake scripts
+#------------------------------------------------------------------------------
+
+WM_SCRIPTS      = $(WM_DIR)/scripts
+
 
 #------------------------------------------------------------------------------
 # Declare dependency of all make system files on FILES
@@ -45,7 +51,9 @@ all : $(OPTIONS) $(SFILES) $(VARS)
 
 $(OPTIONS) : $(MAKE_DIR)/options
 	@$(CPP) $(GFLAGS) $(MAKE_DIR)/options | sed -e 's@   *@ @g' > $(OPTIONS)
-
+ifeq ("$(WM_OSTYPE)","MSwindows")
+	@$(WM_SCRIPTS)/wmakeWindowsDlOpenLibs $(OPTIONS) >> $(OPTIONS)
+endif
 
 $(SFILES): $(MAKE_DIR)/files
 	@$(CPP) $(GFLAGS) $(MAKE_DIR)/files | sed -e 's@   *@ @g' > $(FILES)
diff --git a/wmake/scripts/AllwmakeParseArguments b/wmake/scripts/AllwmakeParseArguments
index abe92d94d0c0f68d645d5da3b9f1f0a02d9dbf6c..ddbf07c0704a7180a5ae0c99ed8f05d5913fd3dc 100644
--- a/wmake/scripts/AllwmakeParseArguments
+++ b/wmake/scripts/AllwmakeParseArguments
@@ -53,7 +53,7 @@ USAGE
 # Parse the arguments and options
 #------------------------------------------------------------------------------
 
-unset fromWmake optLog optQueue
+unset fromWmake optDebug optLog optQueue
 
 for arg in "$@"
 do
@@ -88,8 +88,12 @@ do
         fi
         continue    # Permanently remove arg
         ;;
+    -debug)
+        optDebug="-debug"
+        continue    # Permanently remove arg
+        ;;
     -q | -queue)
-        optQueue="-q"
+        optQueue="-queue"
         continue    # Permanently remove arg
         ;;
     lib | libo | libso | dep | objects)
@@ -116,7 +120,7 @@ then
     else
         echo "Logging wmake -all output to '$optLog'" 1>&2
         echo 1>&2
-        exec wmake -all $optQueue $* 2>&1 | /usr/bin/tee $optLog
+        exec wmake -all $optDebug $optQueue $* 2>&1 | /usr/bin/tee $optLog
         # Need to cleanup after the tee
         rc=$? # Error code from tee (not wmake), but not entirely important
         echo "Done logging to '$optLog'" 1>&2
@@ -139,7 +143,7 @@ fi
 # Cleanup local variables and functions
 #------------------------------------------------------------------------------
 
-unset fromWmake optLog optQueue
+unset fromWmake optDebug optLog optQueue
 unset -f usage
 
 
diff --git a/wmake/scripts/wmakeWindowsDlOpenLibs b/wmake/scripts/wmakeWindowsDlOpenLibs
new file mode 100755
index 0000000000000000000000000000000000000000..44074a80bafe00d9c8ff362eb2f81beab3dc169c
--- /dev/null
+++ b/wmake/scripts/wmakeWindowsDlOpenLibs
@@ -0,0 +1,101 @@
+#!/bin/sh
+#------------------------------------------------------------------------------
+# =========                 |
+# \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+#  \\    /   O peration     |
+#   \\  /    A nd           | Copyright (C) 2019 OpenCFD Ltd.
+#    \\/     M anipulation  |
+#-------------------------------------------------------------------------------
+#                           | Copyright (C) 2011-2017 blueCAPE Lda
+#------------------------------------------------------------------------------
+# 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 <http://www.gnu.org/licenses/>.
+#
+# Script
+#     wmakeWindowsDlOpenLibs
+#
+# Usage
+#     wmakeWindowsDlOpenLibs <build/applications/.../options>
+#
+# Description
+#     Extract library dependencies from the EXE_LIBS entry for Windows
+#     applications and emit as FOAM_DLOPEN_LIBS for use with setRootCase.H
+#     Forcibly dlOpen'ing these libraries ensures that they are truly loaded
+#     for the windows application binary.
+#
+#     An alternative means is to define external entry points into particular
+#     libraries and linking with '-u symbol', which would possibly have a lower
+#     overhead but is more code-intrusive and somewhat ad hoc.
+#
+#------------------------------------------------------------------------------
+optionsFile="$1"
+
+[ "$#" -gt 0 ] || exit 1
+[ -f "$optionsFile" ] || exit 2
+[ -r "$optionsFile" ] || exit 2
+
+# Representative exeName from the build path (for messages only)
+# Eg, build/.../basic/laplacianFoam/options -> laplacianFoam
+
+exeName="${optionsFile%/options}"   # Strip trailing '/options'
+exeName="${exeName##*/}"            # Strip leading path
+
+# Use only OpenFOAM-related libraries that we will can actually find
+hasLib()
+{
+    libFile="lib${1}.dll"   # NB: Windows only (.dll)
+
+    [ -e "$FOAM_LIBBIN/$libFile" ] || \
+    [ -e "$FOAM_USER_LIBBIN/$libFile" ] || \
+    [ -e "$FOAM_LIBBIN/$FOAM_MPI/$libFile" ]
+}
+
+
+# After the cpp stage, the EXE_LIBS (if they exist) will be on a single line
+# Extract EXE_LIBS = -labc ..., ignoring -L and .o entries
+#
+# The libNames output comprises comma-separated quoted strings
+#     "lib1","lib2","libN"
+# these are suitable for C-code or a std::initializer_list<fileName> etc.
+
+# The $() sub-shell is unquoted to ensure we get whitespace splitting
+# and read individual words, not lines.
+unset libNames
+for lib in $(sed -ne 's@^.*EXE\_LIBS.*=[ ]*@@p' "$optionsFile")
+do
+    case "$lib" in
+    (*.o | *')'*)
+        ;;
+
+    (-l[0-9A-Za-z]*)
+        lib="${lib#-l}"
+        hasLib "$lib" && libNames="$libNames${libNames:+,}\"$lib\""
+        ;;
+    esac
+done
+
+## Debugging: echo "$exeName: libNames=$libNames" 1>&2
+
+# Emit define for using with Foam::dlOpen()
+if [ -n "$libNames" ]
+then
+    echo "Adding dlOpen(dll) list for $exeName" 1>&2
+    echo "EXE_INC += -DFOAM_DLOPEN_LIBS='$libNames'"
+fi
+
+exit 0 # clean exit
+
+#------------------------------------------------------------------------------
diff --git a/wmake/wmake b/wmake/wmake
index 65dc6282dca4cb1aaf0f7ce30c659ef10bcdda01..ed6893e4d7ca2e848b96ba8ea7bc2fc1131435cf 100755
--- a/wmake/wmake
+++ b/wmake/wmake
@@ -71,6 +71,7 @@ options:
   -a | -all         wmake all sub-directories, running Allwmake if present
   -q | -queue       wmakeCollect all sub-directories, running Allwmake if present
   -k | -keep-going  Keep going even when errors occur (-non-stop)
+  -debug            Define c++DBUG='-DFULLDEBUG -g -O0' as override
   -j                Compile using all local cores/hyperthreads
   -jN | -j N        Compile using N cores/hyperthreads
   -no-scheduler     Disable scheduled parallel compilation
@@ -83,7 +84,6 @@ options:
   -show-c           Print C compiler value
   -show-cflags      Print C compiler flags
   -show-cxx         Print C++ compiler value
-  -show-cxx-arch    Print C compiler flags
   -show-cxxflags    Print C++ compiler flags
   -show-cflags-arch     The C compiler arch flag (eg, -m64 etc)
   -show-cxxflags-arch   The C++ compiler arch flag (eg, -m64 etc)
@@ -131,7 +131,7 @@ allCores()
 #------------------------------------------------------------------------------
 
 # Default to compiling the local target only
-unset all optShow update optPrintRootDir
+unset all update optDebug optShow optPrintRootDir
 
 while [ "$#" -gt 0 ]
 do
@@ -143,8 +143,11 @@ do
         -s | -silent)
             export WM_QUIET=true
             ;;
+        -debug)
+            optDebug="-DFULLDEBUG -g -O0"
+            ;;
         -show-api | -show-ext-so | \
-        -show-compile-c | -show-c | -show-cflags | -show-cflags-arch | \
+        -show-compile-c   | -show-c   | -show-cflags   | -show-cflags-arch | \
         -show-compile-cxx | -show-cxx | -show-cxxflags | -show-cxxflags-arch )
             $make -f $WM_DIR/makefiles/info "${1#-show-}"
             optShow=true
@@ -348,7 +351,7 @@ if [ "$all" = all ]
 then
     if [ -e Allwmake ]
     then
-        ./Allwmake -fromWmake $targetType
+        ./Allwmake -fromWmake ${optDebug:+-debug} $targetType
         exit $?
     fi
 
@@ -364,6 +367,7 @@ then
         # Compile all applications in sub-directories
         $make ${WM_CONTINUE_ON_ERROR:+-k} \
               -f $WM_DIR/makefiles/apps \
+              ${optDebug:+c++DBUG="$optDebug"} \
               TARGET="$targetType" FOAM_APPS="$FOAM_APPS"
         makeExitCode=$?
     else
@@ -394,7 +398,7 @@ then
         "$WM_SCHEDULER" -clean \
      && wmake -all objects   \
      && "$WM_SCHEDULER"
-    ) && wmake -all
+    ) && wmake -all ${optDebug:+-debug}
     exit $?
 fi
 
@@ -449,11 +453,11 @@ esac
 
     # Pre-build the $WM_OPTIONS/options file
     # which is included when building the $WM_OPTIONS/files file
-    $make -s -f $WM_DIR/makefiles/files MAKE_DIR=$MakeDir \
-          OBJECTS_DIR=$objectsDir $objectsDir/options
+    $make -s -f $WM_DIR/makefiles/files \
+        MAKE_DIR=$MakeDir OBJECTS_DIR=$objectsDir $objectsDir/options
 
-    $make -s -f $WM_DIR/makefiles/files MAKE_DIR=$MakeDir \
-          OBJECTS_DIR=$objectsDir
+    $make -s -f $WM_DIR/makefiles/files \
+        MAKE_DIR=$MakeDir OBJECTS_DIR=$objectsDir
 )
 
 
@@ -477,8 +481,8 @@ case "$targetType" in
 (lib | libo | libso | dep)
     if grep -qe '^ *LIB *=' "$MakeDir/files" 2>/dev/null
     then
-        $make -s -f $WM_DIR/makefiles/general MAKE_DIR=$MakeDir \
-              OBJECTS_DIR=$objectsDir lnInclude
+        $make -s -f $WM_DIR/makefiles/general \
+            MAKE_DIR=$MakeDir OBJECTS_DIR=$objectsDir lnInclude
     fi
     ;;
 esac
@@ -491,8 +495,8 @@ esac
 if [ -n "$WM_UPDATE_DEPENDENCIES" ]
 then
 
-    $make -f $WM_DIR/makefiles/general MAKE_DIR=$MakeDir \
-        OBJECTS_DIR=$objectsDir updatedep
+    $make -f $WM_DIR/makefiles/general \
+        MAKE_DIR=$MakeDir OBJECTS_DIR=$objectsDir updatedep
     makeExitCode=$?
 
     [ $makeExitCode -eq 0 ] || exit $makeExitCode
@@ -503,8 +507,9 @@ fi
 # Make the dependency files or object files and link
 #------------------------------------------------------------------------------
 
-exec $make -f $WM_DIR/makefiles/general MAKE_DIR=$MakeDir \
-     OBJECTS_DIR=$objectsDir $targetType
+exec $make -f $WM_DIR/makefiles/general \
+     ${optDebug:+c++DBUG="$optDebug"} \
+     MAKE_DIR=$MakeDir OBJECTS_DIR=$objectsDir $targetType
 
 exit 0 # clean exit