diff --git a/src/OpenFOAM/meshes/polyMesh/polyMesh.C b/src/OpenFOAM/meshes/polyMesh/polyMesh.C
index 5aba0e0d2f48d0e364ebb85e2975125929fa1d4a..ea17e4c706fa3c89c8edc284edc19b96e07f7ceb 100644
--- a/src/OpenFOAM/meshes/polyMesh/polyMesh.C
+++ b/src/OpenFOAM/meshes/polyMesh/polyMesh.C
@@ -1202,12 +1202,12 @@ void Foam::polyMesh::movePoints(const pointField& newPoints)
 
         if (storeOldCellCentres_)
         {
-            oldCellCentresPtr_.clear();
+            oldCellCentresPtr_.reset(nullptr);
             oldCellCentresPtr_.reset(new pointField(cellCentres()));
         }
 
         // Mesh motion in the new time step
-        oldPointsPtr_.clear();
+        oldPointsPtr_.reset(nullptr);
         oldPointsPtr_.reset(new pointField(points_));
         curMotionTimeIndex_ = time().timeIndex();
     }
@@ -1276,7 +1276,7 @@ void Foam::polyMesh::movePoints(const pointField& newPoints)
     // have to clear any geometry. However your critical path still stays the
     // same so no time would be gained (unless the decomposition gets weighted).
     // Small benefit for lots of scope for problems so not done.
-    cellTreePtr_.clear();
+    cellTreePtr_.reset(nullptr);
 
     // Reset valid directions (could change with rotation)
     geometricD_ = Zero;
@@ -1304,8 +1304,8 @@ void Foam::polyMesh::movePoints(const pointField& newPoints)
 void Foam::polyMesh::resetMotion() const
 {
     curMotionTimeIndex_ = 0;
-    oldPointsPtr_.clear();
-    oldCellCentresPtr_.clear();
+    oldPointsPtr_.reset(nullptr);
+    oldCellCentresPtr_.reset(nullptr);
 }
 
 
diff --git a/src/OpenFOAM/meshes/polyMesh/polyMesh.H b/src/OpenFOAM/meshes/polyMesh/polyMesh.H
index f1331d9734d0e2ca4961413f928e12c4b2293617..534c4c5786c0980cc94cf609409480e319a4abbd 100644
--- a/src/OpenFOAM/meshes/polyMesh/polyMesh.H
+++ b/src/OpenFOAM/meshes/polyMesh/polyMesh.H
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2017, 2020 OpenFOAM Foundation
-    Copyright (C) 2018-2023 OpenCFD Ltd.
+    Copyright (C) 2018-2024 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -696,8 +696,8 @@ public:
             //- Clear addressing
             void clearAddressing(const bool isMeshUpdate = false);
 
-            //- Clear all geometry and addressing unnecessary for CFD
-            void clearOut();
+            //- Clear all geometry and addressing
+            void clearOut(const bool isMeshUpdate = false);
 
             //- Clear primitive data (points, faces and cells)
             void clearPrimitives();
diff --git a/src/OpenFOAM/meshes/polyMesh/polyMeshClear.C b/src/OpenFOAM/meshes/polyMesh/polyMeshClear.C
index a7d76831b7e8fc64715aea5b26226494e809f7cf..abf8ddea7405f468bbde573db6e3f00dd78c7ef6 100644
--- a/src/OpenFOAM/meshes/polyMesh/polyMeshClear.C
+++ b/src/OpenFOAM/meshes/polyMesh/polyMeshClear.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.
@@ -65,7 +65,7 @@ void Foam::polyMesh::clearGeom()
     solutionD_ = Zero;
 
     // Remove the cell tree
-    cellTreePtr_.clear();
+    cellTreePtr_.reset(nullptr);
 }
 
 
@@ -119,7 +119,7 @@ void Foam::polyMesh::updateGeomPoints
     solutionD_ = Zero;
 
     // Remove the cell tree
-    cellTreePtr_.clear();
+    cellTreePtr_.reset(nullptr);
 
     // Update local data
     points_.instance() = newPoints.instance();
@@ -150,12 +150,12 @@ void Foam::polyMesh::updateGeomPoints
 void Foam::polyMesh::clearAddressing(const bool isMeshUpdate)
 {
     DebugInFunction
-        << "Clearing topology  isMeshUpdate:" << isMeshUpdate << endl;
+        << "isMeshUpdate:" << isMeshUpdate << endl;
 
     if (isMeshUpdate)
     {
-        // Part of a mesh update. Keep meshObjects that have an updateMesh
-        // callback
+        // Part of a mesh update.
+        // Keep meshObjects that have an updateMesh callback
         meshObject::clearUpto
         <
             pointMesh,
@@ -197,10 +197,10 @@ void Foam::polyMesh::clearAddressing(const bool isMeshUpdate)
     cellZones_.clearAddressing();
 
     // Remove the stored tet base points
-    tetBasePtIsPtr_.clear();
+    tetBasePtIsPtr_.reset(nullptr);
 
     // Remove the cell tree
-    cellTreePtr_.clear();
+    cellTreePtr_.reset(nullptr);
 }
 
 
@@ -217,10 +217,10 @@ void Foam::polyMesh::clearPrimitives()
 }
 
 
-void Foam::polyMesh::clearOut()
+void Foam::polyMesh::clearOut(const bool isMeshUpdate)
 {
-    clearGeom();
-    clearAddressing();
+    clearGeom();  // not implementable?  isMeshUpdate
+    clearAddressing(isMeshUpdate);
 }
 
 
@@ -228,15 +228,15 @@ void Foam::polyMesh::clearTetBasePtIs()
 {
     DebugInFunction << "Clearing tet base points" << endl;
 
-    tetBasePtIsPtr_.clear();
+    tetBasePtIsPtr_.reset(nullptr);
 }
 
 
 void Foam::polyMesh::clearCellTree()
 {
-    DebugInFunction << "Clearing cell tree" << endl;
+    DebugInFunction << endl;
 
-    cellTreePtr_.clear();
+    cellTreePtr_.reset(nullptr);
 }
 
 
diff --git a/src/OpenFOAM/meshes/polyMesh/polyMeshUpdate.C b/src/OpenFOAM/meshes/polyMesh/polyMeshUpdate.C
index 2d89a7ef049ff4a139f4c1ef236f33b27a321bbd..f75b83302a30cc61d5295272fa222806b8d6e48f 100644
--- a/src/OpenFOAM/meshes/polyMesh/polyMeshUpdate.C
+++ b/src/OpenFOAM/meshes/polyMesh/polyMeshUpdate.C
@@ -24,9 +24,6 @@ License
     You should have received a copy of the GNU General Public License
     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
 
-Description
-    Update the polyMesh corresponding to the given map.
-
 \*---------------------------------------------------------------------------*/
 
 #include "polyMesh.H"
@@ -54,9 +51,10 @@ void Foam::polyMesh::updateMesh(const mapPolyMesh& mpm)
     cellZones_.clearAddressing();
 
     // Remove the stored tet base points
-    tetBasePtIsPtr_.clear();
+    tetBasePtIsPtr_.reset(nullptr);
+
     // Remove the cell tree
-    cellTreePtr_.clear();
+    cellTreePtr_.reset(nullptr);
 
     // Update parallel data
     if (globalMeshDataPtr_)
diff --git a/src/dynamicMesh/fvMeshDistribute/fvMeshDistribute.C b/src/dynamicMesh/fvMeshDistribute/fvMeshDistribute.C
index ffd40037f0d1c1c99e0405d2be796dc510132849..a3b18318a1528002513c84bdef029bc5700cfe1d 100644
--- a/src/dynamicMesh/fvMeshDistribute/fvMeshDistribute.C
+++ b/src/dynamicMesh/fvMeshDistribute/fvMeshDistribute.C
@@ -2017,7 +2017,14 @@ Foam::autoPtr<Foam::mapDistributePolyMesh> Foam::fvMeshDistribute::distribute
     // Remove meshPhi. Since this would otherwise disappear anyway
     // during topo changes and we have to guarantee that all the fields
     // can be sent.
+
+    // NOTE: could/should use (isMeshUpdate = true) for mesh_.clearOut()
+    // but the bottom level will do a clearGeom() and that doesn't seem
+    // to work particularly well with isMeshUpdate at all.
+    // re-visit if needed...
+
     mesh_.clearOut();
+
     mesh_.resetMotion();
 
     // Get data to send. Make sure is synchronised
diff --git a/src/engine/engineMesh/fvMotionSolverEngineMesh/fvMotionSolverEngineMesh.C b/src/engine/engineMesh/fvMotionSolverEngineMesh/fvMotionSolverEngineMesh.C
index a5b63a7ca90c259f3acb8a39b40ed5a484066c18..2d6bedee3aef7afe7a3e90b5a393ddf23cdc7c71 100644
--- a/src/engine/engineMesh/fvMotionSolverEngineMesh/fvMotionSolverEngineMesh.C
+++ b/src/engine/engineMesh/fvMotionSolverEngineMesh/fvMotionSolverEngineMesh.C
@@ -90,28 +90,28 @@ void Foam::fvMotionSolverEngineMesh::move()
 
     motionSolver_.solve();
 
-    if (engineDB_.foundObject<surfaceScalarField>("phi"))
-    {
-        surfaceScalarField& phi =
-            engineDB_.lookupObjectRef<surfaceScalarField>("phi");
 
-        const volScalarField& rho =
-            engineDB_.lookupObject<volScalarField>("rho");
+    auto* phiPtr = engineDB_.getObjectPtr<surfaceScalarField>("phi");
+
+    if (phiPtr)
+    {
+        auto& phi = *phiPtr;
 
-        const volVectorField& U =
-            engineDB_.lookupObject<volVectorField>("U");
+        const auto& rho = engineDB_.lookupObject<volScalarField>("rho");
+        const auto& U = engineDB_.lookupObject<volVectorField>("U");
 
-        bool absolutePhi = false;
-        if (moving())
+        const bool absolutePhi = moving();
+        if (absolutePhi)
         {
+            // cf. fvc::makeAbsolute
             phi += fvc::interpolate(rho)*fvc::meshPhi(rho, U);
-            absolutePhi = true;
         }
 
         movePoints(motionSolver_.curPoints());
 
         if (absolutePhi)
         {
+            // cf. fvc::makeRelative
             phi -= fvc::interpolate(rho)*fvc::meshPhi(rho, U);
         }
     }
diff --git a/src/engine/engineMesh/layeredEngineMesh/layeredEngineMesh.C b/src/engine/engineMesh/layeredEngineMesh/layeredEngineMesh.C
index 753285b438f77ac5855d86d1dd76ef37952e12e4..31575e631b38d030f35132c2e28624af718d6369 100644
--- a/src/engine/engineMesh/layeredEngineMesh/layeredEngineMesh.C
+++ b/src/engine/engineMesh/layeredEngineMesh/layeredEngineMesh.C
@@ -85,28 +85,28 @@ void Foam::layeredEngineMesh::move()
         }
     }
 
-    if (engineDB_.foundObject<surfaceScalarField>("phi"))
-    {
-        surfaceScalarField& phi =
-            engineDB_.lookupObjectRef<surfaceScalarField>("phi");
 
-        const volScalarField& rho =
-            engineDB_.lookupObject<volScalarField>("rho");
+    auto* phiPtr = engineDB_.getObjectPtr<surfaceScalarField>("phi");
+
+    if (phiPtr)
+    {
+        auto& phi = *phiPtr;
 
-        const volVectorField& U =
-            engineDB_.lookupObject<volVectorField>("U");
+        const auto& rho = engineDB_.lookupObject<volScalarField>("rho");
+        const auto& U = engineDB_.lookupObject<volVectorField>("U");
 
-        bool absolutePhi = false;
-        if (moving())
+        const bool absolutePhi = moving();
+        if (absolutePhi)
         {
+            // cf. fvc::makeAbsolute
             phi += fvc::interpolate(rho)*fvc::meshPhi(rho, U);
-            absolutePhi = true;
         }
 
         movePoints(newPoints);
 
         if (absolutePhi)
         {
+            // cf. fvc::makeRelative
             phi -= fvc::interpolate(rho)*fvc::meshPhi(rho, U);
         }
     }
diff --git a/src/finiteVolume/fvMesh/fvMesh.C b/src/finiteVolume/fvMesh/fvMesh.C
index 3b8de62d6a705ccc9f3af48db1d6717667368b22..b55557f6be0dd236e04aae09da87794cc6c30753 100644
--- a/src/finiteVolume/fvMesh/fvMesh.C
+++ b/src/finiteVolume/fvMesh/fvMesh.C
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2017,2022 OpenFOAM Foundation
-    Copyright (C) 2016-2023 OpenCFD Ltd.
+    Copyright (C) 2016-2024 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -219,22 +219,30 @@ void Foam::fvMesh::storeOldVol(const scalarField& V)
 }
 
 
-void Foam::fvMesh::clearOutLocal()
+void Foam::fvMesh::clearOutLocal(const bool isMeshUpdate)
 {
     clearGeom();
     surfaceInterpolation::clearOut();
 
-    clearAddressing();
+    clearAddressing(isMeshUpdate);
 
     // Clear mesh motion flux
-    deleteDemandDrivenData(phiPtr_);
+    phiPtr_.reset(nullptr);
 }
 
 
-void Foam::fvMesh::clearOut()
+void Foam::fvMesh::clearOut(const bool isMeshUpdate)
 {
-    clearOutLocal();
-    polyMesh::clearOut();
+    clearOutLocal(isMeshUpdate);
+
+    polyMesh::clearOut(isMeshUpdate);
+}
+
+
+void Foam::fvMesh::clearMeshPhi()
+{
+    // Clear mesh motion flux
+    phiPtr_.reset(nullptr);
 }
 
 
@@ -306,7 +314,7 @@ bool Foam::fvMesh::init(const bool doInit)
         (
             rio,
             *this,
-            dimensionedScalar(dimVol, Zero)
+            dimensionedScalar(dimVol, Foam::zero{})
         );
 
         // Set the moving flag early in case demand-driven geometry
@@ -324,11 +332,14 @@ bool Foam::fvMesh::init(const bool doInit)
         DebugInFunction
             << "Detected meshPhi: " << rio.objectRelPath() << nl;
 
-        phiPtr_ = new surfaceScalarField
+        // Clear mesh motion flux
+        phiPtr_.reset(nullptr);
+
+        phiPtr_ = std::make_unique<surfaceScalarField>
         (
             rio,
             *this,
-            dimensionedScalar(dimVol/dimTime, Zero)
+            dimensionedScalar(dimVol/dimTime, Foam::zero{})
         );
 
         // Set the moving flag early in case demand-driven geometry
@@ -942,7 +953,7 @@ void Foam::fvMesh::movePoints(const pointField& p)
         DebugInFunction<< "Creating initial meshPhi field" << endl;
 
         // Create mesh motion flux
-        phiPtr_ = new surfaceScalarField
+        phiPtr_ = std::make_unique<surfaceScalarField>
         (
             IOobject
             (
@@ -954,7 +965,7 @@ void Foam::fvMesh::movePoints(const pointField& p)
                 IOobject::NO_REGISTER
             ),
             *this,
-            dimensionedScalar(dimVolume/dimTime, Zero)
+            dimensionedScalar(dimVolume/dimTime, Foam::zero{})
         );
     }
     else
@@ -1046,10 +1057,10 @@ void Foam::fvMesh::updateMesh(const mapPolyMesh& mpm)
     if (phiPtr_)
     {
         // Mesh moving and topology change. Recreate meshPhi
-        deleteDemandDrivenData(phiPtr_);
+        phiPtr_.reset(nullptr);
 
         // Create mesh motion flux
-        phiPtr_ = new surfaceScalarField
+        phiPtr_ = std::make_unique<surfaceScalarField>
         (
             IOobject
             (
@@ -1061,7 +1072,7 @@ void Foam::fvMesh::updateMesh(const mapPolyMesh& mpm)
                 IOobject::NO_REGISTER
             ),
             *this,
-            dimensionedScalar(dimVolume/dimTime, Zero)
+            dimensionedScalar(dimVolume/dimTime, Foam::zero{})
         );
     }
 
diff --git a/src/finiteVolume/fvMesh/fvMesh.H b/src/finiteVolume/fvMesh/fvMesh.H
index 869016e6a5db18d2e64731353b361d9ae0a8576b..a53d90899bc74529851508537499e6a1bd467e0c 100644
--- a/src/finiteVolume/fvMesh/fvMesh.H
+++ b/src/finiteVolume/fvMesh/fvMesh.H
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2017,2022 OpenFOAM Foundation
-    Copyright (C) 2016-2023 OpenCFD Ltd.
+    Copyright (C) 2016-2024 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -90,13 +90,13 @@ class fvMesh
 {
 protected:
 
-    // Private data
+    // Private Data
 
         //- Boundary mesh
         fvBoundaryMesh boundary_;
 
 
-    // Demand-driven data
+    // Demand-Driven Data
 
         mutable fvMeshLduAddressing* lduPtr_;
 
@@ -128,7 +128,7 @@ protected:
         mutable slicedSurfaceVectorField* CfPtr_;
 
         //- Face motion fluxes
-        mutable surfaceScalarField* phiPtr_;
+        mutable std::unique_ptr<surfaceScalarField> phiPtr_;
 
 
     // Private Member Functions
@@ -149,7 +149,7 @@ protected:
             void clearAddressing(const bool isMeshUpdate = false);
 
             //- Clear local-only storage (geometry, addressing etc)
-            void clearOutLocal();
+            void clearOutLocal(const bool isMeshUpdate = false);
 
             //- Preserve old volume(s)
             void storeOldVol(const scalarField&);
@@ -495,7 +495,7 @@ public:
         // Edit
 
             //- Clear all geometry and addressing
-            void clearOut();
+            void clearOut(const bool isMeshUpdate = false);
 
             //- Update mesh corresponding to the given map
             virtual void updateMesh(const mapPolyMesh& mpm);
@@ -517,7 +517,10 @@ public:
             //- these fvPatches.
             void removeFvBoundary();
 
-            //- Return cell face motion fluxes (or null)
+            //- Clear cell face motion fluxes
+            void clearMeshPhi();
+
+            //- Return cell face motion fluxes, if any (can be nullptr)
             refPtr<surfaceScalarField> setPhi();
 
             //- Return old-time cell volumes
diff --git a/src/finiteVolume/fvMesh/fvMeshGeometry.C b/src/finiteVolume/fvMesh/fvMeshGeometry.C
index 4b34dc5e27502a4e257bb75b5eb5a08c2fd68609..57e83225127746c8e7144467e849584363360d16 100644
--- a/src/finiteVolume/fvMesh/fvMeshGeometry.C
+++ b/src/finiteVolume/fvMesh/fvMeshGeometry.C
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2017,2022 OpenFOAM Foundation
-    Copyright (C) 2020-2022 OpenCFD Ltd.
+    Copyright (C) 2020-2024 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -427,7 +427,7 @@ const Foam::surfaceScalarField& Foam::fvMesh::phi() const
     // mesh motion fluxes if the time has been incremented
     if (!time().subCycling() && phiPtr_->timeIndex() != time().timeIndex())
     {
-        (*phiPtr_) = dimensionedScalar(dimVolume/dimTime, Zero);
+        (*phiPtr_) = dimensionedScalar(dimVolume/dimTime, Foam::zero{});
     }
 
     phiPtr_->setOriented();
@@ -438,17 +438,12 @@ const Foam::surfaceScalarField& Foam::fvMesh::phi() const
 
 Foam::refPtr<Foam::surfaceScalarField> Foam::fvMesh::setPhi()
 {
-    if (!phiPtr_)
-    {
-        return nullptr;
-    }
-    else
-    {
-        // Return non-const reference
-        refPtr<surfaceScalarField> p;
-        p.ref(*phiPtr_);
-        return p;
-    }
+    refPtr<surfaceScalarField> phiref;
+
+    // Return non-const reference, or nullptr if not available
+    phiref.ref(phiPtr_.get());
+
+    return phiref;
 }