diff --git a/src/OpenFOAM/db/IOstreams/Pstreams/UPstream.H b/src/OpenFOAM/db/IOstreams/Pstreams/UPstream.H
index acbd44c17d00377fba110b96677867ef29fd02a2..13d477dcfa025a6705a38a34f8db90d5236d58ce 100644
--- a/src/OpenFOAM/db/IOstreams/Pstreams/UPstream.H
+++ b/src/OpenFOAM/db/IOstreams/Pstreams/UPstream.H
@@ -593,6 +593,33 @@ public:
         //  A no-op for non-parallel. No special treatment for null requests.
         static void addRequest(UPstream::Request& req);
 
+        //- Non-blocking comms: cancel and free outstanding request.
+        //- Corresponds to MPI_Cancel() + MPI_Request_free()
+        //  A no-op if parRun() == false
+        //  if there are no pending requests,
+        //  or if the index is out-of-range (0 to nRequests)
+        static void cancelRequest(const label i);
+
+        //- Non-blocking comms: cancel and free outstanding request.
+        //- Corresponds to MPI_Cancel() + MPI_Request_free()
+        //  A no-op if parRun() == false
+        static void cancelRequest(UPstream::Request& req);
+
+        //- Non-blocking comms: cancel and free outstanding requests.
+        //- Corresponds to MPI_Cancel() + MPI_Request_free()
+        //  A no-op if parRun() == false or list is empty
+        static void cancelRequests(UList<UPstream::Request>& requests);
+
+        //- Non-blocking comms: free outstanding request.
+        //- Corresponds to MPI_Request_free()
+        //  A no-op if parRun() == false
+        static void freeRequest(UPstream::Request& req);
+
+        //- Non-blocking comms: free outstanding requests.
+        //- Corresponds to MPI_Request_free()
+        //  A no-op if parRun() == false or list is empty
+        static void freeRequests(UList<UPstream::Request>& requests);
+
         //- Wait until all requests (from position onwards) have finished.
         //- Corresponds to MPI_Waitall()
         //  A no-op if parRun() == false,
@@ -699,7 +726,7 @@ public:
         //  if there are no pending requests,
         //  or if the indices are out-of-range (0 to nRequests)
         //  Each finished request parameter is set to -1 (ie, done).
-        static bool finishedRequestPair(label& req1, label& req2);
+        static bool finishedRequestPair(label& req0, label& req1);
 
         //- Non-blocking comms: wait for both requests to finish.
         //- Corresponds to pair of MPI_Wait()
@@ -707,7 +734,7 @@ public:
         //  if there are no pending requests,
         //  or if the indices are out-of-range (0 to nRequests)
         //  Each finished request parameter is set to -1 (ie, done).
-        static void waitRequestPair(label& req1, label& req2);
+        static void waitRequestPair(label& req0, label& req1);
 
 
     // General
@@ -1271,11 +1298,17 @@ public:
         //- Reset to default constructed value (MPI_REQUEST_NULL)
         void reset() noexcept;
 
-        //- Same as calling UPstream::waitRequest()
-        void wait() { UPstream::waitRequest(*this); }
+        //- Same as calling UPstream::cancelRequest()
+        void cancel() { UPstream::cancelRequest(*this); }
+
+        //- Same as calling UPstream::freeRequest()
+        void free() { UPstream::freeRequest(*this); }
 
         //- Same as calling UPstream::finishedRequest()
         bool finished() { return UPstream::finishedRequest(*this); }
+
+        //- Same as calling UPstream::waitRequest()
+        void wait() { UPstream::waitRequest(*this); }
 };
 
 
diff --git a/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaceFields/processorGAMGInterfaceField/processorGAMGInterfaceField.C b/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaceFields/processorGAMGInterfaceField/processorGAMGInterfaceField.C
index 0e4b2215352ab2a844766c4ebdac0b93dac9fd08..d5a1ac5e9331edbab2b115d735e06c06f230c5cb 100644
--- a/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaceFields/processorGAMGInterfaceField/processorGAMGInterfaceField.C
+++ b/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaceFields/processorGAMGInterfaceField/processorGAMGInterfaceField.C
@@ -171,9 +171,8 @@ void Foam::processorGAMGInterfaceField::updateInterfaceMatrix
     {
         // Fast path: consume straight from receive buffer
 
-        // Require receive data. Update the send request state.
-        // OR: UPstream::waitRequestPair(recvRequest_, sendRequest_);
-
+        // Require receive data.
+        // Only update the send request state.
         UPstream::waitRequest(recvRequest_); recvRequest_ = -1;
         if (UPstream::finishedRequest(sendRequest_)) sendRequest_ = -1;
     }
diff --git a/src/Pstream/dummy/UPstreamRequest.C b/src/Pstream/dummy/UPstreamRequest.C
index 551e766f37491fa985225dc671f2f478d30d6609..f4962ffd451e7ee6e1ae302ba3001bb488d38b90 100644
--- a/src/Pstream/dummy/UPstreamRequest.C
+++ b/src/Pstream/dummy/UPstreamRequest.C
@@ -53,7 +53,14 @@ Foam::label Foam::UPstream::nRequests() noexcept { return 0; }
 
 void Foam::UPstream::resetRequests(const label n) {}
 
-void Foam::UPstream::addRequest(UPstream::Request& req) {}
+void Foam::UPstream::addRequest(UPstream::Request&) {}
+
+void Foam::UPstream::cancelRequest(const label i) {}
+void Foam::UPstream::cancelRequest(UPstream::Request&) {}
+void Foam::UPstream::cancelRequests(UList<UPstream::Request>&) {}
+
+void Foam::UPstream::freeRequest(UPstream::Request&) {}
+void Foam::UPstream::freeRequests(UList<UPstream::Request>&) {}
 
 void Foam::UPstream::waitRequests(const label pos, label len) {}
 void Foam::UPstream::waitRequests(UList<UPstream::Request>&) {}
@@ -96,18 +103,18 @@ bool Foam::UPstream::finishedRequests(UList<UPstream::Request>&)
 }
 
 
-bool Foam::UPstream::finishedRequestPair(label& req1, label& req2)
+bool Foam::UPstream::finishedRequestPair(label& req0, label& req1)
 {
+    req0 = -1;
     req1 = -1;
-    req2 = -1;
     return true;
 }
 
 
-void Foam::UPstream::waitRequestPair(label& req1, label& req2)
+void Foam::UPstream::waitRequestPair(label& req0, label& req1)
 {
+    req0 = -1;
     req1 = -1;
-    req2 = -1;
 }
 
 
diff --git a/src/Pstream/mpi/UPstreamRequest.C b/src/Pstream/mpi/UPstreamRequest.C
index eb8cfc9251188db9ca0dfc0ffe5d9adc103279b9..4f9467fd225b0a7fc3f63ca7eca8019a617bc582 100644
--- a/src/Pstream/mpi/UPstreamRequest.C
+++ b/src/Pstream/mpi/UPstreamRequest.C
@@ -88,6 +88,118 @@ void Foam::UPstream::addRequest(UPstream::Request& req)
 }
 
 
+void Foam::UPstream::cancelRequest(const label i)
+{
+    // No-op for non-parallel, or out-of-range (eg, placeholder indices)
+    if
+    (
+        !UPstream::parRun()
+     || i < 0
+     || i >= PstreamGlobals::outstandingRequests_.size()
+    )
+    {
+        return;
+    }
+
+    {
+        auto& request = PstreamGlobals::outstandingRequests_[i];
+        if (MPI_REQUEST_NULL != request)  // Active handle is mandatory
+        {
+            MPI_Cancel(&request);
+            MPI_Request_free(&request);  //<- Sets to MPI_REQUEST_NULL
+        }
+    }
+}
+
+
+void Foam::UPstream::cancelRequest(UPstream::Request& req)
+{
+    // No-op for non-parallel
+    if (!UPstream::parRun())
+    {
+        return;
+    }
+
+    {
+        MPI_Request request = PstreamDetail::Request::get(req);
+        if (MPI_REQUEST_NULL != request)  // Active handle is mandatory
+        {
+            MPI_Cancel(&request);
+            MPI_Request_free(&request);
+        }
+        req = UPstream::Request(MPI_REQUEST_NULL);  // Now inactive
+    }
+}
+
+
+void Foam::UPstream::cancelRequests(UList<UPstream::Request>& requests)
+{
+    // No-op for non-parallel
+    if (!UPstream::parRun())
+    {
+        return;
+    }
+
+    for (auto& req : requests)
+    {
+        MPI_Request request = PstreamDetail::Request::get(req);
+        if (MPI_REQUEST_NULL != request)  // Active handle is mandatory
+        {
+            MPI_Cancel(&request);
+            MPI_Request_free(&request);
+        }
+        req = UPstream::Request(MPI_REQUEST_NULL);  // Now inactive
+    }
+}
+
+
+void Foam::UPstream::freeRequest(UPstream::Request& req)
+{
+    // No-op for non-parallel
+    if (!UPstream::parRun())
+    {
+        return;
+    }
+
+    {
+        MPI_Request request = PstreamDetail::Request::get(req);
+        if (MPI_REQUEST_NULL != request)  // Active handle is mandatory
+        {
+            // if (cancel)
+            // {
+            //     MPI_Cancel(&request);
+            // }
+            MPI_Request_free(&request);
+        }
+        req = UPstream::Request(MPI_REQUEST_NULL);  // Now inactive
+    }
+}
+
+
+void Foam::UPstream::freeRequests(UList<UPstream::Request>& requests)
+{
+    // No-op for non-parallel
+    if (!UPstream::parRun())
+    {
+        return;
+    }
+
+    for (auto& req : requests)
+    {
+        MPI_Request request = PstreamDetail::Request::get(req);
+        if (MPI_REQUEST_NULL != request)  // Active handle is mandatory
+        {
+            // if (cancel)
+            // {
+            //     MPI_Cancel(&request);
+            // }
+            MPI_Request_free(&request);
+        }
+        req = UPstream::Request(MPI_REQUEST_NULL);  // Now inactive
+    }
+}
+
+
 void Foam::UPstream::waitRequests(const label pos, label len)
 {
     // No-op for non-parallel, no pending requests or out-of-range
@@ -178,7 +290,7 @@ void Foam::UPstream::waitRequests(UList<UPstream::Request>& requests)
     {
         MPI_Request request = PstreamDetail::Request::get(req);
 
-        if (MPI_REQUEST_NULL != request)
+        if (MPI_REQUEST_NULL != request)  // Apply some prefiltering
         {
             waitRequests[count] = request;
             ++count;
@@ -187,7 +299,7 @@ void Foam::UPstream::waitRequests(UList<UPstream::Request>& requests)
 
     if (!count)
     {
-        // Early exit: has NULL requests only
+        // No active request handles
         return;
     }
 
@@ -422,8 +534,8 @@ Foam::label Foam::UPstream::waitAnyRequest(UList<UPstream::Request>& requests)
 //
 /// void Foam::UPstream::waitRequests
 /// (
-///     UPstream::Request& req1,
-///     UPstream::Request& req2
+///     UPstream::Request& req0,
+///     UPstream::Request& req1
 /// )
 /// {
 ///     // No-op for non-parallel
@@ -435,22 +547,22 @@ Foam::label Foam::UPstream::waitAnyRequest(UList<UPstream::Request>& requests)
 ///     int count = 0;
 ///     MPI_Request waitRequests[2];
 ///
-///     waitRequests[count] = PstreamDetail::Request::get(req1);
+///     waitRequests[count] = PstreamDetail::Request::get(req0);
 ///     if (MPI_REQUEST_NULL != waitRequests[count])
 ///     {
-///         // Flag in advance as being handled
-///         req1 = UPstream::Request(MPI_REQUEST_NULL);
 ///         ++count;
 ///     }
 ///
-///     waitRequests[count] = PstreamDetail::Request::get(req2);
+///     waitRequests[count] = PstreamDetail::Request::get(req1);
 ///     if (MPI_REQUEST_NULL != waitRequests[count])
 ///     {
-///         // Flag in advance as being handled
-///         req2 = UPstream::Request(MPI_REQUEST_NULL);
 ///         ++count;
 ///     }
 ///
+///     // Flag in advance as being handled
+///     req0 = UPstream::Request(MPI_REQUEST_NULL);
+///     req1 = UPstream::Request(MPI_REQUEST_NULL);
+///
 ///     if (!count)
 ///     {
 ///         return;
@@ -544,8 +656,7 @@ void Foam::UPstream::waitRequest(UPstream::Request& req)
 
     profilingPstream::addWaitTime();
 
-    // Handled, reset to MPI_REQUEST_NULL
-    req = UPstream::Request(MPI_REQUEST_NULL);
+    req = UPstream::Request(MPI_REQUEST_NULL);  // Now inactive
 }
 
 
@@ -605,7 +716,7 @@ bool Foam::UPstream::finishedRequest(UPstream::Request& req)
 
     if (flag)
     {
-        // Success: reset request to MPI_REQUEST_NULL
+        // Success: now inactive
         req = UPstream::Request(MPI_REQUEST_NULL);
     }
 
@@ -687,7 +798,7 @@ bool Foam::UPstream::finishedRequests(UList<UPstream::Request>& requests)
     {
         MPI_Request request = PstreamDetail::Request::get(req);
 
-        if (MPI_REQUEST_NULL != request)
+        if (MPI_REQUEST_NULL != request)  // Apply some prefiltering
         {
             waitRequests[count] = request;
             ++count;
@@ -696,7 +807,7 @@ bool Foam::UPstream::finishedRequests(UList<UPstream::Request>& requests)
 
     if (!count)
     {
-        // Early exit: has NULL requests only
+        // No active handles
         return true;
     }
 
@@ -736,45 +847,60 @@ bool Foam::UPstream::finishedRequests(UList<UPstream::Request>& requests)
 }
 
 
-bool Foam::UPstream::finishedRequestPair(label& req1, label& req2)
+bool Foam::UPstream::finishedRequestPair(label& req0, label& req1)
 {
     // No-op for non-parallel
     if (!UPstream::parRun())
     {
+        req0 = -1;
         req1 = -1;
-        req2 = -1;
         return true;
     }
 
-    int count = 0;
+    bool anyActive = false;
     MPI_Request waitRequests[2];
 
-    // In range?
-    if (req1 >= 0 && req1 < PstreamGlobals::outstandingRequests_.size())
+    // No-op for out-of-range (eg, placeholder indices)
+
+    if (req0 >= 0 && req0 < PstreamGlobals::outstandingRequests_.size())
     {
-        waitRequests[0] = PstreamGlobals::outstandingRequests_[req1];
-        ++count;
+        waitRequests[0] = PstreamGlobals::outstandingRequests_[req0];
     }
     else
     {
         waitRequests[0] = MPI_REQUEST_NULL;
-        req1 = -1;
     }
 
-    // No-op for non-parallel, or out-of-range (eg, placeholder indices)
-    if (req2 >= 0 && req2 < PstreamGlobals::outstandingRequests_.size())
+    if (req1 >= 0 && req1 < PstreamGlobals::outstandingRequests_.size())
     {
-        waitRequests[1] = PstreamGlobals::outstandingRequests_[req2];
-        ++count;
+        waitRequests[1] = PstreamGlobals::outstandingRequests_[req1];
     }
     else
     {
         waitRequests[1] = MPI_REQUEST_NULL;
-        req2 = -1;
     }
 
-    if (!count)
+    if (MPI_REQUEST_NULL != waitRequests[0])  // An active handle
+    {
+        anyActive = true;
+    }
+    else
+    {
+        req0 = -1;
+    }
+
+    if (MPI_REQUEST_NULL != waitRequests[1])  // An active handle
+    {
+        anyActive = true;
+    }
+    else
     {
+        req1 = -1;
+    }
+
+    if (!anyActive)
+    {
+        // No active handles
         return true;
     }
 
@@ -807,41 +933,41 @@ bool Foam::UPstream::finishedRequestPair(label& req1, label& req2)
         // No active request handles.
         // Slight pedantic, but copy back requests in case they were altered
 
-        if (req1 >= 0)
+        if (req0 >= 0)
         {
-            PstreamGlobals::outstandingRequests_[req1] = waitRequests[0];
+            PstreamGlobals::outstandingRequests_[req0] = waitRequests[0];
         }
 
-        if (req2 >= 0)
+        if (req1 >= 0)
         {
-            PstreamGlobals::outstandingRequests_[req2] = waitRequests[1];
+            PstreamGlobals::outstandingRequests_[req1] = waitRequests[1];
         }
 
         // Flag indices as 'done'
+        req0 = -1;
         req1 = -1;
-        req2 = -1;
         return true;
     }
 
     // Copy back requests to their 'stack' locations
     for (int i = 0; i < outcount; ++i)
     {
-        int reqid = indices[i];
+        const int idx = indices[i];
 
-        if (reqid == 0)
+        if (idx == 0)
         {
-            if (req1 >= 0)
+            if (req0 >= 0)
             {
-                PstreamGlobals::outstandingRequests_[req1] = waitRequests[0];
-                req1 = -1;
+                PstreamGlobals::outstandingRequests_[req0] = waitRequests[0];
+                req0 = -1;
             }
         }
-        if (reqid == 1)
+        if (idx == 1)
         {
-            if (req2 >= 0)
+            if (req1 >= 0)
             {
-                PstreamGlobals::outstandingRequests_[req2] = waitRequests[1];
-                req2 = -1;
+                PstreamGlobals::outstandingRequests_[req1] = waitRequests[1];
+                req1 = -1;
             }
         }
     }
@@ -850,13 +976,13 @@ bool Foam::UPstream::finishedRequestPair(label& req1, label& req2)
 }
 
 
-void Foam::UPstream::waitRequestPair(label& req1, label& req2)
+void Foam::UPstream::waitRequestPair(label& req0, label& req1)
 {
     // No-op for non-parallel. Flag indices as 'done'
     if (!UPstream::parRun())
     {
+        req0 = -1;
         req1 = -1;
-        req2 = -1;
         return;
     }
 
@@ -864,32 +990,37 @@ void Foam::UPstream::waitRequestPair(label& req1, label& req2)
     MPI_Request waitRequests[2];
 
     // No-op for out-of-range (eg, placeholder indices)
-    if (req1 >= 0 && req1 < PstreamGlobals::outstandingRequests_.size())
-    {
-        waitRequests[0] = PstreamGlobals::outstandingRequests_[req1];
-        ++count;
-    }
-    else
-    {
-        waitRequests[0] = MPI_REQUEST_NULL;
-        req1 = -1;  // Flag as 'done'
-    }
+    // Prefilter inactive handles
 
-    // No-op for out-of-range (eg, placeholder indices)
-    if (req2 >= 0 && req2 < PstreamGlobals::outstandingRequests_.size())
+    if (req0 >= 0 && req0 < PstreamGlobals::outstandingRequests_.size())
     {
-        waitRequests[1] = PstreamGlobals::outstandingRequests_[req2];
-        ++count;
+        waitRequests[count] = PstreamGlobals::outstandingRequests_[req0];
+        PstreamGlobals::outstandingRequests_[req0] = MPI_REQUEST_NULL;
+
+        if (MPI_REQUEST_NULL != waitRequests[count])  // An active handle
+        {
+            ++count;
+        }
     }
-    else
+
+    if (req1 >= 0 && req1 < PstreamGlobals::outstandingRequests_.size())
     {
-        waitRequests[1] = MPI_REQUEST_NULL;
-        req2 = -1;  // Flag as 'done'
+        waitRequests[count] = PstreamGlobals::outstandingRequests_[req1];
+        PstreamGlobals::outstandingRequests_[req1] = MPI_REQUEST_NULL;
+
+        if (MPI_REQUEST_NULL != waitRequests[count])  // An active handle
+        {
+            ++count;
+        }
     }
 
-    // Early exit
+    // Flag in advance as being handled
+    req0 = -1;
+    req1 = -1;
+
     if (!count)
     {
+        // No active handles
         return;
     }
 
@@ -904,23 +1035,6 @@ void Foam::UPstream::waitRequestPair(label& req1, label& req2)
     }
 
     profilingPstream::addWaitTime();
-
-    // Copy back requests to their 'stack' locations
-    // and flag index as done
-
-    if (req1 >= 0)
-    {
-        PstreamGlobals::outstandingRequests_[req1] = waitRequests[0];
-    }
-
-    if (req2 >= 0)
-    {
-        PstreamGlobals::outstandingRequests_[req2] = waitRequests[1];
-    }
-
-    // Flag indices as 'done'
-    req1 = -1;
-    req2 = -1;
 }
 
 
diff --git a/src/overset/lduPrimitiveProcessorInterface/GAMG/calculatedProcessorGAMGInterfaceField.C b/src/overset/lduPrimitiveProcessorInterface/GAMG/calculatedProcessorGAMGInterfaceField.C
index adf9b74a17a539ff422f74c73651b166d05e7d9b..81526549aea059ae870eaf48a6e088de2fe7eb2e 100644
--- a/src/overset/lduPrimitiveProcessorInterface/GAMG/calculatedProcessorGAMGInterfaceField.C
+++ b/src/overset/lduPrimitiveProcessorInterface/GAMG/calculatedProcessorGAMGInterfaceField.C
@@ -172,9 +172,8 @@ void Foam::calculatedProcessorGAMGInterfaceField::updateInterfaceMatrix
     {
         // Fast path: consume straight from receive buffer
 
-        // Require receive data. Update the send request state.
-        // OR: UPstream::waitRequestPair(recvRequest_, sendRequest_);
-
+        // Require receive data.
+        // Only update the send request state.
         UPstream::waitRequest(recvRequest_); recvRequest_ = -1;
         if (UPstream::finishedRequest(sendRequest_)) sendRequest_ = -1;
     }