diff --git a/applications/test/Matrix/Test-Matrix.C b/applications/test/Matrix/Test-Matrix.C
index bf70af621fb6a4a466929bf364a00338eb35aab3..61aaf2d8a35ae0c89c3f9f38a8e7004cf4b183a7 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           | Copyright (C) 2004-2010 OpenCFD Ltd.
+    \\  /    A nd           | Copyright (C) 2004-2010, 2019 OpenCFD Ltd.
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
                             | Copyright (C) 2011-2016 OpenFOAM Foundation
@@ -40,44 +40,82 @@ using namespace Foam;
 
 int main(int argc, char *argv[])
 {
-    SquareMatrix<scalar> hmm(3);
+    // SquareMatrix
+    {
+        Info<< nl << "Test SquareMatrix" << nl;
+
+        SquareMatrix<scalar> square1(3);
+
+        square1(0, 0) = -3.0;
+        square1(0, 1) = 10.0;
+        square1(0, 2) = -4.0;
+        square1(1, 0) = 2.0;
+        square1(1, 1) = 3.0;
+        square1(1, 2) = 10.0;
+        square1(2, 0) = 2.0;
+        square1(2, 1) = 6.0;
+        square1(2, 2) = 1.0;
+
+        Info<< "matrix: " << square1
+            << " begin: " << long(square1.cdata()) << nl;
+
+        //Info<< square1 - 2.0*(-square1) << nl;
+        Info<< "min:" << min(square1) << " max:" << max(square1) << nl;
+        Info<< "min/max: " << minMax(square1) << nl;
+
+        // Steal matrix contents
+
+        List<scalar> stole(square1.release());
+
+        Info<< "matrix: " << square1
+            << " begin: " << long(square1.cdata()) << nl;
+
+        Info<< "List: " << stole << 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<< "min/max: " << minMax(square1) << nl;
 
-    //Info<< hmm << endl << hmm - 2.0*(-hmm) << endl;
-    Info<< max(hmm) << endl;
-    Info<< min(hmm) << endl;
+        square1 = 100;
 
-    SquareMatrix<scalar> hmm2(3, I);
+        Info<< "matrix: " << square1
+            << " begin: " << long(square1.cdata()) << nl;
 
-    hmm = hmm2;
 
-    Info<< hmm << endl;
+        SquareMatrix<scalar> square2(3, I);
 
-    //SquareMatrix<scalar> hmm3(Sin);
+        square1 = square2;
 
-    //Info<< hmm3 << endl;
+        Info<< nl << "After copy assign from Identity:" << nl << square1 << nl;
 
-    SquareMatrix<scalar> hmm4;
+        square1 += 1.25*square2;
 
-    hmm4 = hmm2;
+        Info<< nl << "After +=" << nl << square1 << nl;
 
-    Info<< hmm4 << endl;
+        square1 -= square2.T();
 
-    SquareMatrix<scalar> hmm5;
+        Info<< nl << "After -=" << nl << square1 << nl;
 
-    hmm4 = hmm5;
-    Info<< hmm5 << endl;
+        square1 *= 10;
 
+        Info<< nl << "After *=" << nl << square1 << nl;
+
+        square1 /= 8;
+
+        Info<< nl << "After /=" << nl << square1 << nl;
+
+        SquareMatrix<scalar> square4;
+        square4 = square2;
+
+        Info<< nl << square4 << endl;
+
+        SquareMatrix<scalar> square5;
+        square4 = square5;
+        Info<< nl << square5 << endl;
+    }
+
+    // RectangularMatrix
     {
+        Info<< nl << "Test RectangularMatrix" << nl;
+
         RectangularMatrix<scalar> rm1(5, 6, 3.1);
         rm1(0, 1) = 4.5;
         RectangularMatrix<scalar> rm1b(rm1.block(2, 2, 0, 0));
diff --git a/src/OpenFOAM/matrices/DiagonalMatrix/DiagonalMatrix.C b/src/OpenFOAM/matrices/DiagonalMatrix/DiagonalMatrix.C
index 1a3da1e7e7bfe75d1069e76b70accab35ace156b..99b7b1135993e81cbb19d34734a593633b2b5ec9 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           | Copyright (C) 2004-2010 OpenCFD Ltd.
+    \\  /    A nd           | Copyright (C) 2004-2010, 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 e0474803cb6254763779ccf5e025c2c9c5d82490..c5e56dac95e695182dfb35f307a04e9f736d4fd7 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           | Copyright (C) 2004-2011 OpenCFD Ltd.
+    \\  /    A nd           | Copyright (C) 2004-2011, 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..7798d2ea9dd7d9441be65ea1d998aaab61f0a6eb 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);
             }
@@ -93,11 +93,11 @@ void Foam::LLTMatrix<Type>::decompose(const SquareMatrix<Type>& M)
 template<class Type>
 void Foam::LLTMatrix<Type>::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
+    // If x and source are different, copy initialize x = source
     if (&x != &source)
     {
         x = source;
@@ -106,11 +106,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 +118,31 @@ 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>
 Foam::tmp<Foam::Field<Type>> Foam::LLTMatrix<Type>::solve
 (
-    const Field<Type>& source
+    const UList<Type>& 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..a9f853e41ce43f2884389b18deaab35d21e8b592 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
@@ -58,7 +58,6 @@ class LLTMatrix
 :
     public SquareMatrix<Type>
 {
-
 public:
 
     // Constructors
@@ -66,23 +65,23 @@ 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 returning the solution in the Field 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
-        //  returning the solution
-        tmp<Field<Type>> solve(const Field<Type>& source) const;
+        //- returning the solution
+        tmp<Field<Type>> solve(const UList<Type>& source) const;
 };
 
 
diff --git a/src/OpenFOAM/matrices/LUscalarMatrix/LUscalarMatrix.H b/src/OpenFOAM/matrices/LUscalarMatrix/LUscalarMatrix.H
index 6a666f099fc7991253d544523cb8bb878e9ab7bc..c5fb4c48e46d265cd59481e10ad129dec70ab509 100644
--- a/src/OpenFOAM/matrices/LUscalarMatrix/LUscalarMatrix.H
+++ b/src/OpenFOAM/matrices/LUscalarMatrix/LUscalarMatrix.H
@@ -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 dc5b508d3d919e7b79a8b36585f1830a6fe9f2f0..30124aa7fec3be4ad8b0f39c5688326ff5515dba 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           | Copyright (C) 2004-2010 OpenCFD Ltd.
+    \\  /    A nd           | Copyright (C) 2004-2010, 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 d5d205a9a0dce1b850d0823e9b03f30f8e664912..4b3c44b8ebf1e8d091b766c38f71701435a0fcc9 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           | Copyright (C) 2004-2010 OpenCFD Ltd.
+    \\  /    A nd           | Copyright (C) 2004-2010, 2019 OpenCFD Ltd.
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
                             | Copyright (C) 2011-2017 OpenFOAM Foundation
@@ -26,18 +26,8 @@ License
 \*---------------------------------------------------------------------------*/
 
 #include "Matrix.H"
-
-// * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * * //
-
-template<class Form, class Type>
-void Foam::Matrix<Form, Type>::allocate()
-{
-    if (mRows_ && nCols_)
-    {
-        v_ = new Type[size()];
-    }
-}
-
+#include <functional>
+#include <algorithm>
 
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
@@ -48,14 +38,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 +51,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 +130,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 +152,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 +193,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();
+
+    mRows_ = mat.mRows_;
+    nCols_ = mat.nCols_;
+    v_ = mat.v_;
+
+    mat.mRows_ = 0;
+    mat.nCols_ = 0;
+    mat.v_ = nullptr;
+}
 
-    label minM = min(m, mRows_);
-    label minN = min(n, nCols_);
 
-    for (label i=0; i<minM; i++)
+template<class Form, class Type>
+void Foam::Matrix<Form, Type>::resize(const label m, const label n)
+{
+    if (m == mRows_ && n == nCols_)
+    {
+        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<minN; j++)
+        for (label j=0; j < ncol; ++j)
         {
             newMatrix(i, j) = (*this)(i, j);
         }
@@ -265,14 +264,13 @@ void Foam::Matrix<Form, Type>::setSize(const label m, const label n)
 template<class Form, class Type>
 Form Foam::Matrix<Form, Type>::T() const
 {
-    const Matrix<Form, Type>& A = *this;
     Form At(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) = (*this)(i, j);
         }
     }
 
@@ -283,31 +281,41 @@ Form Foam::Matrix<Form, Type>::T() const
 // * * * * * * * * * * * * * * * 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);
 }
 
 
@@ -318,11 +326,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,130 +343,170 @@ 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 (this == &other)
+    {
+        FatalErrorInFunction
+            << "Attempted addition to self"
+            << abort(FatalError);
+    }
 
-    if (mn)
+    if (m() != other.m() || n() != other.n())
     {
-        label curMaxI = 0;
-        const Type* Mv = M.v();
+        FatalErrorInFunction
+            << "Attempt to add matrices with different sizes: ("
+            << m() << ", " << n() << ") != ("
+            << other.m() << ", " << other.n() << ')' << nl
+            << abort(FatalError);
+    }
+
+    Type* out = this->data();
+    const Type* in = other.cdata();
+
+    const label len = this->size();
+
+    for (label idx=0; idx < len; ++idx)
+    {
+        out[idx] += in[idx];
+    }
+}
 
-        for (label i=1; i<mn; i++)
-        {
-            if (Mv[i] > Mv[curMaxI])
-            {
-                curMaxI = i;
-            }
-        }
 
-        return Mv[curMaxI];
+template<class Form, class Type>
+void Foam::Matrix<Form, Type>::operator-=(const Matrix<Form, Type>& other)
+{
+    if (this == &other)
+    {
+        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);
+    }
+
+    Type* out = this->data();
+    const Type* in = other.cdata();
+
+    const label len = this->size();
 
-        // Return in error to keep compiler happy
-        return M(0, 0);
+    for (label idx=0; idx < len; ++idx)
+    {
+        out[idx] -= in[idx];
     }
 }
 
 
 template<class Form, class Type>
-const Type& Foam::min(const Matrix<Form, Type>& M)
+void Foam::Matrix<Form, Type>::operator*=(const scalar s)
 {
-    const label mn = M.size();
+    for (Type& val : *this)
+    {
+        val *= s;
+    }
+}
+
 
-    if (mn)
+template<class Form, class Type>
+void Foam::Matrix<Form, Type>::operator/=(const scalar s)
+{
+    for (Type& val : *this)
     {
-        label curMinI = 0;
-        const Type* Mv = M.v();
+        val /= s;
+    }
+}
 
-        for (label i=1; i<mn; i++)
-        {
-            if (Mv[i] < Mv[curMinI])
-            {
-                curMinI = i;
-            }
-        }
 
-        return Mv[curMinI];
+// * * * * * * * * * * * * * * * Global Functions  * * * * * * * * * * * * * //
+
+template<class Form, class Type>
+const Type& Foam::max(const Matrix<Form, Type>& mat)
+{
+    if (mat.empty())
+    {
+        FatalErrorInFunction
+            << "Matrix is empty" << abort(FatalError);
     }
-    else
+
+    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
-            << "Matrix is empty"
-            << abort(FatalError);
+            << "Matrix is empty" << abort(FatalError);
+    }
+
+    return *(std::min_element(mat.cbegin(), mat.cend()));
+}
+
+
+template<class Form, class Type>
+Foam::MinMax<Type> Foam::minMax(const Matrix<Form, Type>& mat)
+{
+    MinMax<Type> result;
 
-        // Return in error to keep compiler happy
-        return M(0, 0);
+    for (const Type& val : mat)
+    {
+        result += val;
     }
+
+    return result;
 }
 
 
 // * * * * * * * * * * * * * * * Global Operators  * * * * * * * * * * * * * //
 
 template<class Form, class Type>
-Form Foam::operator-(const Matrix<Form, Type>& M)
+Form Foam::operator-(const Matrix<Form, Type>& mat)
 {
-    Form nM(M.m(), M.n());
-
-    if (M.m() && M.n())
-    {
-        Type* nMv = nM.v();
-        const Type* Mv = M.v();
+    Form result(mat.m(), mat.n());
 
-        const label mn = M.size();
-        for (label i=0; i<mn; i++)
-        {
-            nMv[i] = -Mv[i];
-        }
-    }
+    std::transform
+    (
+        mat.cbegin(),
+        mat.cend(),
+        result.begin(),
+        std::negate<Type>()
+    );
 
-    return nM;
+    return result;
 }
 
 
@@ -468,29 +516,23 @@ Form Foam::operator+(const Matrix<Form, Type>& A, const Matrix<Form, Type>& B)
     if (A.m() != B.m())
     {
         FatalErrorInFunction
-            << "Attempt to add matrices with different numbers of rows: "
-            << A.m() << ", " << B.m()
-            << abort(FatalError);
-    }
-
-    if (A.n() != B.n())
-    {
-        FatalErrorInFunction
-            << "Attempt to add matrices with different numbers of columns: "
-            << A.n() << ", " << B.n()
+            << "Attempt to add matrices with different sizes: ("
+            << A.m() << ", " << A.n() << ") != ("
+            << B.m() << ", " << B.n() << ')' << nl
             << abort(FatalError);
     }
 
     Form AB(A.m(), A.n());
 
-    Type* ABv = AB.v();
-    const Type* Av = A.v();
-    const Type* Bv = B.v();
+    Type* ABv = AB.data();
+    const Type* Av = A.cdata();
+    const Type* Bv = B.cdata();
 
-    const label mn = A.size();
-    for (label i=0; i<mn; i++)
+    const label len = A.size();
+
+    for (label idx=0; idx < len; ++idx)
     {
-        ABv[i] = Av[i] + Bv[i];
+        ABv[idx] = Av[idx] + Bv[idx];
     }
 
     return AB;
@@ -503,29 +545,23 @@ Form Foam::operator-(const Matrix<Form, Type>& A, const Matrix<Form, Type>& B)
     if (A.m() != B.m())
     {
         FatalErrorInFunction
-            << "Attempt to add matrices with different numbers of rows: "
-            << A.m() << ", " << B.m()
-            << abort(FatalError);
-    }
-
-    if (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);
     }
 
     Form AB(A.m(), A.n());
 
-    Type* ABv = AB.v();
-    const Type* Av = A.v();
-    const Type* Bv = B.v();
+    Type* ABv = AB.data();
+    const Type* Av = A.cdata();
+    const Type* Bv = B.cdata();
+
+    const label len = A.size();
 
-    const label mn = A.size();
-    for (label i=0; i<mn; i++)
+    for (label idx=0; idx < len; ++idx)
     {
-        ABv[i] = Av[i] - Bv[i];
+        ABv[idx] = Av[idx] - Bv[idx];
     }
 
     return AB;
@@ -533,65 +569,68 @@ Form Foam::operator-(const Matrix<Form, Type>& A, const Matrix<Form, Type>& B)
 
 
 template<class Form, class Type>
-Form Foam::operator*(const scalar s, const Matrix<Form, Type>& M)
+Form Foam::operator*(const scalar s, const Matrix<Form, Type>& mat)
 {
-    Form sM(M.m(), M.n());
+    Form result(mat.m(), mat.n());
+
+    const label len = mat.size();
 
-    if (M.m() && M.n())
+    if (len)
     {
-        Type* sMv = sM.v();
-        const Type* Mv = M.v();
+        Type* out = result.data();
+        const Type* in = mat.cdata();
 
-        const label mn = M.size();
-        for (label i=0; i<mn; i++)
+        for (label idx=0; idx < len; ++idx)
         {
-            sMv[i] = s*Mv[i];
+            out[idx] = s * in[idx];
         }
     }
 
-    return sM;
+    return result;
 }
 
 
 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 scalar s)
 {
-    Form sM(M.m(), M.n());
+    Form result(mat.m(), mat.n());
 
-    if (M.m() && M.n())
+    const label len = mat.size();
+
+    if (len)
     {
-        Type* sMv = sM.v();
-        const Type* Mv = M.v();
+        Type* out = result.data();
+        const Type* in = mat.cdata();
 
-        const label mn = M.size();
-        for (label i=0; i<mn; i++)
+        for (label idx=0; idx < len; ++idx)
         {
-            sMv[i] = Mv[i]*s;
+            out[idx] = in[idx] * s;
         }
     }
 
-    return sM;
+    return result;
 }
 
 
 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 scalar s)
 {
-    Form sM(M.m(), M.n());
+    Form result(mat.m(), mat.n());
+
+    const label len = mat.size();
 
-    if (M.m() && M.n())
+    if (len)
     {
-        Type* sMv = sM.v();
-        const Type* Mv = M.v();
+        Type* out = result.data();
+        const Type* in = mat.cdata();
 
-        const label mn = M.size();
-        for (label i=0; i<mn; i++)
+        for (label idx=0; idx < len; ++idx)
         {
-            sMv[i] = Mv[i]/s;
+            out[idx] = in[idx] / s;
         }
     }
 
-    return sM;
+    return result;
 }
 
 
@@ -607,10 +646,9 @@ Foam::operator*
     {
         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);
     }
 
@@ -621,13 +659,13 @@ 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 j=0; j < AB.n(); ++j)
         {
-            for (label k=0; k<B.m(); k++)
+            for (label k=0; k < B.m(); ++k)
             {
-                AB(i, j) += A(i, k)*B(k, j);
+                AB(i, j) += A(i, k) * B(k, j);
             }
         }
     }
@@ -639,33 +677,32 @@ Foam::operator*
 template<class Form, class Type>
 inline Foam::tmp<Foam::Field<Type>> Foam::operator*
 (
-    const Matrix<Form, Type>& M,
-    const Field<Type>& f
+    const Matrix<Form, Type>& mat,
+    const Field<Type>& x
 )
 {
-    if (M.n() != f.size())
+    if (mat.n() != x.size())
     {
         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"
+            << "Matrix : (" << mat.m() << ", " << mat.n() << ')' << nl
+            << "Field  : " << x.size() << " rows" << nl
+            << "The number of matrix columns must equal the field size" << nl
             << abort(FatalError);
     }
 
-    tmp<Field<Type>> tMf(new Field<Type>(M.m(), Zero));
-    Field<Type>& Mf = tMf.ref();
+    auto tresult = tmp<Field<Type>>::New(mat.m(), Zero);
+    Field<Type>& result = tresult.ref();
 
-    for (label i=0; i<M.m(); i++)
+    for (label i=0; i < mat.m(); ++i)
     {
-        for (label j=0; j<M.n(); j++)
+        for (label j=0; j < mat.n(); ++j)
         {
-            Mf[i] += M(i, j)*f[j];
+            result[i] += mat(i, j) * x[j];
         }
     }
 
-    return tMf;
+    return tresult;
 }
 
 
diff --git a/src/OpenFOAM/matrices/Matrix/Matrix.H b/src/OpenFOAM/matrices/Matrix/Matrix.H
index 7c67a4b984c616d23588131fbebc479c80304fc9..700a31e523d303b805b2f1b30afdf08238e494d6 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           | Copyright (C) 2004-2010 OpenCFD Ltd.
+    \\  /    A nd           | Copyright (C) 2004-2010, 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,11 +49,8 @@ SourceFiles
 #ifndef Matrix_H
 #define Matrix_H
 
-#include "bool.H"
-#include "label.H"
 #include "uLabel.H"
 #include "Field.H"
-#include "zero.H"
 #include "autoPtr.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@@ -51,27 +58,10 @@ SourceFiles
 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 +71,16 @@ class MatrixBlock;
 template<class Form, class Type>
 class Matrix
 {
-    // Private data
+    // Private Data
 
         //- 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();
+        //- Allocate storage for the contents
+        inline void doAlloc();
 
 
 public:
@@ -105,7 +95,16 @@ 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
@@ -117,30 +116,33 @@ public:
         Matrix(const label m, const label n);
 
         //- Construct with given number of rows and columns
-        //  initializing all elements to zero
+        //- 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&);
+        //- initializing all elements to the given value
+        Matrix(const label m, const label n, 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
         template<class Form2>
-        explicit Matrix(const Matrix<Form2, Type>&);
+        explicit Matrix(const Matrix<Form2, Type>& mat);
 
         //- 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
         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,25 +154,47 @@ 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 true if the matrix is empty (ie, size() is zero)
+        inline bool empty() const noexcept;
 
-            //- Return element vector of the Matrix
-            inline Type* v();
+        //- Return const pointer to the first data element, which can also
+        //- be used to address into the matrix contents
+        inline const Type* cdata() const noexcept;
 
+        //- Return pointer to the first data element, which can also
+        //- be used to address into the matrix contents
+        inline Type* data() noexcept;
 
-        // Block access
+        //- Return const pointer to data in the specified row.
+        //  Subscript checking only with FULLDEBUG
+        inline const Type* rowData(const label irow) const;
+
+        //- Return pointer to data in the specified row.
+        //  Subscript checking only with FULLDEBUG
+        inline Type* rowData(const label irow);
+
+        //- Linear addressing const element access
+        //  Subscript checking only with FULLDEBUG
+        inline const Type& at(const label idx) const;
+
+        //- Linear addressing element access
+        //  Subscript checking only with FULLDEBUG
+        inline Type& at(const label idx);
+
+
+
+    // Block Access
 
             inline ConstMatrixBlock<mType> block
             (
@@ -229,145 +253,246 @@ public:
                 const label nStart
             );
 
+    // Check
+
+        //- Check index i is within valid range (0 ... m-1).
+        inline void checki(const label irow) const;
 
-        // Check
+        //- Check index j is within valid range (0 ... n-1).
+        inline void checkj(const label jcol) const;
 
-            //- Check index i is within valid range (0 ... m-1).
-            inline void checki(const label i) const;
+        //- Check that dimensions are positive, non-zero
+        inline void checkSize() const;
 
-            //- Check index j is within valid range (0 ... n-1).
-            inline void checkj(const label j) const;
+        //- True if all entries have identical values, and matrix is non-empty
+        inline bool uniform() const;
 
 
-        // Edit
+    // Edit
 
-            //- Clear the Matrix, i.e. set sizes to zero.
-            void clear();
+        //- Clear the Matrix, i.e. set sizes to zero.
+        void clear();
 
-            //- Transfer the contents of the argument Matrix into this Matrix
-            //  and annul the argument Matrix.
-            void transfer(mType&);
+        //- Release storage management of the Matrix contents by transferring
+        //- management to a List
+        List<Type> release();
 
-            //- Resize the matrix preserving the elements
-            void setSize(const label m, const label n);
+        //- Swap contents
+        void swap(Matrix<Form, Type>& mat);
 
-            //- Resize the matrix without reallocating storage (unsafe)
-            inline void shallowResize(const label m, const label n);
+        //- Transfer the contents of the argument Matrix into this Matrix
+        //- and annul the argument Matrix.
+        void transfer(Matrix<Form, Type>& mat);
+
+        //- Change the matrix dimensions, preserving the elements
+        void resize(const label m, const label n);
+
+        //- Change the matrix dimensions, preserving the elements
+        inline void setSize(const label m, const label n);
+
+        //- Resize the matrix without reallocating storage (unsafe)
+        inline void shallowResize(const label m, const label n);
 
 
         //- Return the transpose of the matrix
         Form T() const;
 
 
-    // Member operators
+    // Member Operators
 
-        //- Return subscript-checked row of Matrix.
-        inline Type* operator[](const label);
+        //- Return const pointer to data in the specified row - rowData().
+        //  Subscript checking only with FULLDEBUG
+        inline const Type* operator[](const label irow) const;
 
-        //- Return subscript-checked row of constant Matrix.
-        inline const Type* operator[](const label) 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
         template<class MatrixType>
-        void operator=(const ConstMatrixBlock<MatrixType>&);
+        void operator=(const ConstMatrixBlock<MatrixType>& Mb);
 
         //- 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);
+
+        //- Matrix subtraction
+        void operator-=(const Matrix<Form, Type>& other);
+
+        //- Matrix scalar multiplication
+        void operator*=(const scalar s);
 
+        //- Matrix scalar division
+        void operator/=(const scalar s);
 
-    // IOstream operators
 
-        //- Read Matrix from Istream, discarding contents of existing Matrix.
-        friend Istream& operator>> <Form, Type>
-        (
-            Istream&,
-            mType&
-        );
+    // Random access iterator (non-const)
 
-        //- Write Matrix to Ostream.
-        friend Ostream& operator<< <Form, Type>
-        (
-            Ostream&,
-            const mType&
-        );
+        //- Return an iterator to begin traversing a Matrix
+        inline iterator begin();
+
+        //- Return an iterator to end traversing a Matrix
+        inline iterator end();
+
+
+    // 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_;
+        }
 };
 
 
-// Global functions and operators
+// IOstream Operators
 
+//- 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, Operators
+
+//- Find max value in the matrix
+template<class Form, class Type>
+const Type& max(const Matrix<Form, Type>& mat);
+
+//- Find min value in the matrix
+template<class Form, class Type>
+const Type& min(const Matrix<Form, Type>& mat);
+
+//- Find the min/max values of the matrix
+template<class Form, class Type>
+MinMax<Type> minMax(const Matrix<Form, Type>& mat);
+
+//- Matrix negation
 template<class Form, class Type>
-Form operator-(const Matrix<Form, Type>&);
+Form operator-(const Matrix<Form, Type>& mat);
 
+//- Matrix addition
 template<class Form, class Type>
 Form operator+
 (
-    const Matrix<Form, Type>&,
-    const Matrix<Form, Type>&
+    const Matrix<Form, Type>& A,
+    const Matrix<Form, Type>& B
 );
 
+
+//- Matrix subtraction
 template<class Form, class Type>
 Form operator-
 (
-    const Matrix<Form, Type>&,
-    const Matrix<Form, Type>&
+    const Matrix<Form, Type>& A,
+    const Matrix<Form, Type>& B
 );
 
+
+//- Scalar multiplication of a matrix
 template<class Form, class Type>
 Form operator*
 (
-    const scalar,
-    const Matrix<Form, Type>&
+    const scalar s,
+    const Matrix<Form, Type>& mat
 );
 
+
+//- Scalar multiplication of a matrix
 template<class Form, class Type>
 Form operator*
 (
-    const Matrix<Form, Type>&,
-    const scalar
+    const Matrix<Form, Type>& mat,
+    const scalar s
 );
 
+
+//- Scalar division of a matrix
 template<class Form, class Type>
 Form operator/
 (
-    const Matrix<Form, Type>&,
-    const scalar
+    const Matrix<Form, Type>& mat,
+    const scalar s
 );
 
+
+//- Matrix-matrix multiplication
 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
 template<class Form, class Type>
 tmp<Field<Type>> operator*
 (
-    const Matrix<Form, Type>&,
-    const Field<Type>&
+    const Matrix<Form, Type>& mat,
+    const Field<Type>& x
 );
 
 
diff --git a/src/OpenFOAM/matrices/Matrix/MatrixI.H b/src/OpenFOAM/matrices/Matrix/MatrixI.H
index dfef8f70c5938c67c6f570c46304bbefdf2c5614..c264aed42ae5ff7a4d8df1f0d9e88e8c33b7369a 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           | Copyright (C) 2004-2010 OpenCFD Ltd.
+    \\  /    A nd           | Copyright (C) 2004-2010, 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,8 @@ 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::autoPtr<Foam::Matrix<Form, Type>>
+Foam::Matrix<Form, Type>::clone() const
 {
     return autoPtr<Matrix<Form, Type>>::New(*this);
 }
@@ -56,14 +70,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,7 +86,14 @@ 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 bool Foam::Matrix<Form, Type>::empty() const noexcept
+{
+    return !mRows_ || !nCols_;
 }
 
 
@@ -86,7 +107,7 @@ inline void Foam::Matrix<Form, Type>::checki(const label i) const
             << "Attempt to access element from empty matrix"
             << abort(FatalError);
     }
-    else if (i<0 || i>=mRows_)
+    if (i < 0 || i >= mRows_)
     {
         FatalErrorInFunction
             << "Index " << i << " out of range 0 ... " << mRows_-1
@@ -106,7 +127,7 @@ inline void Foam::Matrix<Form, Type>::checkj(const label j) const
             << "Attempt to access element from empty matrix"
             << abort(FatalError);
     }
-    else if (j<0 || j>=nCols_)
+    if (j < 0 || j >= nCols_)
     {
         FatalErrorInFunction
             << "index " << j << " out of range 0 ... " << nCols_-1
@@ -117,19 +138,104 @@ inline void Foam::Matrix<Form, Type>::checkj(const label j) const
 
 
 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 || idx >= this->size())
+    {
+        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 || idx >= this->size())
+    {
+        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
@@ -282,6 +388,13 @@ Foam::Matrix<Form, Type>::col
 }
 
 
+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 +403,97 @@ void Foam::Matrix<Form, Type>::shallowResize(const label m, const label n)
 }
 
 
+// * * * * * * * * * * * * * * * * * 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];
+    checki(irow);
+    checkj(jcol);
+    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];
+    checki(irow);
+    checkj(jcol);
+    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_;
+    checki(irow);
+    return v_ + irow*nCols_;
 }
 
 
 template<class Form, class Type>
-inline Type* Foam::Matrix<Form, Type>::operator[](const label i)
+inline Type* Foam::Matrix<Form, Type>::operator[](const label irow)
 {
-    checki(i);
-    return v_ + i*nCols_;
+    checki(irow);
+    return v_ + irow*nCols_;
 }
 
 
diff --git a/src/OpenFOAM/matrices/Matrix/MatrixIO.C b/src/OpenFOAM/matrices/Matrix/MatrixIO.C
index a39588225d2020d3603c5d616f999d6a82f8e1c8..3f9005c4025c93236a5725c2e396078780d4aaf9 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           | Copyright (C) 2004-2010 OpenCFD Ltd.
+    \\  /    A nd           | Copyright (C) 2004-2010, 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/QRMatrix/QRMatrix.C b/src/OpenFOAM/matrices/QRMatrix/QRMatrix.C
index 75cd80a05271ad148c3a887d6d2d6d4fd50b5b68..1d754b5a198c328b272922ae09779825f0bd1fec 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,9 +158,10 @@ 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();
@@ -189,10 +190,11 @@ void Foam::QRMatrix<MatrixType>::solvex
 template<class MatrixType>
 void Foam::QRMatrix<MatrixType>::solve
 (
-    Field<cmptType>& x,
-    const Field<cmptType>& source
+    List<cmptType>& x,
+    const UList<cmptType>& source
 ) const
 {
+    // Assert (&x != &source) ?
     const label m = Q_.m();
 
     // x = Q_.T()*source;
@@ -213,15 +215,14 @@ template<class MatrixType>
 Foam::tmp<Foam::Field<typename MatrixType::cmptType>>
 Foam::QRMatrix<MatrixType>::solve
 (
-    const Field<cmptType>& source
+    const UList<cmptType>& source
 ) const
 {
-    tmp<Field<cmptType>> tx(new Field<cmptType>(Q_.m()));
-    Field<cmptType>& x = tx.ref();
+    auto tresult(tmp<Field<cmptType>>::New(Q_.m()));
 
-    solve(x, source);
+    solve(tresult.ref(), source);
 
-    return tx;
+    return tresult;
 }
 
 
diff --git a/src/OpenFOAM/matrices/QRMatrix/QRMatrix.H b/src/OpenFOAM/matrices/QRMatrix/QRMatrix.H
index e925967646989300744743fb554185bd8bf5d0a8..b716cd195482b634f824c2285a749cf4411d9230 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,13 @@ 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;
 
 
 public:
@@ -102,14 +103,14 @@ 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 Field 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
+        tmp<Field<cmptType>> solve(const UList<cmptType>& source) const;
 
-        //- Return the inverse of a square matrix
+        //- 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 924615f9eb905eebdf9f2dfa259ecbd94525d201..ae49b677e51d57c4eec8edb09493b923e183a8a2 100644
--- a/src/OpenFOAM/matrices/RectangularMatrix/RectangularMatrix.H
+++ b/src/OpenFOAM/matrices/RectangularMatrix/RectangularMatrix.H
@@ -77,27 +77,30 @@ public:
         inline RectangularMatrix(const MatrixBlock<MatrixType>&);
 
         //- Construct with given number of rows and columns
-        //  initializing all elements to zero
+        //- 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&);
+        //- and value for all elements.
+        inline RectangularMatrix(const label m, const label n, const Type& val);
 
         //- 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 RectangularMatrix(Istream& is);
 
         //- Clone
         inline autoPtr<RectangularMatrix<Type>> clone() const;
 
 
-    // Member operators
+    // Member Operators
 
         //- Assignment of all elements to zero
         void operator=(const zero);
+
+        //- Assignment of all elements to the given value
+        void operator=(const Type& val);
 };
 
 
diff --git a/src/OpenFOAM/matrices/RectangularMatrix/RectangularMatrixI.H b/src/OpenFOAM/matrices/RectangularMatrix/RectangularMatrixI.H
index 6d40febe009df0450fd5c1f06f0c9d7a53552963..f45b3b797803ee4625265b241b29c0dcd74dd105 100644
--- a/src/OpenFOAM/matrices/RectangularMatrix/RectangularMatrixI.H
+++ b/src/OpenFOAM/matrices/RectangularMatrix/RectangularMatrixI.H
@@ -84,20 +84,20 @@ inline Foam::RectangularMatrix<Type>::RectangularMatrix
 (
     const label m,
     const label n,
-    const Type& t
+    const Type& val
 )
 :
-    Matrix<RectangularMatrix<Type>, Type>(m, n, t)
+    Matrix<RectangularMatrix<Type>, Type>(m, n, val)
 {}
 
 
 template<class Type>
 inline Foam::RectangularMatrix<Type>::RectangularMatrix
 (
-    const SquareMatrix<Type>& SM
+    const SquareMatrix<Type>& mat
 )
 :
-    Matrix<RectangularMatrix<Type>, Type>(SM)
+    Matrix<RectangularMatrix<Type>, Type>(mat)
 {}
 
 
@@ -125,6 +125,13 @@ void Foam::RectangularMatrix<Type>::operator=(const zero)
 }
 
 
+template<class Type>
+void Foam::RectangularMatrix<Type>::operator=(const Type& val)
+{
+    Matrix<RectangularMatrix<Type>, Type>::operator=(val);
+}
+
+
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
 namespace Foam
diff --git a/src/OpenFOAM/matrices/SquareMatrix/SquareMatrix.H b/src/OpenFOAM/matrices/SquareMatrix/SquareMatrix.H
index 576f95db793d7cf331c23d6a48a5dea1ab20d7be..f1819a9c9cb46385ddacb248f52b64ef4589a733 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           | Copyright (C) 2004-2010 OpenCFD Ltd.
+    \\  /    A nd           | Copyright (C) 2004-2010, 2019 OpenCFD Ltd.
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
                             | Copyright (C) 2011-2016 OpenFOAM Foundation
@@ -47,10 +47,8 @@ SourceFiles
 namespace Foam
 {
 
-// Forward declaration of friend functions and operators
-
-template<class Type>
-class RectangularMatrix;
+// Forward Declarations
+template<class Type> class RectangularMatrix;
 
 
 /*---------------------------------------------------------------------------*\
@@ -82,23 +80,23 @@ public:
         inline SquareMatrix(const MatrixBlock<MatrixType>&);
 
         //- Construct given number of rows/columns
-        //  initializing all elements to zero
+        //- initializing all elements to zero
         inline SquareMatrix(const label n, const zero);
 
         //- Construct given number of rows and columns (checked to be equal)
-        //  initializing all elements to zero
+        //- 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
+        //- initializing to the identity matrix
         inline SquareMatrix(const label n, const Identity<Type>);
 
         //- Construct with given number of rows and rows
-        //  initializing all elements to the given value
-        inline SquareMatrix(const label n, const Type&);
+        //- initializing all elements to the given value
+        inline SquareMatrix(const label n, const Type& val);
 
         //- Construct as copy of a RectangularMatrix
-        //  which is checked to be square
+        //- which is checked to be square
         inline explicit SquareMatrix(const RectangularMatrix<Type>&);
 
         //- Construct from Istream.
@@ -110,13 +108,16 @@ 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
@@ -124,7 +125,10 @@ public:
         //- Assignment of all elements to zero
         void operator=(const zero);
 
-        //- Assignment elements to the
+        //- Assignment of all elements to the given value
+        void operator=(const Type& val);
+
+        //- Clear and assign diagonal to identity
         void operator=(const Identity<Type>);
 };
 
diff --git a/src/OpenFOAM/matrices/SquareMatrix/SquareMatrixI.H b/src/OpenFOAM/matrices/SquareMatrix/SquareMatrixI.H
index c65f617edb309896f1a0720edef7911170dce38f..97c61c892372a0da020ec6d1010dabb497572ec7 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           | Copyright (C) 2004-2010 OpenCFD Ltd.
+    \\  /    A nd           | Copyright (C) 2004-2010, 2019 OpenCFD Ltd.
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
                             | Copyright (C) 2011-2016 OpenFOAM Foundation
@@ -98,42 +98,42 @@ template<class Type>
 inline Foam::SquareMatrix<Type>::SquareMatrix
 (
     const label n,
-    const Identity<Type>
+    const Type& val
 )
 :
-    Matrix<SquareMatrix<Type>, Type>(n, n, Zero)
-{
-    for (label i=0; i<n; i++)
-    {
-        this->operator()(i, i) = Type(I);
-    }
-}
+    Matrix<SquareMatrix<Type>, Type>(n, n, val)
+{}
 
 
 template<class Type>
 inline Foam::SquareMatrix<Type>::SquareMatrix
 (
     const label n,
-    const Type& t
+    const Identity<Type>
 )
 :
-    Matrix<SquareMatrix<Type>, Type>(n, n, t)
-{}
+    Matrix<SquareMatrix<Type>, Type>(n, n, Zero)
+{
+    for (label i=0; i<n; i++)
+    {
+        this->operator()(i, i) = Type(I);
+    }
+}
 
 
 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())
+    if (mat.m() != mat.n())
     {
         FatalErrorInFunction
             << "Attempt to construct a square matrix from a rectangular matrix "
-            << this->m() << " x " << this->n() << nl
+            << mat.m() << " x " << mat.n() << nl
             << abort(FatalError);
     }
 }
@@ -156,10 +156,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);
 }
 
 
@@ -179,10 +186,18 @@ void Foam::SquareMatrix<Type>::operator=(const zero)
 }
 
 
+template<class Type>
+void Foam::SquareMatrix<Type>::operator=(const Type& val)
+{
+    Matrix<SquareMatrix<Type>, Type>::operator=(val);
+}
+
+
 template<class Type>
 void Foam::SquareMatrix<Type>::operator=(const Identity<Type>)
 {
     Matrix<SquareMatrix<Type>, Type>::operator=(Zero);
+
     for (label i=0; i<this->n(); i++)
     {
         this->operator()(i, i) = Type(I);
diff --git a/src/OpenFOAM/matrices/SymmetricSquareMatrix/SymmetricSquareMatrix.H b/src/OpenFOAM/matrices/SymmetricSquareMatrix/SymmetricSquareMatrix.H
index 267da6b327f5114a270240e7401f85d756b0075f..f4bf7c9c41aaf24574b79b8528877e8f464d9bd7 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
@@ -70,13 +70,13 @@ public:
         //- Construct given number of rows/columns, initializing to zero
         inline SymmetricSquareMatrix(const label n, const zero);
 
+        //- Construct with given number of rows/columns
+        //- initializing all elements to the given value
+        inline SymmetricSquareMatrix(const label n, const Type& val);
+
         //- Construct given number of rows/columns,
         inline SymmetricSquareMatrix(const label n, const Identity<Type>);
 
-        //- Construct with given number of rows/columns
-        //  initializing all elements to the given value
-        inline SymmetricSquareMatrix(const label n, const Type&);
-
         //- Construct from Istream.
         inline SymmetricSquareMatrix(Istream&);
 
@@ -85,7 +85,7 @@ public:
 };
 
 
-// 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..a2f8dc01092d2bc367084a4f1f90c581350faedf 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
@@ -56,27 +56,27 @@ 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>
 inline Foam::SymmetricSquareMatrix<Type>::SymmetricSquareMatrix
 (
     const label n,
-    const Type& t
+    const Identity<Type>
 )
 :
-    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>