diff --git a/src/lagrangian/basic/particle/particle.C b/src/lagrangian/basic/particle/particle.C
index 2ddea84408d4090b3182072da41ef260c50d466b..3168a6e630e7816bf249e175c7c09ca68dd48241 100644
--- a/src/lagrangian/basic/particle/particle.C
+++ b/src/lagrangian/basic/particle/particle.C
@@ -5,8 +5,8 @@
     \\  /    A nd           | www.openfoam.com
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
-    Copyright (C) 2011-2017, 2020 OpenFOAM Foundation
-    Copyright (C) 2018-2021 OpenCFD Ltd.
+    Copyright (C) 2011-2017, 2020-2021 OpenFOAM Foundation
+    Copyright (C) 2018-2022 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -433,9 +433,11 @@ void Foam::particle::locate
     // Perturbing displacement to avoid zero in case position is the
     // cellCentre
     const vector displacement =
+    (
         position
       - mesh_.cellCentres()[celli_]
-      + vector(VSMALL, VSMALL, VSMALL);
+      + vector(VSMALL, VSMALL, VSMALL)
+    );
 
     // Loop all cell tets to find the one containing the position. Track
     // through each tet from the cell centre. If a tet contains the position
@@ -443,13 +445,13 @@ void Foam::particle::locate
     const Foam::cell& c = mesh_.cells()[celli_];
     scalar minF = VGREAT;
     label minTetFacei = -1, minTetPti = -1;
-    forAll(c, cellTetFacei)
+    for (const label meshFacei : c)
     {
-        const Foam::face& f = mesh_.faces()[c[cellTetFacei]];
+        const Foam::face& f = mesh_.faces()[meshFacei];
         for (label tetPti = 1; tetPti < f.size() - 1; ++tetPti)
         {
             coordinates_ = barycentric(1, 0, 0, 0);
-            tetFacei_ = c[cellTetFacei];
+            tetFacei_ = meshFacei;
             tetPti_ = tetPti;
             facei_ = -1;
 
@@ -525,8 +527,8 @@ Foam::particle::particle
     tetFacei_(tetFacei),
     tetPti_(tetPti),
     facei_(-1),
-    stepFraction_(1.0),
-    behind_(0.0),
+    stepFraction_(1),
+    behind_(0),
     nBehind_(0),
     origProc_(Pstream::myProcNo()),
     origId_(getNewParticleID())
@@ -546,8 +548,8 @@ Foam::particle::particle
     tetFacei_(-1),
     tetPti_(-1),
     facei_(-1),
-    stepFraction_(1.0),
-    behind_(0.0),
+    stepFraction_(1),
+    behind_(0),
     nBehind_(0),
     origProc_(Pstream::myProcNo()),
     origId_(getNewParticleID())
@@ -579,8 +581,8 @@ Foam::particle::particle
     tetFacei_(tetFacei),
     tetPti_(tetPti),
     facei_(-1),
-    stepFraction_(1.0),
-    behind_(0.0),
+    stepFraction_(1),
+    behind_(0),
     nBehind_(0),
     origProc_(Pstream::myProcNo()),
     origId_(getNewParticleID())
@@ -743,15 +745,15 @@ Foam::scalar Foam::particle::trackToStationaryTri
 
     if (debug)
     {
-        Pout<< "Local displacement = " << Tx1 << "/" << detA << endl;
+        Pout<< "Local displacement = " << Tx1 << '/' << detA << endl;
     }
 
     // Calculate the hit fraction
     label iH = -1;
-    scalar muH = detA <= 0 ? VGREAT : 1/detA;
+    scalar muH = detA > VSMALL ? 1/detA : VGREAT;
     for (label i = 0; i < 4; ++ i)
     {
-        if (Tx1[i] < - detA*SMALL)
+        if (Tx1[i] < - VSMALL && Tx1[i] < - mag(detA)*SMALL)
         {
             scalar mu = - y0[i]/Tx1[i];
 
@@ -770,6 +772,15 @@ Foam::scalar Foam::particle::trackToStationaryTri
         }
     }
 
+    // If there has been no hit on a degenerate or inverted tet then the
+    // displacement must be within the round off error. Advance the step
+    // fraction without moving and return.
+    if (iH == -1 && muH == VGREAT)
+    {
+        stepFraction_ += fraction;
+        return 0;
+    }
+
     // Set the new coordinates
     barycentric yH = y0 + muH*Tx1;
 
@@ -903,7 +914,7 @@ Foam::scalar Foam::particle::trackToMovingTri
 
     // Calculate the hit fraction
     label iH = -1;
-    scalar muH = detA[0] <= 0 ? VGREAT : 1/detA[0];
+    scalar muH = detA[0] > VSMALL ? 1/detA[0] : VGREAT;
     for (label i = 0; i < 4; ++i)
     {
         const Roots<3> mu = hitEqn[i].roots();
@@ -913,7 +924,8 @@ Foam::scalar Foam::particle::trackToMovingTri
             if
             (
                 mu.type(j) == roots::real
-             && hitEqn[i].derivative(mu[j]) < - detA[0]*SMALL
+             && hitEqn[i].derivative(mu[j]) < - VSMALL
+             && hitEqn[i].derivative(mu[j]) < - mag(detA[0])*SMALL
             )
             {
                 if (debug)
@@ -928,7 +940,7 @@ Foam::scalar Foam::particle::trackToMovingTri
                     const scalar detAH = detAEqn.value(mu[j]);
 
                     Pout<< "Hit on tet face " << i << " at local coordinate "
-                        << (std::isnormal(detAH) ? name(yH/detAH) : "???")
+                        << (mag(detAH) > VSMALL ? name(yH/detAH) : "???")
                         << ", " << mu[j]*detA[0]*100 << "% of the "
                         << "way along the track" << endl;
 
@@ -946,6 +958,15 @@ Foam::scalar Foam::particle::trackToMovingTri
         }
     }
 
+    // If there has been no hit on a degenerate or inverted tet then the
+    // displacement must be within the round off error. Advance the step
+    // fraction without moving and return.
+    if (iH == -1 && muH == VGREAT)
+    {
+        stepFraction_ += fraction;
+        return 0;
+    }
+
     // Set the new coordinates
     barycentric yH
     (
@@ -962,7 +983,7 @@ Foam::scalar Foam::particle::trackToMovingTri
     // distance and therefore can be of the static mesh type. This has not yet
     // been implemented.
     const scalar detAH = detAEqn.value(muH);
-    if (!std::isnormal(detAH))
+    if (mag(detAH) < VSMALL)
     {
         FatalErrorInFunction
             << "A moving tet collapsed onto a particle. This is not supported. "
@@ -1038,7 +1059,7 @@ Foam::scalar Foam::particle::trackToTri
     label& tetTriI
 )
 {
-    if ((mesh_.moving() && (stepFraction_ != 1 || fraction != 0)))
+    if (mesh_.moving() && (stepFraction_ != 1 || fraction != 0))
     {
         return trackToMovingTri(displacement, fraction, tetTriI);
     }