diff --git a/src/OpenFOAM/matrices/LUscalarMatrix/LUscalarMatrix.C b/src/OpenFOAM/matrices/LUscalarMatrix/LUscalarMatrix.C
index 2d03159abe84e52446523856553a3511829a29c6..1c401c232b7aa646b212c272dbd3bf54e49f9e66 100644
--- a/src/OpenFOAM/matrices/LUscalarMatrix/LUscalarMatrix.C
+++ b/src/OpenFOAM/matrices/LUscalarMatrix/LUscalarMatrix.C
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2017 OpenFOAM Foundation
-    Copyright (C) 2020 OpenCFD Ltd.
+    Copyright (C) 2020-2024 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -42,17 +42,16 @@ namespace Foam
 
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
-Foam::LUscalarMatrix::LUscalarMatrix()
+Foam::LUscalarMatrix::LUscalarMatrix() noexcept
 :
     comm_(UPstream::worldComm)
 {}
 
 
-Foam::LUscalarMatrix::LUscalarMatrix(const scalarSquareMatrix& matrix)
+Foam::LUscalarMatrix::LUscalarMatrix(const scalarSquareMatrix& mat)
 :
-    scalarSquareMatrix(matrix),
-    comm_(UPstream::worldComm),
-    pivotIndices_(m())
+    scalarSquareMatrix(mat),
+    comm_(UPstream::worldComm)
 {
     LUDecompose(*this, pivotIndices_);
 }
@@ -69,13 +68,14 @@ Foam::LUscalarMatrix::LUscalarMatrix
 {
     if (UPstream::parRun())
     {
-        PtrList<procLduMatrix> lduMatrices(UPstream::nProcs(comm_));
-
-        label lduMatrixi = 0;
+        PtrList<procLduMatrix> lduMatrices
+        (
+            UPstream::master(comm_) ? UPstream::nProcs(comm_) : 1
+        );
 
         lduMatrices.set
         (
-            lduMatrixi++,
+            0,  // rank-local matrix (and/or master)
             new procLduMatrix
             (
                 ldum,
@@ -88,101 +88,66 @@ Foam::LUscalarMatrix::LUscalarMatrix
         {
             for (const int proci : UPstream::subProcs(comm_))
             {
-                lduMatrices.set
-                (
-                    lduMatrixi++,
-                    new procLduMatrix
-                    (
-                        IPstream
-                        (
-                            UPstream::commsTypes::scheduled,
-                            proci,
-                            0,          // bufSize
-                            UPstream::msgType(),
-                            comm_
-                        )()
-                    )
-                );
+                auto& mat = lduMatrices.emplace_set(proci);
+
+                IPstream::recv(mat, proci, UPstream::msgType(), comm_);
             }
+
+            convert(lduMatrices);
         }
         else
         {
-            OPstream toMaster
+            OPstream::send
             (
-                UPstream::commsTypes::scheduled,
+                lduMatrices[0],  // rank-local matrix
                 UPstream::masterNo(),
-                0,              // bufSize
                 UPstream::msgType(),
                 comm_
             );
-            procLduMatrix cldum
-            (
-                ldum,
-                interfaceCoeffs,
-                interfaces
-            );
-            toMaster<< cldum;
-
-        }
-
-        if (UPstream::master(comm_))
-        {
-            label nCells = 0;
-            forAll(lduMatrices, i)
-            {
-                nCells += lduMatrices[i].size();
-            }
-
-            scalarSquareMatrix m(nCells, 0.0);
-            transfer(m);
-            convert(lduMatrices);
         }
     }
     else
     {
-        label nCells = ldum.lduAddr().size();
-        scalarSquareMatrix m(nCells, Zero);
-        transfer(m);
         convert(ldum, interfaceCoeffs, interfaces);
     }
 
-    if (UPstream::master(comm_))
+
+    if (debug && UPstream::master(comm_))
     {
-        if (debug)
-        {
-            const label numRows = m();
-            const label numCols = n();
+        const label numRows = nRows();
+        const label numCols = nCols();
 
-            Pout<< "LUscalarMatrix : size:" << numRows << endl;
-            for (label rowi = 0; rowi < numRows; ++rowi)
-            {
-                const scalar* row = operator[](rowi);
+        Pout<< "LUscalarMatrix : size:" << numRows << endl;
+        for (label rowi = 0; rowi < numRows; ++rowi)
+        {
+            const scalar* row = operator[](rowi);
 
-                Pout<< "cell:" << rowi << " diagCoeff:" << row[rowi] << endl;
+            Pout<< "cell:" << rowi << " diagCoeff:" << row[rowi] << nl;
 
-                Pout<< "    connects to upper cells :";
-                for (label coli = rowi+1; coli < numCols; ++coli)
+            Pout<< "    connects to upper cells :";
+            for (label coli = rowi+1; coli < numCols; ++coli)
+            {
+                if (mag(row[coli]) > SMALL)
                 {
-                    if (mag(row[coli]) > SMALL)
-                    {
-                        Pout<< ' ' << coli << " (coeff:" << row[coli] << ')';
-                    }
+                    Pout<< ' ' << coli << " (coeff:" << row[coli] << ')';
                 }
-                Pout<< endl;
-                Pout<< "    connects to lower cells :";
-                for (label coli = 0; coli < rowi; ++coli)
+            }
+            Pout<< nl;
+            Pout<< "    connects to lower cells :";
+            for (label coli = 0; coli < rowi; ++coli)
+            {
+                if (mag(row[coli]) > SMALL)
                 {
-                    if (mag(row[coli]) > SMALL)
-                    {
-                        Pout<< ' ' << coli << " (coeff:" << row[coli] << ')';
-                    }
+                    Pout<< ' ' << coli << " (coeff:" << row[coli] << ')';
                 }
-                Pout<< nl;
             }
             Pout<< nl;
         }
+        Pout<< endl;
+    }
 
-        pivotIndices_.setSize(m());
+    if (UPstream::master(comm_))
+    {
         LUDecompose(*this, pivotIndices_);
     }
 }
@@ -197,6 +162,10 @@ void Foam::LUscalarMatrix::convert
     const lduInterfaceFieldPtrsList& interfaces
 )
 {
+    // Resize and fill with zero
+    scalarSquareMatrix::resize_nocopy(ldum.lduAddr().size());
+    scalarSquareMatrix::operator=(Foam::zero{});
+
     const label* __restrict__ uPtr = ldum.lduAddr().upperAddr().begin();
     const label* __restrict__ lPtr = ldum.lduAddr().lowerAddr().begin();
 
@@ -259,14 +228,26 @@ void Foam::LUscalarMatrix::convert
     const PtrList<procLduMatrix>& lduMatrices
 )
 {
-    procOffsets_.setSize(lduMatrices.size() + 1);
-    procOffsets_[0] = 0;
+    procOffsets_.resize_nocopy(lduMatrices.size() + 1);
 
-    forAll(lduMatrices, ldumi)
     {
-        procOffsets_[ldumi+1] = procOffsets_[ldumi] + lduMatrices[ldumi].size();
+        auto iter = procOffsets_.begin();
+
+        label nCellsTotal = 0;
+        *iter++ = nCellsTotal;
+
+        for (const auto& mat : lduMatrices)
+        {
+            nCellsTotal += mat.size();
+            *iter++ = nCellsTotal;
+        }
+
+        // Resize and fill with zero
+        scalarSquareMatrix::resize_nocopy(nCellsTotal);
+        scalarSquareMatrix::operator=(Foam::zero{});
     }
 
+
     forAll(lduMatrices, ldumi)
     {
         const procLduMatrix& lduMatrixi = lduMatrices[ldumi];
@@ -400,10 +381,9 @@ void Foam::LUscalarMatrix::printDiagonalDominance() const
 }
 
 
-void Foam::LUscalarMatrix::decompose(const scalarSquareMatrix& M)
+void Foam::LUscalarMatrix::decompose(const scalarSquareMatrix& mat)
 {
-    scalarSquareMatrix::operator=(M);
-    pivotIndices_.setSize(m());
+    scalarSquareMatrix::operator=(mat);
     LUDecompose(*this, pivotIndices_);
 }
 
diff --git a/src/OpenFOAM/matrices/LUscalarMatrix/LUscalarMatrix.H b/src/OpenFOAM/matrices/LUscalarMatrix/LUscalarMatrix.H
index ada33620bee9e3da7fc7bf0c9308dec474e25c2f..682ec7e6cdfe4869867bd373264f236144c28f8a 100644
--- a/src/OpenFOAM/matrices/LUscalarMatrix/LUscalarMatrix.H
+++ b/src/OpenFOAM/matrices/LUscalarMatrix/LUscalarMatrix.H
@@ -34,8 +34,8 @@ SourceFiles
 
 \*---------------------------------------------------------------------------*/
 
-#ifndef LUscalarMatrix_H
-#define LUscalarMatrix_H
+#ifndef Foam_LUscalarMatrix_H
+#define Foam_LUscalarMatrix_H
 
 #include "scalarMatrices.H"
 #include "labelList.H"
@@ -47,6 +47,7 @@ SourceFiles
 namespace Foam
 {
 
+// Forward Declarations
 class lduMatrix;
 class procLduMatrix;
 
@@ -58,7 +59,7 @@ class LUscalarMatrix
 :
     public scalarSquareMatrix
 {
-    // Private data
+    // Private Data
 
         //- Communicator to use
         const label comm_;
@@ -70,7 +71,7 @@ class LUscalarMatrix
         labelList pivotIndices_;
 
 
-    // Private member functions
+    // Private Member Functions
 
         //- Convert the given lduMatrix into this LUscalarMatrix
         void convert
@@ -81,12 +82,12 @@ class LUscalarMatrix
         );
 
         //- Convert the given list of procLduMatrix into this LUscalarMatrix
-        //  on the master processor
+        //- on the master processor
         void convert(const PtrList<procLduMatrix>& lduMatrices);
 
 
         //- Print the ratio of the mag-sum of the off-diagonal coefficients
-        //  to the mag-diagonal
+        //- to the mag-diagonal
         void printDiagonalDominance() const;
 
 
@@ -98,13 +99,14 @@ public:
 
     // Constructors
 
-        //- Construct null
-        LUscalarMatrix();
+        //- Default construct
+        LUscalarMatrix() noexcept;
 
-        //- Construct from and perform LU decomposition of the matrix M
-        LUscalarMatrix(const scalarSquareMatrix& M);
+        //- Construct from and perform LU decomposition of the given matrix
+        explicit LUscalarMatrix(const scalarSquareMatrix& mat);
 
-        //- Construct from lduMatrix and perform LU decomposition
+        //- Construct from lduMatrix and perform LU decomposition.
+        //- In parallel it assembles the matrix on the master.
         LUscalarMatrix
         (
             const lduMatrix& ldum,
@@ -115,8 +117,8 @@ public:
 
     // Member Functions
 
-        //- Perform the LU decomposition of the matrix M
-        void decompose(const scalarSquareMatrix& M);
+        //- Perform the LU decomposition of the matrix
+        void decompose(const scalarSquareMatrix& mat);
 
         //- Solve the linear system with the given source
         //  and returning the solution in the Field argument x.
diff --git a/src/OpenFOAM/matrices/LUscalarMatrix/LUscalarMatrixTemplates.C b/src/OpenFOAM/matrices/LUscalarMatrix/LUscalarMatrixTemplates.C
index 568275e54c8ae398a3ef56dddff9ed1a336fbb75..9113a8a1243255d3822b52c091c8f71f0ea70b8c 100644
--- a/src/OpenFOAM/matrices/LUscalarMatrix/LUscalarMatrixTemplates.C
+++ b/src/OpenFOAM/matrices/LUscalarMatrix/LUscalarMatrixTemplates.C
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2017 OpenFOAM Foundation
-    Copyright (C) 2019-2020 OpenCFD Ltd.
+    Copyright (C) 2019-2024 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -44,79 +44,141 @@ void Foam::LUscalarMatrix::solve
         x = source;
     }
 
-    if (Pstream::parRun())
+    const auto tag = UPstream::msgType();
+
+    if (UPstream::parRun())
     {
-        List<Type> X; // scratch space (on master)
+        List<Type> allx;  // scratch space (on master)
+
+        const label startOfRequests = UPstream::nRequests();
 
-        if (Pstream::master(comm_))
+        // Like globalIndex::gather()
+        if (UPstream::master(comm_))
         {
-            X.resize(m());
+            allx.resize(m());
 
-            SubList<Type>(X, x.size()) = x;
+            SubList<Type>(allx, x.size()) = x;
 
-            for (const int proci : Pstream::subProcs(comm_))
+            for (const int proci : UPstream::subProcs(comm_))
             {
-                UIPstream::read
+                SubList<Type> procSlot
                 (
-                    Pstream::commsTypes::scheduled,
-                    proci,
-                    reinterpret_cast<char*>
-                    (
-                        &(X[procOffsets_[proci]])
-                    ),
-                    (procOffsets_[proci+1]-procOffsets_[proci])*sizeof(Type),
-                    Pstream::msgType(),
-                    comm_
+                    allx,
+                    procOffsets_[proci+1]-procOffsets_[proci],
+                    procOffsets_[proci]
                 );
+
+                if (procSlot.empty())
+                {
+                    // Nothing to do
+                }
+                else if (is_contiguous<Type>::value)
+                {
+                    UIPstream::read
+                    (
+                        UPstream::commsTypes::nonBlocking,
+                        proci,
+                        procSlot.data_bytes(),
+                        procSlot.size_bytes(),
+                        tag,
+                        comm_
+                    );
+                }
+                else
+                {
+                    IPstream::recv(procSlot, proci, tag, comm_);
+                }
             }
         }
         else
         {
-            UOPstream::write
-            (
-                Pstream::commsTypes::scheduled,
-                Pstream::masterNo(),
-                x.cdata_bytes(),
-                x.byteSize(),
-                Pstream::msgType(),
-                comm_
-            );
+            if (x.empty())
+            {
+                // Nothing to do
+            }
+            else if (is_contiguous<Type>::value)
+            {
+                UOPstream::write
+                (
+                    UPstream::commsTypes::nonBlocking,
+                    UPstream::masterNo(),
+                    x.cdata_bytes(),
+                    x.size_bytes(),
+                    tag,
+                    comm_
+                );
+            }
+            else
+            {
+                OPstream::send(x, UPstream::masterNo(), tag, comm_);
+            }
         }
 
-        if (Pstream::master(comm_))
+        UPstream::waitRequests(startOfRequests);
+
+        // LUBacksubstitute and then like globalIndex::scatter()
+        if (UPstream::master(comm_))
         {
-            LUBacksubstitute(*this, pivotIndices_, X);
+            LUBacksubstitute(*this, pivotIndices_, allx);
 
-            x = SubList<Type>(X, x.size());
+            x = SubList<Type>(allx, x.size());
 
-            for (const int proci : Pstream::subProcs(comm_))
+            for (const int proci : UPstream::subProcs(comm_))
             {
-                UOPstream::write
+                SubList<Type> procSlot
                 (
-                    Pstream::commsTypes::scheduled,
-                    proci,
-                    reinterpret_cast<const char*>
-                    (
-                        &(X[procOffsets_[proci]])
-                    ),
-                    (procOffsets_[proci+1]-procOffsets_[proci])*sizeof(Type),
-                    Pstream::msgType(),
-                    comm_
+                    allx,
+                    procOffsets_[proci+1]-procOffsets_[proci],
+                    procOffsets_[proci]
                 );
+
+                if (procSlot.empty())
+                {
+                    // Nothing to do
+                }
+                else if (is_contiguous<Type>::value)
+                {
+                    UOPstream::write
+                    (
+                        UPstream::commsTypes::nonBlocking,
+                        proci,
+                        procSlot.cdata_bytes(),
+                        procSlot.size_bytes(),
+                        tag,
+                        comm_
+                    );
+                }
+                else
+                {
+                    OPstream::send(procSlot, proci, tag, comm_);
+                }
             }
         }
         else
         {
-            UIPstream::read
-            (
-                Pstream::commsTypes::scheduled,
-                Pstream::masterNo(),
-                x.data_bytes(),
-                x.byteSize(),
-                Pstream::msgType(),
-                comm_
-            );
+            if (x.empty())
+            {
+                // Nothing to do
+            }
+            else if (is_contiguous<Type>::value)
+            {
+                UIPstream::read
+                (
+                    UPstream::commsTypes::nonBlocking,
+                    UPstream::masterNo(),
+                    x.data_bytes(),
+                    x.size_bytes(),
+                    tag,
+                    comm_
+                );
+            }
+            else
+            {
+                IPstream::recv(x, UPstream::masterNo(), tag, comm_);
+            }
         }
+
+        UPstream::waitRequests(startOfRequests);
     }
     else
     {
@@ -131,7 +193,7 @@ Foam::tmp<Foam::Field<Type>> Foam::LUscalarMatrix::solve
     const UList<Type>& source
 ) const
 {
-    auto tx(tmp<Field<Type>>::New(m()));
+    auto tx = tmp<Field<Type>>::New(m());
 
     solve(tx.ref(), source);
 
diff --git a/src/OpenFOAM/matrices/LUscalarMatrix/procLduInterface.C b/src/OpenFOAM/matrices/LUscalarMatrix/procLduInterface.C
index 02309fbab5851ba5091b9c1d7a8d0ed7ca2f5532..6680dca7f1d0a54cc200b6a2b3cd77e2fc5dd3b3 100644
--- a/src/OpenFOAM/matrices/LUscalarMatrix/procLduInterface.C
+++ b/src/OpenFOAM/matrices/LUscalarMatrix/procLduInterface.C
@@ -6,6 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2015 OpenFOAM Foundation
+    Copyright (C) 2024 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -69,27 +70,47 @@ Foam::procLduInterface::procLduInterface
 
 
 Foam::procLduInterface::procLduInterface(Istream& is)
-:
-    faceCells_(is),
-    coeffs_(is),
-    myProcNo_(readLabel(is)),
-    neighbProcNo_(readLabel(is)),
-    tag_(readLabel(is)),
-    comm_(readLabel(is))
-{}
+{
+    read(is);
+}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+void Foam::procLduInterface::read(Istream& is)
+{
+    is  >> faceCells_
+        >> coeffs_
+        >> myProcNo_
+        >> neighbProcNo_
+        >> tag_
+        >> comm_;
+}
+
+
+void Foam::procLduInterface::write(Ostream& os) const
+{
+    os  << faceCells_
+        << coeffs_
+        << myProcNo_
+        << neighbProcNo_
+        << tag_
+        << comm_;
+}
 
 
 // * * * * * * * * * * * * * * * IOstream Operators  * * * * * * * * * * * * //
 
-Foam::Ostream& Foam::operator<<(Ostream& os, const procLduInterface& cldui)
+Foam::Istream& Foam::operator>>(Istream& is, procLduInterface& intf)
 {
-    os  << cldui.faceCells_
-        << cldui.coeffs_
-        << cldui.myProcNo_
-        << cldui.neighbProcNo_
-        << cldui.tag_
-        << cldui.comm_;
+    intf.read(is);
+    return is;
+}
+
 
+Foam::Ostream& Foam::operator<<(Ostream& os, const procLduInterface& intf)
+{
+    intf.write(os);
     return os;
 }
 
diff --git a/src/OpenFOAM/matrices/LUscalarMatrix/procLduInterface.H b/src/OpenFOAM/matrices/LUscalarMatrix/procLduInterface.H
index c0e74aeb978aea8361822a01ccaba75b77ab9203..22f1582bc21e9e09ca128ea5c8ab7072ae1b5547 100644
--- a/src/OpenFOAM/matrices/LUscalarMatrix/procLduInterface.H
+++ b/src/OpenFOAM/matrices/LUscalarMatrix/procLduInterface.H
@@ -6,6 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2016 OpenFOAM Foundation
+    Copyright (C) 2024 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -49,10 +50,11 @@ namespace Foam
 class lduInterfaceField;
 class procLduInterface;
 
+Istream& operator>>(Istream&, procLduInterface&);
 Ostream& operator<<(Ostream&, const procLduInterface&);
 
 /*---------------------------------------------------------------------------*\
-                           Class procLduInterface Declaration
+                      Class procLduInterface Declaration
 \*---------------------------------------------------------------------------*/
 
 class procLduInterface
@@ -68,6 +70,7 @@ class procLduInterface
 
 public:
 
+    //- Friendship
     friend class LUscalarMatrix;
 
 
@@ -85,7 +88,8 @@ public:
             const scalarField& coeffs
         );
 
-        procLduInterface(Istream& is);
+        //- Read construct from Istream
+        explicit procLduInterface(Istream& is);
 
         autoPtr<procLduInterface> clone()
         {
@@ -99,8 +103,12 @@ public:
         }
 
 
-    // Ostream Operator
+    // IO Operations
 
+        void read(Istream& is);
+        void write(Ostream& os) const;
+
+        friend Istream& operator>>(Istream&, procLduInterface&);
         friend Ostream& operator<<(Ostream&, const procLduInterface&);
 };
 
diff --git a/src/OpenFOAM/matrices/LUscalarMatrix/procLduMatrix.C b/src/OpenFOAM/matrices/LUscalarMatrix/procLduMatrix.C
index 9670e99e14657811473c9c9de61a37b2d2880458..ff2e032d97dec24bc9d7854756646e3c9b7e5075 100644
--- a/src/OpenFOAM/matrices/LUscalarMatrix/procLduMatrix.C
+++ b/src/OpenFOAM/matrices/LUscalarMatrix/procLduMatrix.C
@@ -50,7 +50,7 @@ Foam::procLduMatrix::procLduMatrix
 
     forAll(interfaces, i)
     {
-        if (interfaces.set(i))
+        if (interfaces.test(i))
         {
             interfaces_.set
             (
@@ -67,27 +67,48 @@ Foam::procLduMatrix::procLduMatrix
 
 
 Foam::procLduMatrix::procLduMatrix(Istream& is)
-:
-    upperAddr_(is),
-    lowerAddr_(is),
-    diag_(is),
-    upper_(is),
-    lower_(is),
-    interfaces_(is)
-{}
+{
+    read(is);
+}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+// void Foam::procLduMatrix::clear()
+// {
+//     upperAddr_.clear();
+//     lowerAddr_.clear();
+//     diag_.clear();
+//     upper_.clear();
+//     lower_.clear();
+//     interfaces_.clear();
+// }
+
+
+void Foam::procLduMatrix::read(Istream& is)
+{
+    is >> upperAddr_ >> lowerAddr_ >> diag_ >> upper_ >> lower_ >> interfaces_;
+}
+
+
+void Foam::procLduMatrix::write(Ostream& os) const
+{
+    os << upperAddr_ << lowerAddr_ << diag_ << upper_ << lower_ << interfaces_;
+}
 
 
 // * * * * * * * * * * * * * * * IOstream Operators  * * * * * * * * * * * * //
 
-Foam::Ostream& Foam::operator<<(Ostream& os, const procLduMatrix& cldum)
+Foam::Istream& Foam::operator>>(Istream& is, procLduMatrix& mat)
 {
-    os  << cldum.upperAddr_
-        << cldum.lowerAddr_
-        << cldum.diag_
-        << cldum.upper_
-        << cldum.lower_
-        << cldum.interfaces_;
+    mat.read(is);
+    return is;
+}
 
+
+Foam::Ostream& Foam::operator<<(Ostream& os, const procLduMatrix& mat)
+{
+    mat.write(os);
     return os;
 }
 
diff --git a/src/OpenFOAM/matrices/LUscalarMatrix/procLduMatrix.H b/src/OpenFOAM/matrices/LUscalarMatrix/procLduMatrix.H
index 179b6a88602e60b443fc600ec7b48dd2ee1a0831..71c63e4ef97df153b3e991f4157401dcc128a771 100644
--- a/src/OpenFOAM/matrices/LUscalarMatrix/procLduMatrix.H
+++ b/src/OpenFOAM/matrices/LUscalarMatrix/procLduMatrix.H
@@ -6,6 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2013 OpenFOAM Foundation
+    Copyright (C) 2024 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -34,8 +35,8 @@ SourceFiles
 
 \*---------------------------------------------------------------------------*/
 
-#ifndef procLduMatrix_H
-#define procLduMatrix_H
+#ifndef Foam_procLduMatrix_H
+#define Foam_procLduMatrix_H
 
 #include "labelList.H"
 #include "scalarField.H"
@@ -47,23 +48,21 @@ SourceFiles
 namespace Foam
 {
 
+// Forward Declarations
+class procLduMatrix;
 class procLduInterface;
 class lduMatrix;
 
-// Forward declaration of friend functions and operators
-
-class procLduMatrix;
-
+Istream& operator>>(Istream&, procLduMatrix&);
 Ostream& operator<<(Ostream&, const procLduMatrix&);
 
-
 /*---------------------------------------------------------------------------*\
-                           Class procLduMatrix Declaration
+                        Class procLduMatrix Declaration
 \*---------------------------------------------------------------------------*/
 
 class procLduMatrix
 {
-    // Private data
+    // Private Data
 
         labelList upperAddr_;
         labelList lowerAddr_;
@@ -72,20 +71,24 @@ class procLduMatrix
         scalarField lower_;
         PtrList<procLduInterface> interfaces_;
 
+public:
 
-    // Private Member Functions
+    //- Friendship
+    friend class LUscalarMatrix;
 
-        //- No copy construct
-        procLduMatrix(const procLduMatrix&) = delete;
 
+    // Generated Methods
 
-public:
+        //- Default construct
+        procLduMatrix() = default;
 
-    friend class LUscalarMatrix;
+        //- No copy construct
+        procLduMatrix(const procLduMatrix&) = delete;
 
 
     // Constructors
 
+        //- Construct from components. Extracts active interfaces
         procLduMatrix
         (
             const lduMatrix& ldum,
@@ -93,19 +96,26 @@ public:
             const lduInterfaceFieldPtrsList& interfaces
         );
 
-        procLduMatrix(Istream& is);
+        //- Read construct from Istream
+        explicit procLduMatrix(Istream& is);
 
 
-    // Member functions
+    // Member Functions
 
-        label size() const
+        label size() const noexcept
         {
             return diag_.size();
         }
 
+        // void clear();
+
+
+    // IO Operations
 
-    // Ostream operator
+        void read(Istream& is);
+        void write(Ostream& os) const;
 
+        friend Istream& operator>>(Istream&, procLduMatrix&);
         friend Ostream& operator<<(Ostream&, const procLduMatrix&);
 };
 
diff --git a/src/OpenFOAM/matrices/LduMatrix/LduMatrix/LduMatrix.C b/src/OpenFOAM/matrices/LduMatrix/LduMatrix/LduMatrix.C
index dbdaa0fbc3f050bcc54a3eae48887d773536225a..c76026bd5353c776dccd68516803b636184e37e8 100644
--- a/src/OpenFOAM/matrices/LduMatrix/LduMatrix/LduMatrix.C
+++ b/src/OpenFOAM/matrices/LduMatrix/LduMatrix/LduMatrix.C
@@ -6,6 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2016 OpenFOAM Foundation
+    Copyright (C) 2024 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -33,109 +34,86 @@ License
 template<class Type, class DType, class LUType>
 Foam::LduMatrix<Type, DType, LUType>::LduMatrix(const lduMesh& mesh)
 :
-    lduMesh_(mesh),
-    diagPtr_(nullptr),
-    upperPtr_(nullptr),
-    lowerPtr_(nullptr),
-    sourcePtr_(nullptr),
-    interfaces_(0),
-    interfacesUpper_(0),
-    interfacesLower_(0)
+    lduMesh_(mesh)
 {}
 
 
 template<class Type, class DType, class LUType>
 Foam::LduMatrix<Type, DType, LUType>::LduMatrix(const LduMatrix& A)
 :
-    lduMesh_(A.lduMesh_),
-    diagPtr_(nullptr),
-    upperPtr_(nullptr),
-    lowerPtr_(nullptr),
-    sourcePtr_(nullptr),
-    interfaces_(0),
-    interfacesUpper_(0),
-    interfacesLower_(0)
+    lduMesh_(A.lduMesh_)
 {
     if (A.diagPtr_)
     {
-        diagPtr_ = new Field<DType>(*(A.diagPtr_));
+        diagPtr_ = std::make_unique<Field<DType>>(*(A.diagPtr_));
     }
 
     if (A.upperPtr_)
     {
-        upperPtr_ = new Field<LUType>(*(A.upperPtr_));
+        upperPtr_ = std::make_unique<Field<LUType>>(*(A.upperPtr_));
     }
 
     if (A.lowerPtr_)
     {
-        lowerPtr_ = new Field<LUType>(*(A.lowerPtr_));
+        lowerPtr_ = std::make_unique<Field<LUType>>(*(A.lowerPtr_));
     }
 
     if (A.sourcePtr_)
     {
-        sourcePtr_ = new Field<Type>(*(A.sourcePtr_));
+        sourcePtr_ = std::make_unique<Field<Type>>(*(A.sourcePtr_));
     }
 }
 
 
 template<class Type, class DType, class LUType>
-Foam::LduMatrix<Type, DType, LUType>::LduMatrix(LduMatrix& A, bool reuse)
+Foam::LduMatrix<Type, DType, LUType>::LduMatrix(LduMatrix&& A)
 :
     lduMesh_(A.lduMesh_),
-    diagPtr_(nullptr),
-    upperPtr_(nullptr),
-    lowerPtr_(nullptr),
-    sourcePtr_(nullptr),
-    interfaces_(0),
-    interfacesUpper_(0),
-    interfacesLower_(0)
+    diagPtr_(std::move(A.diagPtr_)),
+    lowerPtr_(std::move(A.lowerPtr_)),
+    upperPtr_(std::move(A.upperPtr_)),
+    sourcePtr_(std::move(A.sourcePtr_))
 {
-    if (reuse)
-    {
-        if (A.diagPtr_)
-        {
-            diagPtr_ = A.diagPtr_;
-            A.diagPtr_ = nullptr;
-        }
+    // Clear the old interfaces?
+}
 
-        if (A.upperPtr_)
-        {
-            upperPtr_ = A.upperPtr_;
-            A.upperPtr_ = nullptr;
-        }
 
-        if (A.lowerPtr_)
-        {
-            lowerPtr_ = A.lowerPtr_;
-            A.lowerPtr_ = nullptr;
-        }
+template<class Type, class DType, class LUType>
+Foam::LduMatrix<Type, DType, LUType>::LduMatrix(LduMatrix& A, bool reuse)
+:
+    lduMesh_(A.lduMesh_)
+{
+    if (reuse)
+    {
+        // Move assignment
+        diagPtr_ = std::move(A.diagPtr_);
+        upperPtr_ = std::move(A.upperPtr_);
+        lowerPtr_ = std::move(A.lowerPtr_);
+        sourcePtr_ = std::move(A.sourcePtr_);
 
-        if (A.sourcePtr_)
-        {
-            sourcePtr_ = A.sourcePtr_;
-            A.sourcePtr_ = nullptr;
-        }
+        // Clear the old interfaces?
     }
     else
     {
+        // Copy assignment
         if (A.diagPtr_)
         {
-            diagPtr_ = new Field<DType>(*(A.diagPtr_));
+            diagPtr_ = std::make_unique<Field<DType>>(*(A.diagPtr_));
         }
 
         if (A.upperPtr_)
         {
-            upperPtr_ = new Field<LUType>(*(A.upperPtr_));
+            upperPtr_ = std::make_unique<Field<LUType>>(*(A.upperPtr_));
         }
 
         if (A.lowerPtr_)
         {
-            lowerPtr_ = new Field<LUType>(*(A.lowerPtr_));
+            lowerPtr_ = std::make_unique<Field<LUType>>(*(A.lowerPtr_));
         }
 
         if (A.sourcePtr_)
         {
-            sourcePtr_ = new Field<Type>(*(A.sourcePtr_));
+            sourcePtr_ = std::make_unique<Field<Type>>(*(A.sourcePtr_));
         }
     }
 }
@@ -152,48 +130,51 @@ Foam::LduMatrix<Type, DType, LUType>::LduMatrix
     diagPtr_(new Field<DType>(is)),
     upperPtr_(new Field<LUType>(is)),
     lowerPtr_(new Field<LUType>(is)),
-    sourcePtr_(new Field<Type>(is)),
-    interfaces_(0),
-    interfacesUpper_(0),
-    interfacesLower_(0)
+    sourcePtr_(new Field<Type>(is))
 {}
 
 
-// * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * * //
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
 template<class Type, class DType, class LUType>
-Foam::LduMatrix<Type, DType, LUType>::~LduMatrix()
+Foam::word Foam::LduMatrix<Type, DType, LUType>::matrixTypeName() const
 {
     if (diagPtr_)
     {
-        delete diagPtr_;
+        return
+        (
+            (!upperPtr_)
+          ? (!lowerPtr_ ? "diagonal" : "diagonal-lower")
+          : (!lowerPtr_ ? "symmetric" : "asymmetric")
+        );
     }
 
-    if (upperPtr_)
-    {
-        delete upperPtr_;
-    }
+    // is empty (or just wrong)
+    return (!upperPtr_ && !lowerPtr_ ? "empty" : "ill-defined");
+}
 
-    if (lowerPtr_)
-    {
-        delete lowerPtr_;
-    }
 
-    if (sourcePtr_)
+template<class Type, class DType, class LUType>
+const Foam::Field<DType>& Foam::LduMatrix<Type, DType, LUType>::diag() const
+{
+    if (!diagPtr_)
     {
-        delete sourcePtr_;
+        FatalErrorInFunction
+            << "diagPtr_ unallocated"
+            << abort(FatalError);
     }
-}
 
+    return *diagPtr_;
+}
 
-// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
 template<class Type, class DType, class LUType>
 Foam::Field<DType>& Foam::LduMatrix<Type, DType, LUType>::diag()
 {
     if (!diagPtr_)
     {
-        diagPtr_ = new Field<DType>(lduAddr().size(), Zero);
+        diagPtr_ =
+            std::make_unique<Field<DType>>(lduAddr().size(), Foam::zero{});
     }
 
     return *diagPtr_;
@@ -201,127 +182,115 @@ Foam::Field<DType>& Foam::LduMatrix<Type, DType, LUType>::diag()
 
 
 template<class Type, class DType, class LUType>
-Foam::Field<LUType>& Foam::LduMatrix<Type, DType, LUType>::upper()
+const Foam::Field<LUType>& Foam::LduMatrix<Type, DType, LUType>::upper() const
 {
-    if (!upperPtr_)
+    if (upperPtr_)
     {
-        if (lowerPtr_)
-        {
-            upperPtr_ = new Field<LUType>(*lowerPtr_);
-        }
-        else
+        return *upperPtr_;
+    }
+    else
+    {
+        if (!lowerPtr_)
         {
-            upperPtr_ = new Field<LUType>
-            (
-                lduAddr().lowerAddr().size(),
-                Zero
-            );
+            FatalErrorInFunction
+                << "lowerPtr_ and upperPtr_ unallocated"
+                << abort(FatalError);
         }
-    }
 
-    return *upperPtr_;
+        return *lowerPtr_;
+    }
 }
 
 
 template<class Type, class DType, class LUType>
-Foam::Field<LUType>& Foam::LduMatrix<Type, DType, LUType>::lower()
+Foam::Field<LUType>& Foam::LduMatrix<Type, DType, LUType>::upper()
 {
-    if (!lowerPtr_)
+    if (!upperPtr_)
     {
-        if (upperPtr_)
+        if (lowerPtr_)
         {
-            lowerPtr_ = new Field<LUType>(*upperPtr_);
+            upperPtr_ = std::make_unique<Field<LUType>>(*lowerPtr_);
         }
         else
         {
-            lowerPtr_ = new Field<LUType>
-            (
-                lduAddr().lowerAddr().size(),
-                Zero
-            );
+            upperPtr_ =
+                std::make_unique<Field<LUType>>
+                (
+                    lduAddr().lowerAddr().size(),
+                    Foam::zero{}
+                );
         }
     }
 
-    return *lowerPtr_;
+    return *upperPtr_;
 }
 
 
 template<class Type, class DType, class LUType>
-Foam::Field<Type>& Foam::LduMatrix<Type, DType, LUType>::source()
+const Foam::Field<LUType>& Foam::LduMatrix<Type, DType, LUType>::lower() const
 {
-    if (!sourcePtr_)
+    if (lowerPtr_)
     {
-        sourcePtr_ = new Field<Type>(lduAddr().size(), Zero);
+        return *lowerPtr_;
     }
-
-    return *sourcePtr_;
-}
-
-
-template<class Type, class DType, class LUType>
-const Foam::Field<DType>& Foam::LduMatrix<Type, DType, LUType>::diag() const
-{
-    if (!diagPtr_)
+    else
     {
-        FatalErrorInFunction
-            << "diagPtr_ unallocated"
-            << abort(FatalError);
-    }
+        if (!upperPtr_)
+        {
+            FatalErrorInFunction
+                << "lowerPtr_ and upperPtr_ unallocated"
+                << abort(FatalError);
+        }
 
-    return *diagPtr_;
+        return *upperPtr_;
+    }
 }
 
 
 template<class Type, class DType, class LUType>
-const Foam::Field<LUType>& Foam::LduMatrix<Type, DType, LUType>::upper() const
+Foam::Field<LUType>& Foam::LduMatrix<Type, DType, LUType>::lower()
 {
-    if (!lowerPtr_ && !upperPtr_)
+    if (!lowerPtr_)
     {
-        FatalErrorInFunction
-            << "lowerPtr_ or upperPtr_ unallocated"
-            << abort(FatalError);
+        if (upperPtr_)
+        {
+            lowerPtr_ = std::make_unique<Field<LUType>>(*upperPtr_);
+        }
+        else
+        {
+            lowerPtr_ = std::make_unique<Field<LUType>>
+            (
+                lduAddr().lowerAddr().size(),
+                Foam::zero{}
+            );
+        }
     }
 
-    if (upperPtr_)
-    {
-        return *upperPtr_;
-    }
-    else
-    {
-        return *lowerPtr_;
-    }
+    return *lowerPtr_;
 }
 
 
 template<class Type, class DType, class LUType>
-const Foam::Field<LUType>& Foam::LduMatrix<Type, DType, LUType>::lower() const
+const Foam::Field<Type>& Foam::LduMatrix<Type, DType, LUType>::source() const
 {
-    if (!lowerPtr_ && !upperPtr_)
+    if (!sourcePtr_)
     {
         FatalErrorInFunction
-            << "lowerPtr_ or upperPtr_ unallocated"
+            << "sourcePtr_ unallocated"
             << abort(FatalError);
     }
 
-    if (lowerPtr_)
-    {
-        return *lowerPtr_;
-    }
-    else
-    {
-        return *upperPtr_;
-    }
+    return *sourcePtr_;
 }
 
 
 template<class Type, class DType, class LUType>
-const Foam::Field<Type>& Foam::LduMatrix<Type, DType, LUType>::source() const
+Foam::Field<Type>& Foam::LduMatrix<Type, DType, LUType>::source()
 {
     if (!sourcePtr_)
     {
-        FatalErrorInFunction
-            << "sourcePtr_ unallocated"
-            << abort(FatalError);
+        sourcePtr_ =
+            std::make_unique<Field<Type>>(lduAddr().size(), Foam::zero{});
     }
 
     return *sourcePtr_;
@@ -330,43 +299,50 @@ const Foam::Field<Type>& Foam::LduMatrix<Type, DType, LUType>::source() const
 
 // * * * * * * * * * * * * * * * Friend Operators  * * * * * * * * * * * * * //
 
+// template<class Type, class DType, class LUType>
+// Foam::Ostream& Foam::operator<<
+// (
+//     Ostream& os,
+//     const InfoProxy<Type, DType, LUType>& iproxy
+// )
+// {
+//     const auto& mat = *iproxy;
+//
+//     ...
+//
+//     os.check(FUNCTION_NAME);
+//     return os;
+// }
+
+
 template<class Type, class DType, class LUType>
 Foam::Ostream& Foam::operator<<
 (
     Ostream& os,
-    const LduMatrix<Type, DType, LUType>& ldum
+    const LduMatrix<Type, DType, LUType>& mat
 )
 {
-    if (ldum.diagPtr_)
+    if (mat.hasDiag())
     {
-        os  << "Diagonal = "
-            << *ldum.diagPtr_
-            << endl << endl;
+        os  << "Diagonal = " << mat.diag() << nl << nl;
     }
 
-    if (ldum.upperPtr_)
+    if (mat.hasUpper())
     {
-        os  << "Upper triangle = "
-            << *ldum.upperPtr_
-            << endl << endl;
+        os  << "Upper triangle = " << mat.upper() << nl << nl;
     }
 
-    if (ldum.lowerPtr_)
+    if (mat.hasLower())
     {
-        os  << "Lower triangle = "
-            << *ldum.lowerPtr_
-            << endl << endl;
+        os  << "Lower triangle = " << mat.lower() << nl << nl;
     }
 
-    if (ldum.sourcePtr_)
+    if (mat.hasSource())
     {
-        os  << "Source = "
-            << *ldum.sourcePtr_
-            << endl << endl;
+        os  << "Source = " << mat.source() << nl << nl;
     }
 
     os.check(FUNCTION_NAME);
-
     return os;
 }
 
diff --git a/src/OpenFOAM/matrices/LduMatrix/LduMatrix/LduMatrix.H b/src/OpenFOAM/matrices/LduMatrix/LduMatrix/LduMatrix.H
index 96e9fd14f4e303bf5ca51a51a0f739db6ed20f95..407f7ee3226666147dcf8029533ce8f5f04d988b 100644
--- a/src/OpenFOAM/matrices/LduMatrix/LduMatrix/LduMatrix.H
+++ b/src/OpenFOAM/matrices/LduMatrix/LduMatrix/LduMatrix.H
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2017 OpenFOAM Foundation
-    Copyright (C) 2019-2023 OpenCFD Ltd.
+    Copyright (C) 2019-2024 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -93,25 +93,32 @@ class LduMatrix
         const lduMesh& lduMesh_;
 
         //- Diagonal coefficients
-        Field<DType> *diagPtr_;
+        std::unique_ptr<Field<DType>> diagPtr_;
 
         //- Off-diagonal coefficients
-        Field<LUType> *upperPtr_, *lowerPtr_;
+        std::unique_ptr<Field<LUType>> upperPtr_;
+
+        //- Off-diagonal coefficients
+        std::unique_ptr<Field<LUType>> lowerPtr_;
 
         //- Source
-        Field<Type> *sourcePtr_;
+        std::unique_ptr<Field<Type>> sourcePtr_;
 
         //- Field interfaces (processor patches etc.)
         LduInterfaceFieldPtrsList<Type> interfaces_;
 
         //- Off-diagonal coefficients for interfaces
-        FieldField<Field, LUType> interfacesUpper_, interfacesLower_;
+        FieldField<Field, LUType> interfacesUpper_;
+
+        //- Off-diagonal coefficients for interfaces
+        FieldField<Field, LUType> interfacesLower_;
 
 
 public:
 
     friend class SolverPerformance<Type>;
 
+    // -----------------------------------------------------------------------
     //- Abstract base-class for LduMatrix solvers
     class solver
     {
@@ -274,6 +281,7 @@ public:
     };
 
 
+    // -----------------------------------------------------------------------
     //- Abstract base-class for LduMatrix smoothers
     class smoother
     {
@@ -371,6 +379,7 @@ public:
     };
 
 
+    // -----------------------------------------------------------------------
     //- Abstract base-class for LduMatrix preconditioners
     class preconditioner
     {
@@ -466,6 +475,8 @@ public:
     };
 
 
+    // -----------------------------------------------------------------------
+
     // Static Data
 
         // Declare name of the class and its debug switch
@@ -476,126 +487,125 @@ public:
 
         //- Construct given an LDU addressed mesh.
         //  The coefficients are initially empty for subsequent setting.
-        LduMatrix(const lduMesh&);
+        //  Not yet 'explicit' (legacy code may rely on implicit construct)
+        LduMatrix(const lduMesh& mesh);
 
-        //- Construct as copy
+        //- Copy construct
         LduMatrix(const LduMatrix<Type, DType, LUType>&);
 
+        //- Move construct
+        LduMatrix(LduMatrix<Type, DType, LUType>&&);
+
         //- Construct as copy or re-use as specified.
         LduMatrix(LduMatrix<Type, DType, LUType>&, bool reuse);
 
         //- Construct given an LDU addressed mesh and an Istream
-        //  from which the coefficients are read
-        LduMatrix(const lduMesh&, Istream&);
+        //- from which the coefficients are read
+        LduMatrix(const lduMesh& mesh, Istream& is);
 
 
     //- Destructor
-    ~LduMatrix();
+    ~LduMatrix() = default;
 
 
     // Member Functions
 
-        // Access to addressing
+    // Addressing
 
-            //- Return the LDU mesh from which the addressing is obtained
-            const lduMesh& mesh() const noexcept
-            {
-                return lduMesh_;
-            }
+        //- Return the LDU mesh from which the addressing is obtained
+        const lduMesh& mesh() const noexcept
+        {
+            return lduMesh_;
+        }
 
-            //- Return the LDU addressing
-            const lduAddressing& lduAddr() const
-            {
-                return lduMesh_.lduAddr();
-            }
+        //- Return the LDU addressing
+        const lduAddressing& lduAddr() const
+        {
+            return lduMesh_.lduAddr();
+        }
 
-            //- Return the patch evaluation schedule
-            const lduSchedule& patchSchedule() const
-            {
-                return lduAddr().patchSchedule();
-            }
+        //- Return the patch evaluation schedule
+        const lduSchedule& patchSchedule() const
+        {
+            return lduMesh_.lduAddr().patchSchedule();
+        }
 
-            //- Return interfaces
-            const LduInterfaceFieldPtrsList<Type>& interfaces() const
-            {
-                return interfaces_;
-            }
+        //- Const access to the interfaces
+        const LduInterfaceFieldPtrsList<Type>& interfaces() const noexcept
+        {
+            return interfaces_;
+        }
 
-            //- Return interfaces
-            LduInterfaceFieldPtrsList<Type>& interfaces()
-            {
-                return interfaces_;
-            }
+        //- Non-const access to the interfaces
+        LduInterfaceFieldPtrsList<Type>& interfaces() noexcept
+        {
+            return interfaces_;
+        }
 
 
-        // Access to coefficients
+    // Coefficients
 
-            Field<DType>& diag();
-            Field<LUType>& upper();
-            Field<LUType>& lower();
-            Field<Type>& source();
+        const Field<DType>& diag() const;
+        const Field<LUType>& upper() const;
+        const Field<LUType>& lower() const;
+        const Field<Type>& source() const;
 
-            FieldField<Field, LUType>& interfacesUpper()
-            {
-                return interfacesUpper_;
-            }
+        Field<DType>& diag();
+        Field<LUType>& upper();
+        Field<LUType>& lower();
+        Field<Type>& source();
 
-            FieldField<Field, LUType>& interfacesLower()
-            {
-                return interfacesLower_;
-            }
 
+    // Interfaces
 
-            const Field<DType>& diag() const;
-            const Field<LUType>& upper() const;
-            const Field<LUType>& lower() const;
-            const Field<Type>& source() const;
+        const FieldField<Field, LUType>& interfacesUpper() const noexcept
+        {
+            return interfacesUpper_;
+        }
 
-            const FieldField<Field, LUType>& interfacesUpper() const
-            {
-                return interfacesUpper_;
-            }
+        const FieldField<Field, LUType>& interfacesLower() const noexcept
+        {
+            return interfacesLower_;
+        }
 
-            const FieldField<Field, LUType>& interfacesLower() const
-            {
-                return interfacesLower_;
-            }
+        FieldField<Field, LUType>& interfacesUpper() noexcept
+        {
+            return interfacesUpper_;
+        }
 
+        FieldField<Field, LUType>& interfacesLower() noexcept
+        {
+            return interfacesLower_;
+        }
 
-            bool hasDiag() const noexcept
-            {
-                return (diagPtr_);
-            }
 
-            bool hasUpper() const noexcept
-            {
-                return (upperPtr_);
-            }
+    // Characteristics
 
-            bool hasLower() const noexcept
-            {
-                return (lowerPtr_);
-            }
+        //- The matrix type (empty, diagonal, symmetric, ...)
+        word matrixTypeName() const;
 
-            bool hasSource() const noexcept
-            {
-                return (sourcePtr_);
-            }
+        bool hasDiag() const noexcept { return bool(diagPtr_); }
+        bool hasUpper() const noexcept { return bool(upperPtr_); }
+        bool hasLower() const noexcept { return bool(lowerPtr_); }
+        bool hasSource() const noexcept { return bool(sourcePtr_); }
 
-            bool diagonal() const noexcept
-            {
-                return (diagPtr_ && !lowerPtr_ && !upperPtr_);
-            }
+        //- Matrix has diagonal only
+        bool diagonal() const noexcept
+        {
+            return (diagPtr_ && !lowerPtr_ && !upperPtr_);
+        }
 
-            bool symmetric() const noexcept
-            {
-                return (diagPtr_ && (!lowerPtr_ && upperPtr_));
-            }
+        //- Matrix is symmetric
+        bool symmetric() const noexcept
+        {
+            return (diagPtr_ && !lowerPtr_ && upperPtr_);
+        }
 
-            bool asymmetric() const noexcept
-            {
-                return (diagPtr_ && lowerPtr_ && upperPtr_);
-            }
+        //- Matrix is asymmetric (ie, full)
+        bool asymmetric() const noexcept
+        {
+            return (diagPtr_ && lowerPtr_ && upperPtr_);
+        }
 
 
         // Operations
@@ -651,8 +661,12 @@ public:
 
     // Member Operators
 
+        //- Copy assignment
         void operator=(const LduMatrix<Type, DType, LUType>&);
 
+        //- Move assignment
+        void operator=(LduMatrix<Type, DType, LUType>&&);
+
         void negate();
 
         void operator+=(const LduMatrix<Type, DType, LUType>&);
diff --git a/src/OpenFOAM/matrices/LduMatrix/LduMatrix/LduMatrixOperations.C b/src/OpenFOAM/matrices/LduMatrix/LduMatrix/LduMatrixOperations.C
index 7945a8cd2da82752cbb4740102af3fd788d0f911..46e7ad7b605cd058fdcb2898aca7e1eb58bb2d4c 100644
--- a/src/OpenFOAM/matrices/LduMatrix/LduMatrix/LduMatrixOperations.C
+++ b/src/OpenFOAM/matrices/LduMatrix/LduMatrix/LduMatrixOperations.C
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2016 OpenFOAM Foundation
-    Copyright (C) 2019 OpenCFD Ltd.
+    Copyright (C) 2019-2024 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -92,7 +92,7 @@ Foam::LduMatrix<Type, DType, LUType>::H(const Field<Type>& psi) const
 {
     auto tHpsi = tmp<Field<Type>>::New(lduAddr().size(), Foam::zero{});
 
-    if (lowerPtr_ || upperPtr_)
+    if (hasLower() || hasUpper())
     {
         Type* __restrict__ HpsiPtr = tHpsi.ref().begin();
 
@@ -169,32 +169,30 @@ void Foam::LduMatrix<Type, DType, LUType>::operator=(const LduMatrix& A)
         return;  // Self-assignment is a no-op
     }
 
-    if (A.diagPtr_)
+    if (A.hasDiag())
     {
         diag() = A.diag();
     }
 
-    if (A.upperPtr_)
+    if (A.hasUpper())
     {
         upper() = A.upper();
     }
-    else if (upperPtr_)
+    else
     {
-        delete upperPtr_;
-        upperPtr_ = nullptr;
+        upperPtr_.reset(nullptr);
     }
 
-    if (A.lowerPtr_)
+    if (A.hasLower())
     {
         lower() = A.lower();
     }
-    else if (lowerPtr_)
+    else
     {
-        delete lowerPtr_;
-        lowerPtr_ = nullptr;
+        lowerPtr_.reset(nullptr);
     }
 
-    if (A.sourcePtr_)
+    if (A.hasSource())
     {
         source() = A.source();
     }
@@ -204,6 +202,24 @@ void Foam::LduMatrix<Type, DType, LUType>::operator=(const LduMatrix& A)
 }
 
 
+template<class Type, class DType, class LUType>
+void Foam::LduMatrix<Type, DType, LUType>::operator=(LduMatrix&& A)
+{
+    if (this == &A)
+    {
+        return;  // Self-assignment is a no-op
+    }
+
+    diagPtr_ = std::move(A.diagPtr_);
+    upperPtr_ = std::move(A.upperPtr_);
+    lowerPtr_ = std::move(A.lowerPtr_);
+    sourcePtr_ = std::move(A.sourcePtr_);
+
+    interfacesUpper_ = std::move(A.interfacesUpper_);
+    interfacesLower_ = std::move(A.interfacesLower_);
+}
+
+
 template<class Type, class DType, class LUType>
 void Foam::LduMatrix<Type, DType, LUType>::negate()
 {
@@ -235,12 +251,12 @@ void Foam::LduMatrix<Type, DType, LUType>::negate()
 template<class Type, class DType, class LUType>
 void Foam::LduMatrix<Type, DType, LUType>::operator+=(const LduMatrix& A)
 {
-    if (A.diagPtr_)
+    if (A.hasDiag())
     {
         diag() += A.diag();
     }
 
-    if (A.sourcePtr_)
+    if (A.hasSource())
     {
         source() += A.source();
     }
@@ -265,7 +281,7 @@ void Foam::LduMatrix<Type, DType, LUType>::operator+=(const LduMatrix& A)
     }
     else if (asymmetric() && A.symmetric())
     {
-        if (A.upperPtr_)
+        if (A.hasUpper())
         {
             lower() += A.upper();
             upper() += A.upper();
@@ -284,12 +300,12 @@ void Foam::LduMatrix<Type, DType, LUType>::operator+=(const LduMatrix& A)
     }
     else if (diagonal())
     {
-        if (A.upperPtr_)
+        if (A.hasUpper())
         {
             upper() = A.upper();
         }
 
-        if (A.lowerPtr_)
+        if (A.hasLower())
         {
             lower() = A.lower();
         }
@@ -312,12 +328,12 @@ void Foam::LduMatrix<Type, DType, LUType>::operator+=(const LduMatrix& A)
 template<class Type, class DType, class LUType>
 void Foam::LduMatrix<Type, DType, LUType>::operator-=(const LduMatrix& A)
 {
-    if (A.diagPtr_)
+    if (A.hasDiag())
     {
         diag() -= A.diag();
     }
 
-    if (A.sourcePtr_)
+    if (A.hasSource())
     {
         source() -= A.source();
     }
@@ -342,7 +358,7 @@ void Foam::LduMatrix<Type, DType, LUType>::operator-=(const LduMatrix& A)
     }
     else if (asymmetric() && A.symmetric())
     {
-        if (A.upperPtr_)
+        if (A.hasUpper())
         {
             lower() -= A.upper();
             upper() -= A.upper();
@@ -361,12 +377,12 @@ void Foam::LduMatrix<Type, DType, LUType>::operator-=(const LduMatrix& A)
     }
     else if (diagonal())
     {
-        if (A.upperPtr_)
+        if (A.hasUpper())
         {
             upper() = -A.upper();
         }
 
-        if (A.lowerPtr_)
+        if (A.hasLower())
         {
             lower() = -A.lower();
         }
diff --git a/src/OpenFOAM/matrices/SquareMatrix/SquareMatrix.C b/src/OpenFOAM/matrices/SquareMatrix/SquareMatrix.C
index 2c64598fd6918851e3a7c9bf7379388c6a018229..fc5e12418479ce116e72c9f6e03bbf2b87a30953 100644
--- a/src/OpenFOAM/matrices/SquareMatrix/SquareMatrix.C
+++ b/src/OpenFOAM/matrices/SquareMatrix/SquareMatrix.C
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2013-2016 OpenFOAM Foundation
-    Copyright (C) 2019-2023 OpenCFD Ltd.
+    Copyright (C) 2019-2024 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -124,7 +124,7 @@ scalar det(const SquareMatrix<Type>& matrix)
 {
     SquareMatrix<Type> matrixTmp = matrix;
 
-    labelList pivotIndices(matrix.m());
+    labelList pivotIndices;
     label sign;
     LUDecompose(matrixTmp, pivotIndices, sign);
 
@@ -136,7 +136,7 @@ scalar det(const SquareMatrix<Type>& matrix)
 template<class Type>
 scalar det(SquareMatrix<Type>& matrix)
 {
-    labelList pivotIndices(matrix.m());
+    labelList pivotIndices;
     label sign;
     LUDecompose(matrix, pivotIndices, sign);
 
diff --git a/src/OpenFOAM/matrices/lduMatrix/lduAddressing/lduAddressing.C b/src/OpenFOAM/matrices/lduMatrix/lduAddressing/lduAddressing.C
index 61006d077c3ffc57cddbc9741cf296d11992774f..91180115b7f2c568dc0fb042fbb525349dfce927 100644
--- a/src/OpenFOAM/matrices/lduMatrix/lduAddressing/lduAddressing.C
+++ b/src/OpenFOAM/matrices/lduMatrix/lduAddressing/lduAddressing.C
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2016 OpenFOAM Foundation
-    Copyright (C) 2016 OpenCFD Ltd.
+    Copyright (C) 2016-2024 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -27,7 +27,6 @@ License
 \*---------------------------------------------------------------------------*/
 
 #include "lduAddressing.H"
-#include "demandDrivenData.H"
 #include "scalarField.H"
 
 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
@@ -44,7 +43,7 @@ void Foam::lduAddressing::calcLosort() const
     // Scan the neighbour list to find out how many times the cell
     // appears as a neighbour of the face. Done this way to avoid guessing
     // and resizing list
-    labelList nNbrOfFace(size(), Zero);
+    labelList nNbrOfFace(size(), Foam::zero{});
 
     const labelUList& nbr = upperAddr();
 
@@ -73,9 +72,8 @@ void Foam::lduAddressing::calcLosort() const
     }
 
     // Gather the neighbours into the losort array
-    losortPtr_ = new labelList(nbr.size(), -1);
-
-    labelList& lst = *losortPtr_;
+    losortPtr_ = std::make_unique<labelList>(nbr.size(), -1);
+    auto& lst = *losortPtr_;
 
     // Set counter for losort
     label lstI = 0;
@@ -104,9 +102,8 @@ void Foam::lduAddressing::calcOwnerStart() const
 
     const labelList& own = lowerAddr();
 
-    ownerStartPtr_ = new labelList(size() + 1, own.size());
-
-    labelList& ownStart = *ownerStartPtr_;
+    ownerStartPtr_ = std::make_unique<labelList>(size() + 1, own.size());
+    auto& ownStart = *ownerStartPtr_;
 
     // Set up first lookup by hand
     ownStart[0] = 0;
@@ -139,9 +136,8 @@ void Foam::lduAddressing::calcLosortStart() const
             << abort(FatalError);
     }
 
-    losortStartPtr_ = new labelList(size() + 1, Zero);
-
-    labelList& lsrtStart = *losortStartPtr_;
+    losortStartPtr_ = std::make_unique<labelList>(size() + 1, Foam::zero{});
+    auto& lsrtStart = *losortStartPtr_;
 
     const labelList& nbr = upperAddr();
 
@@ -173,16 +169,6 @@ void Foam::lduAddressing::calcLosortStart() const
 }
 
 
-// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
-
-Foam::lduAddressing::~lduAddressing()
-{
-    deleteDemandDrivenData(losortPtr_);
-    deleteDemandDrivenData(ownerStartPtr_);
-    deleteDemandDrivenData(losortStartPtr_);
-}
-
-
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
 const Foam::labelUList& Foam::lduAddressing::losortAddr() const
@@ -220,9 +206,9 @@ const Foam::labelUList& Foam::lduAddressing::losortStartAddr() const
 
 void Foam::lduAddressing::clearOut()
 {
-    deleteDemandDrivenData(losortPtr_);
-    deleteDemandDrivenData(ownerStartPtr_);
-    deleteDemandDrivenData(losortStartPtr_);
+    losortPtr_.reset(nullptr);
+    ownerStartPtr_.reset(nullptr);
+    losortStartPtr_.reset(nullptr);
 }
 
 
@@ -262,7 +248,7 @@ Foam::Tuple2<Foam::label, Foam::scalar> Foam::lduAddressing::band() const
     const labelUList& owner = lowerAddr();
     const labelUList& neighbour = upperAddr();
 
-    labelList cellBandwidth(size(), Zero);
+    labelList cellBandwidth(size(), Foam::zero{});
 
     forAll(neighbour, facei)
     {
diff --git a/src/OpenFOAM/matrices/lduMatrix/lduAddressing/lduAddressing.H b/src/OpenFOAM/matrices/lduMatrix/lduAddressing/lduAddressing.H
index c37cd61aec852a29cf1a44e4f87e0118f9bc5ff3..b610a6539d4b8805519015220ea80aa4dc573e4d 100644
--- a/src/OpenFOAM/matrices/lduMatrix/lduAddressing/lduAddressing.H
+++ b/src/OpenFOAM/matrices/lduMatrix/lduAddressing/lduAddressing.H
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2016 OpenFOAM Foundation
-    Copyright (C) 2016-2019 OpenCFD Ltd.
+    Copyright (C) 2016-2024 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -123,23 +123,17 @@ class lduAddressing
     //- Demand-driven data
 
         //- Losort addressing
-        mutable labelList* losortPtr_;
+        mutable std::unique_ptr<labelList> losortPtr_;
 
         //- Owner start addressing
-        mutable labelList* ownerStartPtr_;
+        mutable std::unique_ptr<labelList> ownerStartPtr_;
 
         //- Losort start addressing
-        mutable labelList* losortStartPtr_;
+        mutable std::unique_ptr<labelList> losortStartPtr_;
 
 
     // Private Member Functions
 
-        //- No copy construct
-        lduAddressing(const lduAddressing&) = delete;
-
-        //- No copy assignment
-        void operator=(const lduAddressing&) = delete;
-
         //- Calculate losort
         void calcLosort() const;
 
@@ -152,24 +146,32 @@ class lduAddressing
 
 public:
 
-    //- Construct with size (number of equations)
-    explicit lduAddressing(const label nEqns)
-    :
-        size_(nEqns),
-        losortPtr_(nullptr),
-        ownerStartPtr_(nullptr),
-        losortStartPtr_(nullptr)
-    {}
+    // Generated Methods
+
+        //- No copy construct
+        lduAddressing(const lduAddressing&) = delete;
+
+        //- No copy assignment
+        void operator=(const lduAddressing&) = delete;
+
+
+    // Constructors
+
+        //- Construct with size (number of equations)
+        explicit lduAddressing(const label nEqns) noexcept
+        :
+            size_(nEqns)
+        {}
 
 
     //- Destructor
-    virtual ~lduAddressing();
+    virtual ~lduAddressing() = default;
 
 
     // Member Functions
 
         //- Return number of equations
-        label size() const
+        label size() const noexcept
         {
             return size_;
         }
diff --git a/src/OpenFOAM/matrices/lduMatrix/lduMatrix/lduMatrix.C b/src/OpenFOAM/matrices/lduMatrix/lduMatrix/lduMatrix.C
index dd3232541991f1077ccf41d0808c4da12282b712..e2767c6b5262da32109a81c1fd087ccee9b71d3e 100644
--- a/src/OpenFOAM/matrices/lduMatrix/lduMatrix/lduMatrix.C
+++ b/src/OpenFOAM/matrices/lduMatrix/lduMatrix/lduMatrix.C
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2017 OpenFOAM Foundation
-    Copyright (C) 2019-2021 OpenCFD Ltd.
+    Copyright (C) 2019-2024 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -60,79 +60,66 @@ Foam::lduMatrix::normTypesNames_
 
 Foam::lduMatrix::lduMatrix(const lduMesh& mesh)
 :
-    lduMesh_(mesh),
-    lowerPtr_(nullptr),
-    diagPtr_(nullptr),
-    upperPtr_(nullptr)
+    lduMesh_(mesh)
 {}
 
 
 Foam::lduMatrix::lduMatrix(const lduMatrix& A)
 :
-    lduMesh_(A.lduMesh_),
-    lowerPtr_(nullptr),
-    diagPtr_(nullptr),
-    upperPtr_(nullptr)
+    lduMesh_(A.lduMesh_)
 {
-    if (A.lowerPtr_)
+    if (A.diagPtr_)
     {
-        lowerPtr_ = new scalarField(*(A.lowerPtr_));
+        diagPtr_ = std::make_unique<scalarField>(*(A.diagPtr_));
     }
 
-    if (A.diagPtr_)
+    if (A.upperPtr_)
     {
-        diagPtr_ = new scalarField(*(A.diagPtr_));
+        upperPtr_ = std::make_unique<scalarField>(*(A.upperPtr_));
     }
 
-    if (A.upperPtr_)
+    if (A.lowerPtr_)
     {
-        upperPtr_ = new scalarField(*(A.upperPtr_));
+        lowerPtr_ = std::make_unique<scalarField>(*(A.lowerPtr_));
     }
 }
 
 
-Foam::lduMatrix::lduMatrix(lduMatrix& A, bool reuse)
+Foam::lduMatrix::lduMatrix(lduMatrix&& A)
 :
     lduMesh_(A.lduMesh_),
-    lowerPtr_(nullptr),
-    diagPtr_(nullptr),
-    upperPtr_(nullptr)
+    diagPtr_(std::move(A.diagPtr_)),
+    lowerPtr_(std::move(A.lowerPtr_)),
+    upperPtr_(std::move(A.upperPtr_))
+{}
+
+
+Foam::lduMatrix::lduMatrix(lduMatrix& A, bool reuse)
+:
+    lduMesh_(A.lduMesh_)
 {
     if (reuse)
     {
-        if (A.lowerPtr_)
-        {
-            lowerPtr_ = A.lowerPtr_;
-            A.lowerPtr_ = nullptr;
-        }
-
-        if (A.diagPtr_)
-        {
-            diagPtr_ = A.diagPtr_;
-            A.diagPtr_ = nullptr;
-        }
-
-        if (A.upperPtr_)
-        {
-            upperPtr_ = A.upperPtr_;
-            A.upperPtr_ = nullptr;
-        }
+        diagPtr_ = std::move(A.diagPtr_);
+        upperPtr_ = std::move(A.upperPtr_);
+        lowerPtr_ = std::move(A.lowerPtr_);
     }
     else
     {
-        if (A.lowerPtr_)
+        // Copy assignment
+        if (A.diagPtr_)
         {
-            lowerPtr_ = new scalarField(*(A.lowerPtr_));
+            diagPtr_ = std::make_unique<scalarField>(*(A.diagPtr_));
         }
 
-        if (A.diagPtr_)
+        if (A.upperPtr_)
         {
-            diagPtr_ = new scalarField(*(A.diagPtr_));
+            upperPtr_ = std::make_unique<scalarField>(*(A.upperPtr_));
         }
 
-        if (A.upperPtr_)
+        if (A.lowerPtr_)
         {
-            upperPtr_ = new scalarField(*(A.upperPtr_));
+            lowerPtr_ = std::make_unique<scalarField>(*(A.lowerPtr_));
         }
     }
 }
@@ -140,64 +127,56 @@ Foam::lduMatrix::lduMatrix(lduMatrix& A, bool reuse)
 
 Foam::lduMatrix::lduMatrix(const lduMesh& mesh, Istream& is)
 :
-    lduMesh_(mesh),
-    lowerPtr_(nullptr),
-    diagPtr_(nullptr),
-    upperPtr_(nullptr)
+    lduMesh_(mesh)
 {
-    Switch hasLow(is);
-    Switch hasDiag(is);
-    Switch hasUp(is);
+    bool withLower, withDiag, withUpper;
+
+    is >> withLower >> withDiag >> withUpper;
 
-    if (hasLow)
+    if (withLower)
     {
-        lowerPtr_ = new scalarField(is);
+        lowerPtr_ = std::make_unique<scalarField>(is);
     }
-    if (hasDiag)
+    if (withDiag)
     {
-        diagPtr_ = new scalarField(is);
+        diagPtr_ = std::make_unique<scalarField>(is);
     }
-    if (hasUp)
+    if (withUpper)
     {
-        upperPtr_ = new scalarField(is);
+        upperPtr_ = std::make_unique<scalarField>(is);
     }
 }
 
 
-Foam::lduMatrix::~lduMatrix()
-{
-    if (lowerPtr_)
-    {
-        delete lowerPtr_;
-    }
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
+Foam::word Foam::lduMatrix::matrixTypeName() const
+{
     if (diagPtr_)
     {
-        delete diagPtr_;
+        return
+        (
+            (!upperPtr_)
+          ? (!lowerPtr_ ? "diagonal" : "diagonal-lower")
+          : (!lowerPtr_ ? "symmetric" : "asymmetric")
+        );
     }
 
-    if (upperPtr_)
-    {
-        delete upperPtr_;
-    }
+    // is empty (or just wrong)
+    return (!upperPtr_ && !lowerPtr_ ? "empty" : "ill-defined");
 }
 
 
-Foam::scalarField& Foam::lduMatrix::lower()
+const Foam::scalarField& Foam::lduMatrix::diag() const
 {
-    if (!lowerPtr_)
+    if (!diagPtr_)
     {
-        if (upperPtr_)
-        {
-            lowerPtr_ = new scalarField(*upperPtr_);
-        }
-        else
-        {
-            lowerPtr_ = new scalarField(lduAddr().lowerAddr().size(), Zero);
-        }
+        FatalErrorInFunction
+            << "diagPtr_ unallocated"
+            << abort(FatalError);
     }
 
-    return *lowerPtr_;
+    return *diagPtr_;
 }
 
 
@@ -205,71 +184,87 @@ Foam::scalarField& Foam::lduMatrix::diag()
 {
     if (!diagPtr_)
     {
-        diagPtr_ = new scalarField(lduAddr().size(), Zero);
+        diagPtr_ =
+            std::make_unique<scalarField>(lduAddr().size(), Foam::zero{});
     }
 
     return *diagPtr_;
 }
 
 
-Foam::scalarField& Foam::lduMatrix::upper()
+Foam::scalarField& Foam::lduMatrix::diag(label size)
 {
-    if (!upperPtr_)
+    if (!diagPtr_)
     {
-        if (lowerPtr_)
-        {
-            upperPtr_ = new scalarField(*lowerPtr_);
-        }
-        else
-        {
-            upperPtr_ = new scalarField(lduAddr().lowerAddr().size(), Zero);
-        }
+        // if (size < 0)
+        // {
+        //     size = lduAddr().size();
+        // }
+        diagPtr_ = std::make_unique<scalarField>(size, Foam::zero{});
     }
 
-    return *upperPtr_;
+    return *diagPtr_;
 }
 
 
-Foam::scalarField& Foam::lduMatrix::lower(const label nCoeffs)
+const Foam::scalarField& Foam::lduMatrix::upper() const
 {
-    if (!lowerPtr_)
+    if (upperPtr_)
     {
-        if (upperPtr_)
-        {
-            lowerPtr_ = new scalarField(*upperPtr_);
-        }
-        else
+        return *upperPtr_;
+    }
+    else
+    {
+        if (!lowerPtr_)
         {
-            lowerPtr_ = new scalarField(nCoeffs, Zero);
+            FatalErrorInFunction
+                << "lowerPtr_ and upperPtr_ unallocated"
+                << abort(FatalError);
         }
-    }
 
-    return *lowerPtr_;
+        return *lowerPtr_;
+    }
 }
 
 
-Foam::scalarField& Foam::lduMatrix::diag(const label size)
+Foam::scalarField& Foam::lduMatrix::upper()
 {
-    if (!diagPtr_)
+    if (!upperPtr_)
     {
-        diagPtr_ = new scalarField(size, Zero);
+        if (lowerPtr_)
+        {
+            upperPtr_ = std::make_unique<scalarField>(*lowerPtr_);
+        }
+        else
+        {
+            upperPtr_ =
+                std::make_unique<scalarField>
+                (
+                    lduAddr().lowerAddr().size(),
+                    Foam::zero{}
+                );
+        }
     }
 
-    return *diagPtr_;
+    return *upperPtr_;
 }
 
 
-Foam::scalarField& Foam::lduMatrix::upper(const label nCoeffs)
+Foam::scalarField& Foam::lduMatrix::upper(label nCoeffs)
 {
     if (!upperPtr_)
     {
         if (lowerPtr_)
         {
-            upperPtr_ = new scalarField(*lowerPtr_);
+            upperPtr_ = std::make_unique<scalarField>(*lowerPtr_);
         }
         else
         {
-            upperPtr_ = new scalarField(nCoeffs, Zero);
+            // if (nCoeffs < 0)
+            // {
+            //     nCoeffs = lduAddr().lowerAddr().size();
+            // }
+            upperPtr_ = std::make_unique<scalarField>(nCoeffs, Foam::zero{});
         }
     }
 
@@ -279,54 +274,67 @@ Foam::scalarField& Foam::lduMatrix::upper(const label nCoeffs)
 
 const Foam::scalarField& Foam::lduMatrix::lower() const
 {
-    if (!lowerPtr_ && !upperPtr_)
-    {
-        FatalErrorInFunction
-            << "lowerPtr_ or upperPtr_ unallocated"
-            << abort(FatalError);
-    }
-
     if (lowerPtr_)
     {
         return *lowerPtr_;
     }
     else
     {
+        if (!upperPtr_)
+        {
+            FatalErrorInFunction
+                << "lowerPtr_ and upperPtr_ unallocated"
+                << abort(FatalError);
+        }
+
         return *upperPtr_;
     }
 }
 
 
-const Foam::scalarField& Foam::lduMatrix::diag() const
+Foam::scalarField& Foam::lduMatrix::lower()
 {
-    if (!diagPtr_)
+    if (!lowerPtr_)
     {
-        FatalErrorInFunction
-            << "diagPtr_ unallocated"
-            << abort(FatalError);
+        if (upperPtr_)
+        {
+            lowerPtr_ = std::make_unique<scalarField>(*upperPtr_);
+        }
+        else
+        {
+            lowerPtr_ =
+                std::make_unique<scalarField>
+                (
+                    lduAddr().lowerAddr().size(),
+                    Foam::zero{}
+                );
+        }
     }
 
-    return *diagPtr_;
+    return *lowerPtr_;
 }
 
 
-const Foam::scalarField& Foam::lduMatrix::upper() const
+Foam::scalarField& Foam::lduMatrix::lower(label nCoeffs)
 {
-    if (!lowerPtr_ && !upperPtr_)
+    if (!lowerPtr_)
     {
-        FatalErrorInFunction
-            << "lowerPtr_ or upperPtr_ unallocated"
-            << abort(FatalError);
+        if (upperPtr_)
+        {
+            lowerPtr_ = std::make_unique<scalarField>(*upperPtr_);
+        }
+        else
+        {
+            // if (nCoeffs < 0)
+            // {
+            //     nCoeffs = lduAddr().lowerAddr().size();
+            // }
+            lowerPtr_ =
+                std::make_unique<scalarField>(nCoeffs, Foam::zero{});
+        }
     }
 
-    if (upperPtr_)
-    {
-        return *upperPtr_;
-    }
-    else
-    {
-        return *lowerPtr_;
-    }
+    return *lowerPtr_;
 }
 
 
@@ -377,28 +385,25 @@ void Foam::lduMatrix::setResidualField
 
 // * * * * * * * * * * * * * * * Friend Operators  * * * * * * * * * * * * * //
 
-Foam::Ostream& Foam::operator<<(Ostream& os, const lduMatrix& ldum)
+Foam::Ostream& Foam::operator<<(Ostream& os, const lduMatrix& mat)
 {
-    Switch hasLow = ldum.hasLower();
-    Switch hasDiag = ldum.hasDiag();
-    Switch hasUp = ldum.hasUpper();
+    os  << mat.hasLower() << token::SPACE
+        << mat.hasDiag() << token::SPACE
+        << mat.hasUpper() << token::SPACE;
 
-    os  << hasLow << token::SPACE << hasDiag << token::SPACE
-        << hasUp << token::SPACE;
-
-    if (hasLow)
+    if (mat.hasLower())
     {
-        os  << ldum.lower();
+        os  << mat.lower();
     }
 
-    if (hasDiag)
+    if (mat.hasDiag())
     {
-        os  << ldum.diag();
+        os  << mat.diag();
     }
 
-    if (hasUp)
+    if (mat.hasUpper())
     {
-        os  << ldum.upper();
+        os  << mat.upper();
     }
 
     os.check(FUNCTION_NAME);
@@ -413,54 +418,50 @@ Foam::Ostream& Foam::operator<<
     const InfoProxy<lduMatrix>& iproxy
 )
 {
-    const auto& ldum = *iproxy;
-
-    Switch hasLow = ldum.hasLower();
-    Switch hasDiag = ldum.hasDiag();
-    Switch hasUp = ldum.hasUpper();
+    const auto& mat = *iproxy;
 
-    os  << "Lower:" << hasLow
-        << " Diag:" << hasDiag
-        << " Upper:" << hasUp << endl;
+    os  << "Lower:" << Switch::name(mat.hasLower())
+        << " Diag:" << Switch::name(mat.hasDiag())
+        << " Upper:" << Switch::name(mat.hasUpper()) << endl;
 
-    if (hasLow)
+    if (mat.hasLower())
     {
-        os  << "lower:" << ldum.lower().size() << endl;
+        os  << "lower:" << mat.lower().size() << endl;
     }
-    if (hasDiag)
+    if (mat.hasDiag())
     {
-        os  << "diag :" << ldum.diag().size() << endl;
+        os  << "diag :" << mat.diag().size() << endl;
     }
-    if (hasUp)
+    if (mat.hasUpper())
     {
-        os  << "upper:" << ldum.upper().size() << endl;
+        os  << "upper:" << mat.upper().size() << endl;
     }
 
 
-    //if (hasLow)
+    //if (hasLower)
     //{
     //    os  << "lower contents:" << endl;
-    //    forAll(ldum.lower(), i)
+    //    forAll(mat.lower(), i)
     //    {
-    //        os  << "i:" << i << "\t" << ldum.lower()[i] << endl;
+    //        os  << "i:" << i << "\t" << mat.lower()[i] << endl;
     //    }
     //    os  << endl;
     //}
     //if (hasDiag)
     //{
     //    os  << "diag contents:" << endl;
-    //    forAll(ldum.diag(), i)
+    //    forAll(mat.diag(), i)
     //    {
-    //        os  << "i:" << i << "\t" << ldum.diag()[i] << endl;
+    //        os  << "i:" << i << "\t" << mat.diag()[i] << endl;
     //    }
     //    os  << endl;
     //}
-    //if (hasUp)
+    //if (hasUpper)
     //{
     //    os  << "upper contents:" << endl;
-    //    forAll(ldum.upper(), i)
+    //    forAll(mat.upper(), i)
     //    {
-    //        os  << "i:" << i << "\t" << ldum.upper()[i] << endl;
+    //        os  << "i:" << i << "\t" << mat.upper()[i] << endl;
     //    }
     //    os  << endl;
     //}
diff --git a/src/OpenFOAM/matrices/lduMatrix/lduMatrix/lduMatrix.H b/src/OpenFOAM/matrices/lduMatrix/lduMatrix/lduMatrix.H
index e13bb4cd05764a1561598805afbaa48c99372b00..a4dd1b0601732f8457b896258cc32025dcb2e88a 100644
--- a/src/OpenFOAM/matrices/lduMatrix/lduMatrix/lduMatrix.H
+++ b/src/OpenFOAM/matrices/lduMatrix/lduMatrix/lduMatrix.H
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2017 OpenFOAM Foundation
-    Copyright (C) 2016-2023 OpenCFD Ltd.
+    Copyright (C) 2016-2024 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -57,13 +57,14 @@ SourceFiles
 #include "primitiveFieldsFwd.H"
 #include "FieldField.H"
 #include "lduInterfaceFieldPtrsList.H"
+#include "solverPerformance.H"
 #include "typeInfo.H"
 #include "autoPtr.H"
 #include "runTimeSelectionTables.H"
-#include "solverPerformance.H"
 #include "InfoProxy.H"
 #include "Enum.H"
 #include "profilingTrigger.H"
+#include <functional>  // For reference_wrapper
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
@@ -89,8 +90,14 @@ class lduMatrix
         //const lduMesh& lduMesh_;
         std::reference_wrapper<const lduMesh> lduMesh_;
 
-        //- Coefficients (not including interfaces)
-        scalarField *lowerPtr_, *diagPtr_, *upperPtr_;
+        //- Diagonal coefficients
+        std::unique_ptr<scalarField> diagPtr_;
+
+        //- Off-diagonal coefficients (not including interfaces)
+        std::unique_ptr<scalarField> lowerPtr_;
+
+        //- Off-diagonal coefficients (not including interfaces)
+        std::unique_ptr<scalarField> upperPtr_;
 
 
 public:
@@ -115,6 +122,7 @@ public:
         static const scalar defaultTolerance;
 
 
+    // -----------------------------------------------------------------------
     //- Abstract base-class for lduMatrix solvers
     class solver
     {
@@ -331,6 +339,7 @@ public:
     };
 
 
+    // -----------------------------------------------------------------------
     //- Abstract base-class for lduMatrix smoothers
     class smoother
     {
@@ -478,6 +487,7 @@ public:
     };
 
 
+    // -----------------------------------------------------------------------
     //- Abstract base-class for lduMatrix preconditioners
     class preconditioner
     {
@@ -582,6 +592,8 @@ public:
     };
 
 
+    // -----------------------------------------------------------------------
+
     // Static Data
 
         // Declare name of the class and its debug switch
@@ -590,101 +602,101 @@ public:
 
     // Constructors
 
-        //- Construct given an LDU addressed mesh.
-        //  The coefficients are initially empty for subsequent setting.
-        lduMatrix(const lduMesh&);
+        //- Construct (without coefficients) for an LDU addressed mesh.
+        //  Not yet 'explicit' (legacy code may rely on implicit construct)
+        lduMatrix(const lduMesh& mesh);
 
-        //- Construct as copy
+        //- Copy construct
         lduMatrix(const lduMatrix&);
 
+        //- Move construct
+        lduMatrix(lduMatrix&&);
+
         //- Construct as copy or re-use as specified.
         lduMatrix(lduMatrix&, bool reuse);
 
         //- Construct given an LDU addressed mesh and an Istream
         //- from which the coefficients are read
-        lduMatrix(const lduMesh&, Istream&);
+        lduMatrix(const lduMesh& mesh, Istream& is);
 
 
     //- Destructor
-    ~lduMatrix();
+    ~lduMatrix() = default;
 
 
     // Member Functions
 
-        // Access to addressing
+    // Addressing
 
-            //- Return the LDU mesh from which the addressing is obtained
-            const lduMesh& mesh() const noexcept
-            {
-                return lduMesh_;
-            }
+        //- Return the LDU mesh from which the addressing is obtained
+        const lduMesh& mesh() const noexcept
+        {
+            return lduMesh_;
+        }
 
-            //- Set the LDU mesh containing the addressing is obtained
-            void setLduMesh(const lduMesh& m)
-            {
-                lduMesh_ = m;
-            }
+        //- Set the LDU mesh containing the addressing
+        void setLduMesh(const lduMesh& m)
+        {
+            lduMesh_ = m;
+        }
 
-            //- Return the LDU addressing
-            const lduAddressing& lduAddr() const
-            {
-                return mesh().lduAddr();
-            }
+        //- Return the LDU addressing
+        const lduAddressing& lduAddr() const
+        {
+            return mesh().lduAddr();
+        }
 
-            //- Return the patch evaluation schedule
-            const lduSchedule& patchSchedule() const
-            {
-                return lduAddr().patchSchedule();
-            }
+        //- Return the patch evaluation schedule
+        const lduSchedule& patchSchedule() const
+        {
+            return mesh().lduAddr().patchSchedule();
+        }
 
 
-        // Access to coefficients
+    // Coefficients
 
-            scalarField& lower();
-            scalarField& diag();
-            scalarField& upper();
+        const scalarField& diag() const;
+        const scalarField& upper() const;
+        const scalarField& lower() const;
 
-            // Size with externally provided sizes (for constructing with 'fake'
-            // mesh in GAMG)
+        scalarField& diag();
+        scalarField& upper();
+        scalarField& lower();
 
-                scalarField& lower(const label size);
-                scalarField& diag(const label nCoeffs);
-                scalarField& upper(const label nCoeffs);
+        // Size with externally provided sizes
+        // (for constructing with 'fake' mesh in GAMG)
 
+        scalarField& diag(label size);
+        scalarField& upper(label nCoeffs);
+        scalarField& lower(label nCoeffs);
 
-            const scalarField& lower() const;
-            const scalarField& diag() const;
-            const scalarField& upper() const;
 
-            bool hasDiag() const noexcept
-            {
-                return (diagPtr_);
-            }
+    // Characteristics
 
-            bool hasUpper() const noexcept
-            {
-                return (upperPtr_);
-            }
+        //- The matrix type (empty, diagonal, symmetric, ...)
+        word matrixTypeName() const;
 
-            bool hasLower() const noexcept
-            {
-                return (lowerPtr_);
-            }
+        bool hasDiag() const noexcept { return bool(diagPtr_); }
+        bool hasUpper() const noexcept { return bool(upperPtr_); }
+        bool hasLower() const noexcept { return bool(lowerPtr_); }
 
-            bool diagonal() const noexcept
-            {
-                return (diagPtr_ && !lowerPtr_ && !upperPtr_);
-            }
+        //- Matrix has diagonal only
+        bool diagonal() const noexcept
+        {
+            return (diagPtr_ && !lowerPtr_ && !upperPtr_);
+        }
 
-            bool symmetric() const noexcept
-            {
-                return (diagPtr_ && (!lowerPtr_ && upperPtr_));
-            }
+        //- Matrix is symmetric
+        bool symmetric() const noexcept
+        {
+            return (diagPtr_ && !lowerPtr_ && upperPtr_);
+        }
 
-            bool asymmetric() const noexcept
-            {
-                return (diagPtr_ && lowerPtr_ && upperPtr_);
-            }
+        //- Matrix is asymmetric (ie, full)
+        bool asymmetric() const noexcept
+        {
+            return (diagPtr_ && lowerPtr_ && upperPtr_);
+        }
 
 
         // Operations
@@ -801,8 +813,12 @@ public:
 
     // Member Operators
 
+        //- Copy assignment
         void operator=(const lduMatrix&);
 
+        //- Move assignment
+        void operator=(lduMatrix&&);
+
         void negate();
 
         void operator+=(const lduMatrix&);
diff --git a/src/OpenFOAM/matrices/lduMatrix/lduMatrix/lduMatrixOperations.C b/src/OpenFOAM/matrices/lduMatrix/lduMatrix/lduMatrixOperations.C
index 4d307f57100f385789528a2a34001fa70f0f4217..1e83a03c75b85e8d277ed75820bfc21bca41861a 100644
--- a/src/OpenFOAM/matrices/lduMatrix/lduMatrix/lduMatrixOperations.C
+++ b/src/OpenFOAM/matrices/lduMatrix/lduMatrix/lduMatrixOperations.C
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2016 OpenFOAM Foundation
-    Copyright (C) 2019 OpenCFD Ltd.
+    Copyright (C) 2019-2024 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -86,7 +86,7 @@ void Foam::lduMatrix::sumMagOffDiag
 }
 
 
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+// * * * * * * * * * * * * * * * Member Operators  * * * * * * * * * * * * * //
 
 void Foam::lduMatrix::operator=(const lduMatrix& A)
 {
@@ -95,38 +95,49 @@ void Foam::lduMatrix::operator=(const lduMatrix& A)
         return;  // Self-assignment is a no-op
     }
 
-    if (A.lowerPtr_)
+    if (A.hasLower())
     {
         lower() = A.lower();
     }
-    else if (lowerPtr_)
+    else
     {
-        delete lowerPtr_;
-        lowerPtr_ = nullptr;
+        lowerPtr_.reset(nullptr);
     }
 
-    if (A.upperPtr_)
+    if (A.hasUpper())
     {
         upper() = A.upper();
     }
-    else if (upperPtr_)
+    else
     {
-        delete upperPtr_;
-        upperPtr_ = nullptr;
+        upperPtr_.reset(nullptr);
     }
 
-    if (A.diagPtr_)
+    if (A.hasDiag())
     {
         diag() = A.diag();
     }
 }
 
 
+void Foam::lduMatrix::operator=(lduMatrix&& A)
+{
+    if (this == &A)
+    {
+        return;  // Self-assignment is a no-op
+    }
+
+    diagPtr_ = std::move(A.diagPtr_);
+    upperPtr_ = std::move(A.upperPtr_);
+    lowerPtr_ = std::move(A.lowerPtr_);
+}
+
+
 void Foam::lduMatrix::negate()
 {
-    if (lowerPtr_)
+    if (diagPtr_)
     {
-        lowerPtr_->negate();
+        diagPtr_->negate();
     }
 
     if (upperPtr_)
@@ -134,16 +145,16 @@ void Foam::lduMatrix::negate()
         upperPtr_->negate();
     }
 
-    if (diagPtr_)
+    if (lowerPtr_)
     {
-        diagPtr_->negate();
+        lowerPtr_->negate();
     }
 }
 
 
 void Foam::lduMatrix::operator+=(const lduMatrix& A)
 {
-    if (A.diagPtr_)
+    if (A.hasDiag())
     {
         diag() += A.diag();
     }
@@ -168,7 +179,7 @@ void Foam::lduMatrix::operator+=(const lduMatrix& A)
     }
     else if (asymmetric() && A.symmetric())
     {
-        if (A.upperPtr_)
+        if (A.hasUpper())
         {
             lower() += A.upper();
             upper() += A.upper();
@@ -187,12 +198,12 @@ void Foam::lduMatrix::operator+=(const lduMatrix& A)
     }
     else if (diagonal())
     {
-        if (A.upperPtr_)
+        if (A.hasUpper())
         {
             upper() = A.upper();
         }
 
-        if (A.lowerPtr_)
+        if (A.hasLower())
         {
             lower() = A.lower();
         }
@@ -206,15 +217,8 @@ void Foam::lduMatrix::operator+=(const lduMatrix& A)
         {
             WarningInFunction
                 << "Unknown matrix type combination" << nl
-                << "    this :"
-                << " diagonal:" << diagonal()
-                << " symmetric:" << symmetric()
-                << " asymmetric:" << asymmetric() << nl
-                << "    A    :"
-                << " diagonal:" << A.diagonal()
-                << " symmetric:" << A.symmetric()
-                << " asymmetric:" << A.asymmetric()
-                << endl;
+                << "    this : " << this->matrixTypeName()
+                << "    A    : " << A.matrixTypeName() << endl;
         }
     }
 }
@@ -247,7 +251,7 @@ void Foam::lduMatrix::operator-=(const lduMatrix& A)
     }
     else if (asymmetric() && A.symmetric())
     {
-        if (A.upperPtr_)
+        if (A.hasUpper())
         {
             lower() -= A.upper();
             upper() -= A.upper();
@@ -266,12 +270,12 @@ void Foam::lduMatrix::operator-=(const lduMatrix& A)
     }
     else if (diagonal())
     {
-        if (A.upperPtr_)
+        if (A.hasUpper())
         {
             upper() = -A.upper();
         }
 
-        if (A.lowerPtr_)
+        if (A.hasLower())
         {
             lower() = -A.lower();
         }
@@ -285,15 +289,8 @@ void Foam::lduMatrix::operator-=(const lduMatrix& A)
         {
             WarningInFunction
                 << "Unknown matrix type combination" << nl
-                << "    this :"
-                << " diagonal:" << diagonal()
-                << " symmetric:" << symmetric()
-                << " asymmetric:" << asymmetric() << nl
-                << "    A    :"
-                << " diagonal:" << A.diagonal()
-                << " symmetric:" << A.symmetric()
-                << " asymmetric:" << A.asymmetric()
-                << endl;
+                << "    this : " << this->matrixTypeName()
+                << "    A    : " << A.matrixTypeName() << endl;
         }
     }
 }
diff --git a/src/OpenFOAM/matrices/scalarMatrices/scalarMatrices.C b/src/OpenFOAM/matrices/scalarMatrices/scalarMatrices.C
index 39d3cc37b50ce5b88f5362489809e55162e5bed0..1bd42a36080dad51a0be66547ee16e168659252a 100644
--- a/src/OpenFOAM/matrices/scalarMatrices/scalarMatrices.C
+++ b/src/OpenFOAM/matrices/scalarMatrices/scalarMatrices.C
@@ -6,6 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2016 OpenFOAM Foundation
+    Copyright (C) 2024 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -48,17 +49,20 @@ void Foam::LUDecompose
     label& sign
 )
 {
-    label m = matrix.m();
-    scalar vv[m];
+    const label size = matrix.m();
+
+    pivotIndices.resize_nocopy(size);
+
+    List<scalar> vv(size);
     sign = 1;
 
-    for (label i = 0; i < m; ++i)
+    for (label i = 0; i < size; ++i)
     {
         scalar largestCoeff = 0.0;
         scalar temp;
         const scalar* __restrict__ matrixi = matrix[i];
 
-        for (label j = 0; j < m; ++j)
+        for (label j = 0; j < size; ++j)
         {
             if ((temp = mag(matrixi[j])) > largestCoeff)
             {
@@ -75,7 +79,7 @@ void Foam::LUDecompose
         vv[i] = 1.0/largestCoeff;
     }
 
-    for (label j = 0; j < m; ++j)
+    for (label j = 0; j < size; ++j)
     {
         scalar* __restrict__ matrixj = matrix[j];
 
@@ -94,7 +98,7 @@ void Foam::LUDecompose
         label iMax = 0;
 
         scalar largestCoeff = 0.0;
-        for (label i = j; i < m; ++i)
+        for (label i = j; i < size; ++i)
         {
             scalar* __restrict__ matrixi = matrix[i];
             scalar sum = matrixi[j];
@@ -120,7 +124,7 @@ void Foam::LUDecompose
         {
             scalar* __restrict__ matrixiMax = matrix[iMax];
 
-            for (label k = 0; k < m; ++k)
+            for (label k = 0; k < size; ++k)
             {
                 std::swap(matrixj[k], matrixiMax[k]);
             }
@@ -134,11 +138,11 @@ void Foam::LUDecompose
             matrixj[j] = SMALL;
         }
 
-        if (j != m-1)
+        if (j != size-1)
         {
             scalar rDiag = 1.0/matrixj[j];
 
-            for (label i = j + 1; i < m; ++i)
+            for (label i = j + 1; i < size; ++i)
             {
                 matrix(i, j) *= rDiag;
             }
@@ -150,7 +154,7 @@ void Foam::LUDecompose
 void Foam::LUDecompose(scalarSymmetricSquareMatrix& matrix)
 {
     // Store result in upper triangular part of matrix
-    label size = matrix.m();
+    const label size = matrix.m();
 
     // Set upper triangular parts to zero.
     for (label j = 0; j < size; ++j)
@@ -223,7 +227,7 @@ void Foam::multiply
             << abort(FatalError);
     }
 
-    ans = scalarRectangularMatrix(A.m(), C.n(), Zero);
+    ans = scalarRectangularMatrix(A.m(), C.n(), Foam::zero{});
 
     for (label i = 0; i < A.m(); ++i)
     {
diff --git a/src/OpenFOAM/matrices/scalarMatrices/scalarMatrices.H b/src/OpenFOAM/matrices/scalarMatrices/scalarMatrices.H
index d6ba156a2bcaa6479fd82f12d9c12415ca39f3a8..8035cdfebfe01854b606a7c68fec852a3e5c53bd 100644
--- a/src/OpenFOAM/matrices/scalarMatrices/scalarMatrices.H
+++ b/src/OpenFOAM/matrices/scalarMatrices/scalarMatrices.H
@@ -74,19 +74,21 @@ void solve
     const List<Type>& source
 );
 
-//- LU decompose the matrix with pivoting
+//- LU decompose the matrix with pivoting.
 void LUDecompose
 (
     scalarSquareMatrix& matrix,
+    //! [out] size is adjusted as required
     labelList& pivotIndices
 );
 
 //- LU decompose the matrix with pivoting.
-//- sign is -1 for odd number of row interchanges and 1 for even number.
 void LUDecompose
 (
     scalarSquareMatrix& matrix,
+    //! [out] size is adjusted as required
     labelList& pivotIndices,
+    //! [out] is -1 for odd number of row interchanges and 1 for even number
     label& sign
 );
 
diff --git a/src/OpenFOAM/matrices/scalarMatrices/scalarMatricesTemplates.C b/src/OpenFOAM/matrices/scalarMatrices/scalarMatricesTemplates.C
index 0c3ae682287d35e9666a09d32407975a65780643..7a66cbe6d3459f5bdeef62d2cb0649dd655053f2 100644
--- a/src/OpenFOAM/matrices/scalarMatrices/scalarMatricesTemplates.C
+++ b/src/OpenFOAM/matrices/scalarMatrices/scalarMatricesTemplates.C
@@ -216,7 +216,7 @@ void Foam::LUsolve
     List<Type>& sourceSol
 )
 {
-    labelList pivotIndices(matrix.m());
+    labelList pivotIndices;
     LUDecompose(matrix, pivotIndices);
     LUBacksubstitute(matrix, pivotIndices, sourceSol);
 }