From 98c42479f693586404489a02fef06a8057a98fc8 Mon Sep 17 00:00:00 2001
From: Mark Olesen <Mark.Olesen@esi-group.com>
Date: Thu, 4 May 2023 17:45:58 +0200
Subject: [PATCH] ENH: relax processorField waiting requirements

- for interface polling previously required that both send and recv
  requests were completed before evaluating (values or matrix update).
  However, only the recv needs to be complete, which helps disentangle
  the inter-rank waiting.

  NB: this change is possible following (1f5cf3958bc8) that replaced
      UPstream::resetRequests() call in favour of UPstream::waitRequests()
---
 .../lduCalculatedProcessorField.C             |  32 +++--
 .../lduCalculatedProcessorField.H             |  90 ++++++-------
 .../lduPrimitiveProcessorInterface.C          |   1 +
 .../lduPrimitiveProcessorInterface.H          |  78 ++++++------
 .../lduInterfaceField/lduInterfaceField.H     |  65 +++++-----
 .../processor/processorFaPatchField.C         |  55 ++++----
 .../processor/processorFaPatchField.H         | 114 +++++++++--------
 .../calculatedProcessorFvPatchField.C         |  35 +++--
 .../calculatedProcessorFvPatchField.H         | 117 +++++++++--------
 .../processor/processorFvPatchField.C         |  67 +++++-----
 .../processor/processorFvPatchField.H         | 120 +++++++++---------
 11 files changed, 412 insertions(+), 362 deletions(-)

diff --git a/src/OpenFOAM/matrices/lduMatrix/lduAddressing/lduInterface/lduCalculatedProcessorField/lduCalculatedProcessorField.C b/src/OpenFOAM/matrices/lduMatrix/lduAddressing/lduInterface/lduCalculatedProcessorField/lduCalculatedProcessorField.C
index d60692571d1..0fb082115b0 100644
--- a/src/OpenFOAM/matrices/lduMatrix/lduAddressing/lduInterface/lduCalculatedProcessorField/lduCalculatedProcessorField.C
+++ b/src/OpenFOAM/matrices/lduMatrix/lduAddressing/lduInterface/lduCalculatedProcessorField/lduCalculatedProcessorField.C
@@ -58,12 +58,25 @@ Foam::lduCalculatedProcessorField<Type>::lduCalculatedProcessorField
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
 template<class Type>
-bool Foam::lduCalculatedProcessorField<Type>::ready() const
+bool Foam::lduCalculatedProcessorField<Type>::all_ready() const
 {
     return UPstream::finishedRequestPair(recvRequest_, sendRequest_);
 }
 
 
+template<class Type>
+bool Foam::lduCalculatedProcessorField<Type>::ready() const
+{
+    const bool ok = UPstream::finishedRequest(recvRequest_);
+    if (ok)
+    {
+        recvRequest_ = -1;
+        if (UPstream::finishedRequest(sendRequest_)) sendRequest_ = -1;
+    }
+    return ok;
+}
+
+
 template<class Type>
 void Foam::lduCalculatedProcessorField<Type>::initInterfaceMatrixUpdate
 (
@@ -77,10 +90,11 @@ void Foam::lduCalculatedProcessorField<Type>::initInterfaceMatrixUpdate
     const Pstream::commsTypes commsType
 ) const
 {
-    if (!this->ready())
+    if (!this->all_ready())
     {
         FatalErrorInFunction
-            << "Outstanding request."
+            << "Outstanding request(s) on interface "
+            //<< procInterface_.name()
             << abort(FatalError);
     }
 
@@ -167,12 +181,12 @@ void Foam::lduCalculatedProcessorField<Type>::updateInterfaceMatrix
         return;
     }
 
-    // Require receive data. Update the send request state.
-    // OR: UPstream::waitRequestPair(recvRequest_, sendRequest_);
-
-    UPstream::waitRequest(recvRequest_); recvRequest_ = -1;
-    if (UPstream::finishedRequest(sendRequest_)) sendRequest_ = -1;
-
+    {
+        // Require receive data.
+        // Only update the send request state.
+        UPstream::waitRequest(recvRequest_); recvRequest_ = -1;
+        if (UPstream::finishedRequest(sendRequest_)) sendRequest_ = -1;
+    }
 
     // Consume straight from receive buffer. Note use of our own
     // helper to avoid using fvPatch addressing
diff --git a/src/OpenFOAM/matrices/lduMatrix/lduAddressing/lduInterface/lduCalculatedProcessorField/lduCalculatedProcessorField.H b/src/OpenFOAM/matrices/lduMatrix/lduAddressing/lduInterface/lduCalculatedProcessorField/lduCalculatedProcessorField.H
index bb2cba44e48..c9af9ec11d4 100644
--- a/src/OpenFOAM/matrices/lduMatrix/lduAddressing/lduInterface/lduCalculatedProcessorField/lduCalculatedProcessorField.H
+++ b/src/OpenFOAM/matrices/lduMatrix/lduAddressing/lduInterface/lduCalculatedProcessorField/lduCalculatedProcessorField.H
@@ -103,6 +103,9 @@ protected:
             const solveScalarField& vals
         ) const;
 
+        //- Receive and send requests have both completed
+        virtual bool all_ready() const;
+
 
 public:
 
@@ -112,14 +115,13 @@ public:
 
     // Constructors
 
-        //- Construct from patch and internal field
-        lduCalculatedProcessorField
+        //- Construct from ldu interface
+        explicit lduCalculatedProcessorField
         (
             const lduInterface& interface
-            //const Field<Type>&
         );
 
-        //- Construct as copy
+        //- Copy construct
         lduCalculatedProcessorField
         (
             const lduCalculatedProcessorField<Type>&
@@ -132,48 +134,9 @@ public:
 
     // Member Functions
 
-    // Access
-
-        //- Return communicator used for comms
-        virtual label comm() const
-        {
-            return procInterface_.comm();
-        }
-
-        //- Return processor number
-        virtual int myProcNo() const
-        {
-            return procInterface_.myProcNo();
-        }
-
-        //- Return neighbour processor number
-        virtual int neighbProcNo() const
-        {
-            return procInterface_.myProcNo();
-        }
-
-        //- Is the transform required
-        virtual bool doTransform() const
-        {
-            return false;
-        }
-
-        //- Return face transformation tensor
-        virtual const tensorField& forwardT() const
-        {
-            return procInterface_.forwardT();
-        }
-
-        //- Return rank of component for transform
-        virtual int rank() const
-        {
-            return pTraits<Type>::rank;
-        }
-
-
     // Evaluation
 
-        //- Is all data available
+        //- Are all (receive) data available?
         virtual bool ready() const;
 
         //- Initialise neighbour matrix update
@@ -231,6 +194,45 @@ public:
         {
             NotImplemented;
         }
+
+
+    // Processor coupled interface functions
+
+        //- Return communicator used for communication
+        virtual label comm() const
+        {
+            return procInterface_.comm();
+        }
+
+        //- Return processor number
+        virtual int myProcNo() const
+        {
+            return procInterface_.myProcNo();
+        }
+
+        //- Return neighbour processor number
+        virtual int neighbProcNo() const
+        {
+            return procInterface_.myProcNo();
+        }
+
+        //- Is the transform required
+        virtual bool doTransform() const
+        {
+            return false;
+        }
+
+        //- Return face transformation tensor
+        virtual const tensorField& forwardT() const
+        {
+            return procInterface_.forwardT();
+        }
+
+        //- Return rank of component for transform
+        virtual int rank() const
+        {
+            return pTraits<Type>::rank;
+        }
 };
 
 
diff --git a/src/OpenFOAM/matrices/lduMatrix/lduAddressing/lduInterface/lduPrimitiveProcessorInterface.C b/src/OpenFOAM/matrices/lduMatrix/lduAddressing/lduInterface/lduPrimitiveProcessorInterface.C
index 48074e2e3ea..3f91831e909 100644
--- a/src/OpenFOAM/matrices/lduMatrix/lduAddressing/lduInterface/lduPrimitiveProcessorInterface.C
+++ b/src/OpenFOAM/matrices/lduMatrix/lduAddressing/lduInterface/lduPrimitiveProcessorInterface.C
@@ -136,4 +136,5 @@ Foam::lduPrimitiveProcessorInterface::internalFieldTransfer
     return processorLduInterface::receive<label>(commsType, faceCells_.size());
 }
 
+
 // ************************************************************************* //
diff --git a/src/OpenFOAM/matrices/lduMatrix/lduAddressing/lduInterface/lduPrimitiveProcessorInterface.H b/src/OpenFOAM/matrices/lduMatrix/lduAddressing/lduInterface/lduPrimitiveProcessorInterface.H
index 7314557de61..57063c1f2db 100644
--- a/src/OpenFOAM/matrices/lduMatrix/lduAddressing/lduInterface/lduPrimitiveProcessorInterface.H
+++ b/src/OpenFOAM/matrices/lduMatrix/lduAddressing/lduInterface/lduPrimitiveProcessorInterface.H
@@ -58,6 +58,7 @@ class lduPrimitiveProcessorInterface
 {
     // Private Data
 
+        //- Addressing
         const labelList faceCells_;
 
         //- My processor rank in communicator
@@ -76,19 +77,18 @@ class lduPrimitiveProcessorInterface
         const label comm_;
 
 
-    // Private Member Functions
-
-
-        //- No copy assignment
-        void operator=(const lduPrimitiveProcessorInterface&) = delete;
-
-
 public:
 
     //- Runtime type information
     TypeNameNoDebug("processorInterface");
 
 
+    // Generated Methods
+
+        //- No copy assignment
+        void operator=(const lduPrimitiveProcessorInterface&) = delete;
+
+
     // Constructors
 
         //- Construct from components
@@ -164,46 +164,46 @@ public:
             ) const;
 
 
-        // Processor interface functions
+    // Processor interface functions
 
-            //- Return communicator used for sending
-            virtual label comm() const
-            {
-                return comm_;
-            }
+        //- Return communicator used for sending
+        virtual label comm() const
+        {
+            return comm_;
+        }
 
-            //- Return processor number (rank in communicator)
-            virtual int myProcNo() const
-            {
-                return myProcNo_;
-            }
+        //- Return processor number (rank in communicator)
+        virtual int myProcNo() const
+        {
+            return myProcNo_;
+        }
 
-            //- Return neighbour processor number (rank in communicator)
-            virtual int neighbProcNo() const
-            {
-                return neighbProcNo_;
-            }
+        //- Return neighbour processor number (rank in communicator)
+        virtual int neighbProcNo() const
+        {
+            return neighbProcNo_;
+        }
 
-            //- Return face transformation tensor
-            virtual const tensorField& forwardT() const
-            {
-                return forwardT_;
-            }
+        //- Return face transformation tensor
+        virtual const tensorField& forwardT() const
+        {
+            return forwardT_;
+        }
 
-            //- Return message tag used for sending
-            virtual int tag() const
-            {
-                return tag_;
-            }
+        //- Return message tag used for sending
+        virtual int tag() const
+        {
+            return tag_;
+        }
 
 
-        // Edit
+    // Edit
 
-            //- Return message tag used for sending
-            int& tag()
-            {
-                return tag_;
-            }
+        //- Message tag used for sending (modifiable)
+        int& tag()
+        {
+            return tag_;
+        }
 };
 
 
diff --git a/src/OpenFOAM/matrices/lduMatrix/lduAddressing/lduInterfaceFields/lduInterfaceField/lduInterfaceField.H b/src/OpenFOAM/matrices/lduMatrix/lduAddressing/lduInterfaceFields/lduInterfaceField/lduInterfaceField.H
index f61e43e1d74..3eac6cb2d64 100644
--- a/src/OpenFOAM/matrices/lduMatrix/lduAddressing/lduInterfaceFields/lduInterfaceField/lduInterfaceField.H
+++ b/src/OpenFOAM/matrices/lduMatrix/lduAddressing/lduInterfaceFields/lduInterfaceField/lduInterfaceField.H
@@ -40,9 +40,9 @@ SourceFiles
 #define Foam_lduInterfaceField_H
 
 #include "lduInterface.H"
+#include "lduAddressing.H"
 #include "primitiveFieldsFwd.H"
 #include "Pstream.H"
-#include "lduAddressing.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
@@ -100,42 +100,43 @@ public:
 
     // Member Functions
 
-        // Access
+        //- Return the interface
+        const lduInterface& interface() const noexcept
+        {
+            return interface_;
+        }
 
-            //- Return the interface
-            const lduInterface& interface() const noexcept
-            {
-                return interface_;
-            }
+        //- Return the interface type
+        virtual const word& interfaceFieldType() const
+        {
+            return type();
+        }
 
-            //- Return the interface type
-            virtual const word& interfaceFieldType() const
-            {
-                return type();
-            }
 
+    // Coupled Interface
 
-        // Coupled interface matrix update
+        //- Are all (receive) data available?
+        virtual bool ready() const
+        {
+            return true;
+        }
 
-            //- Whether matrix has been updated
-            bool updatedMatrix() const noexcept
-            {
-                return updatedMatrix_;
-            }
-
-            //- Set matrix as update-to-date, return the previous value
-            bool updatedMatrix(bool flag) const noexcept
-            {
-                bool old(updatedMatrix_);
-                updatedMatrix_ = flag;
-                return old;
-            }
-
-            //- Is all data available
-            virtual bool ready() const
-            {
-                return true;
-            }
+        //- Whether matrix has been updated
+        bool updatedMatrix() const noexcept
+        {
+            return updatedMatrix_;
+        }
+
+        //- Set matrix as update-to-date, return the previous value
+        bool updatedMatrix(bool flag) const noexcept
+        {
+            bool old(updatedMatrix_);
+            updatedMatrix_ = flag;
+            return old;
+        }
+
+
+        // Coupled interface matrix update
 
             //- Initialise neighbour matrix update.
             //- Add/subtract coupled contributions to matrix
diff --git a/src/finiteArea/fields/faPatchFields/constraint/processor/processorFaPatchField.C b/src/finiteArea/fields/faPatchFields/constraint/processor/processorFaPatchField.C
index 70935bcf792..fe31f3761ca 100644
--- a/src/finiteArea/fields/faPatchFields/constraint/processor/processorFaPatchField.C
+++ b/src/finiteArea/fields/faPatchFields/constraint/processor/processorFaPatchField.C
@@ -84,10 +84,10 @@ Foam::processorFaPatchField<Type>::processorFaPatchField
             << " in file " << this->internalField().objectPath()
             << exit(FatalError);
     }
-    if (debug && !ptf.ready())
+    if (debug && !ptf.all_ready())
     {
         FatalErrorInFunction
-            << "On patch " << procPatch_.name() << " outstanding request."
+            << "Outstanding request(s) on patch " << procPatch_.name()
             << abort(FatalError);
     }
 }
@@ -141,10 +141,10 @@ Foam::processorFaPatchField<Type>::processorFaPatchField
     scalarSendBuf_(std::move(ptf.scalarSendBuf_)),
     scalarRecvBuf_(std::move(ptf.scalarRecvBuf_))
 {
-    if (debug && !ptf.ready())
+    if (debug && !ptf.all_ready())
     {
         FatalErrorInFunction
-            << "On patch " << procPatch_.name() << " outstanding request."
+            << "Outstanding request(s) on patch " << procPatch_.name()
             << abort(FatalError);
     }
 }
@@ -162,10 +162,10 @@ Foam::processorFaPatchField<Type>::processorFaPatchField
     sendRequest_(-1),
     recvRequest_(-1)
 {
-    if (debug && !ptf.ready())
+    if (debug && !ptf.all_ready())
     {
         FatalErrorInFunction
-            << "On patch " << procPatch_.name() << " outstanding request."
+            << "Outstanding request(s) on patch " << procPatch_.name()
             << abort(FatalError);
     }
 }
@@ -174,12 +174,25 @@ Foam::processorFaPatchField<Type>::processorFaPatchField
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
 template<class Type>
-bool Foam::processorFaPatchField<Type>::ready() const
+bool Foam::processorFaPatchField<Type>::all_ready() const
 {
     return UPstream::finishedRequestPair(recvRequest_, sendRequest_);
 }
 
 
+template<class Type>
+bool Foam::processorFaPatchField<Type>::ready() const
+{
+    const bool ok = UPstream::finishedRequest(recvRequest_);
+    if (ok)
+    {
+        recvRequest_ = -1;
+        if (UPstream::finishedRequest(sendRequest_)) sendRequest_ = -1;
+    }
+    return ok;
+}
+
+
 template<class Type>
 Foam::tmp<Foam::Field<Type>>
 Foam::processorFaPatchField<Type>::patchNeighbourField() const
@@ -187,8 +200,7 @@ Foam::processorFaPatchField<Type>::patchNeighbourField() const
     if (debug && !this->ready())
     {
         FatalErrorInFunction
-            << "On patch " << procPatch_.name()
-            << " outstanding request."
+            << "Outstanding request on patch " << procPatch_.name()
             << abort(FatalError);
     }
     return *this;
@@ -259,9 +271,8 @@ void Foam::processorFaPatchField<Type>::evaluate
         {
             // Fast path. Received into *this
 
-            // 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;
         }
@@ -303,11 +314,10 @@ void Foam::processorFaPatchField<Type>::initInterfaceMatrixUpdate
     if (commsType == UPstream::commsTypes::nonBlocking)
     {
         // Fast path.
-        if (debug && !this->ready())
+        if (debug && !this->all_ready())
         {
             FatalErrorInFunction
-                << "On patch " << procPatch_.name()
-                << " outstanding request."
+                << "Outstanding request(s) on patch " << procPatch_.name()
                 << abort(FatalError);
         }
 
@@ -368,9 +378,8 @@ void Foam::processorFaPatchField<Type>::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;
     }
@@ -411,11 +420,10 @@ void Foam::processorFaPatchField<Type>::initInterfaceMatrixUpdate
     if (commsType == UPstream::commsTypes::nonBlocking)
     {
         // Fast path.
-        if (debug && !this->ready())
+        if (debug && !this->all_ready())
         {
             FatalErrorInFunction
-                << "On patch " << procPatch_.name()
-                << " outstanding request."
+                << "Outstanding request(s) on patch " << procPatch_.name()
                 << abort(FatalError);
         }
 
@@ -475,9 +483,8 @@ void Foam::processorFaPatchField<Type>::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/finiteArea/fields/faPatchFields/constraint/processor/processorFaPatchField.H b/src/finiteArea/fields/faPatchFields/constraint/processor/processorFaPatchField.H
index 9d903ffb676..960b70a2245 100644
--- a/src/finiteArea/fields/faPatchFields/constraint/processor/processorFaPatchField.H
+++ b/src/finiteArea/fields/faPatchFields/constraint/processor/processorFaPatchField.H
@@ -88,6 +88,12 @@ class processorFaPatchField
             mutable solveScalarField scalarRecvBuf_;
 
 
+    // Private Member Functions
+
+        //- Receive and send requests have both completed
+        virtual bool all_ready() const;
+
+
 public:
 
     //- Runtime type information
@@ -164,33 +170,30 @@ public:
     ~processorFaPatchField() = default;
 
 
-    // Member functions
+    // Member Functions
 
-        // Access
+    // Coupling
 
-            //- Return true if running parallel
-            virtual bool coupled() const
-            {
-                return Pstream::parRun();
-            }
+        //- The patch field is coupled if running in parallel
+        virtual bool coupled() const { return UPstream::parRun(); }
 
-            //- Return neighbour field given internal field
-            tmp<Field<Type>> patchNeighbourField() const;
+        //- Are all (receive) data available?
+        virtual bool ready() const;
 
+        //- Return neighbour field given internal field
+        tmp<Field<Type>> patchNeighbourField() const;
 
-        // Evaluation functions
 
-            //- Initialise the evaluation of the patch field
-            virtual void initEvaluate(const Pstream::commsTypes commsType);
+    // Evaluation
 
-            //- Evaluate the patch field
-            virtual void evaluate(const Pstream::commsTypes commsType);
+        //- Initialise the evaluation of the patch field
+        virtual void initEvaluate(const Pstream::commsTypes commsType);
 
-            //- Return patch-normal gradient
-            virtual tmp<Field<Type>> snGrad() const;
+        //- Evaluate the patch field
+        virtual void evaluate(const Pstream::commsTypes commsType);
 
-            //- Is all data available
-            virtual bool ready() const;
+        //- Return patch-normal gradient
+        virtual tmp<Field<Type>> snGrad() const;
 
 
         // Coupled interface functionality
@@ -245,43 +248,44 @@ public:
                 const Pstream::commsTypes commsType
             ) const;
 
-        //- Processor coupled interface functions
-
-            //- Return communicator used for comms
-            virtual label comm() const
-            {
-                return UPstream::worldComm;
-            }
-
-            //- Return processor number
-            virtual int myProcNo() const
-            {
-                return procPatch_.myProcNo();
-            }
-
-            //- Return neighbour processor number
-            virtual int neighbProcNo() const
-            {
-                return procPatch_.neighbProcNo();
-            }
-
-            //- Does the patch field perform the transformation
-            virtual bool doTransform() const
-            {
-                return (pTraits<Type>::rank && !procPatch_.parallel());
-            }
-
-            //- Return face transformation tensor
-            virtual const tensorField& forwardT() const
-            {
-                return procPatch_.forwardT();
-            }
-
-            //- Return rank of component for transform
-            virtual int rank() const
-            {
-                return pTraits<Type>::rank;
-            }
+
+    // Processor coupled interface functions
+
+        //- Return communicator used for communication
+        virtual label comm() const
+        {
+            return procPatch_.comm();
+        }
+
+        //- Return processor number
+        virtual int myProcNo() const
+        {
+            return procPatch_.myProcNo();
+        }
+
+        //- Return neighbour processor number
+        virtual int neighbProcNo() const
+        {
+            return procPatch_.neighbProcNo();
+        }
+
+        //- Does the patch field perform the transformation
+        virtual bool doTransform() const
+        {
+            return (pTraits<Type>::rank && !procPatch_.parallel());
+        }
+
+        //- Return face transformation tensor
+        virtual const tensorField& forwardT() const
+        {
+            return procPatch_.forwardT();
+        }
+
+        //- Return rank of component for transform
+        virtual int rank() const
+        {
+            return pTraits<Type>::rank;
+        }
 };
 
 
diff --git a/src/finiteVolume/fields/fvPatchFields/constraint/calculatedProcessor/calculatedProcessorFvPatchField.C b/src/finiteVolume/fields/fvPatchFields/constraint/calculatedProcessor/calculatedProcessorFvPatchField.C
index 25e6ee5a234..6b346a2f9d0 100644
--- a/src/finiteVolume/fields/fvPatchFields/constraint/calculatedProcessor/calculatedProcessorFvPatchField.C
+++ b/src/finiteVolume/fields/fvPatchFields/constraint/calculatedProcessor/calculatedProcessorFvPatchField.C
@@ -74,12 +74,25 @@ Foam::calculatedProcessorFvPatchField<Type>::calculatedProcessorFvPatchField
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
 template<class Type>
-bool Foam::calculatedProcessorFvPatchField<Type>::ready() const
+bool Foam::calculatedProcessorFvPatchField<Type>::all_ready() const
 {
     return UPstream::finishedRequestPair(recvRequest_, sendRequest_);
 }
 
 
+template<class Type>
+bool Foam::calculatedProcessorFvPatchField<Type>::ready() const
+{
+    const bool ok = UPstream::finishedRequest(recvRequest_);
+    if (ok)
+    {
+        recvRequest_ = -1;
+        if (UPstream::finishedRequest(sendRequest_)) sendRequest_ = -1;
+    }
+    return ok;
+}
+
+
 template<class Type>
 Foam::tmp<Foam::Field<Type>>
 Foam::calculatedProcessorFvPatchField<Type>::patchNeighbourField() const
@@ -87,10 +100,10 @@ Foam::calculatedProcessorFvPatchField<Type>::patchNeighbourField() const
     if (!this->ready())
     {
         FatalErrorInFunction
-            << "On patch of size " << procInterface_.faceCells().size()
+            << "Outstanding request on patch of size "
+            << procInterface_.faceCells().size()
             << " between proc " << procInterface_.myProcNo()
             << " and " << procInterface_.neighbProcNo()
-            << " outstanding request."
             << abort(FatalError);
     }
     return *this;
@@ -160,9 +173,8 @@ void Foam::calculatedProcessorFvPatchField<Type>::evaluate
 {
     if (UPstream::parRun())
     {
-        // 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;
     }
@@ -182,11 +194,11 @@ void Foam::calculatedProcessorFvPatchField<Type>::initInterfaceMatrixUpdate
     const Pstream::commsTypes commsType
 ) const
 {
-    if (!this->ready())
+    if (!this->all_ready())
     {
         FatalErrorInFunction
-            << "On patch " //<< interface_.name()
-            << " outstanding request."
+            << "Outstanding request(s) on interface "
+            //<< interface_.name()
             << abort(FatalError);
     }
 
@@ -275,9 +287,8 @@ void Foam::calculatedProcessorFvPatchField<Type>::updateInterfaceMatrix
 
     if (UPstream::parRun())
     {
-        // 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/finiteVolume/fields/fvPatchFields/constraint/calculatedProcessor/calculatedProcessorFvPatchField.H b/src/finiteVolume/fields/fvPatchFields/constraint/calculatedProcessor/calculatedProcessorFvPatchField.H
index 7367148a71e..ef6807119ec 100644
--- a/src/finiteVolume/fields/fvPatchFields/constraint/calculatedProcessor/calculatedProcessorFvPatchField.H
+++ b/src/finiteVolume/fields/fvPatchFields/constraint/calculatedProcessor/calculatedProcessorFvPatchField.H
@@ -68,7 +68,7 @@ class calculatedProcessorFvPatchField
 {
 protected:
 
-    // Protected data
+    // Protected Data
 
          //- Local reference cast into the interface
          const lduPrimitiveProcessorInterface& procInterface_;
@@ -106,6 +106,10 @@ protected:
         ) const;
 
 
+        //- Receive and send requests have both completed
+        virtual bool all_ready() const;
+
+
 public:
 
     //- Runtime type information
@@ -161,73 +165,30 @@ public:
     virtual ~calculatedProcessorFvPatchField() = default;
 
 
-    // Member functions
-
-        // processorLduInterfaceField implementation
-
-            //- Return communicator used for comms
-            virtual label comm() const
-            {
-                return procInterface_.comm();
-            }
+    // Member Functions
 
-            //- Return processor number
-            virtual int myProcNo() const
-            {
-                return procInterface_.myProcNo();
-            }
-
-
-            //- Return neighbour processor number
-            virtual int neighbProcNo() const
-            {
-                return procInterface_.myProcNo();
-            }
-
-            //- Is the transform required
-            virtual bool doTransform() const
-            {
-                return false;
-            }
-
-            //- Return face transformation tensor
-            virtual const tensorField& forwardT() const
-            {
-                return procInterface_.forwardT();
-            }
-
-            //- Return rank of component for transform
-            virtual int rank() const
-            {
-                return pTraits<Type>::rank;
-            }
+    // Coupling
 
+        //- The patch field is coupled if running in parallel
+        virtual bool coupled() const { return UPstream::parRun(); }
 
-        // Access
+        //- Are all (receive) data available?
+        virtual bool ready() const;
 
-            //- Return true if this patch field is coupled.
-            //  Our field supplies coefficients to the fvMatrix so
-            //  should behave as a processorFvPatchField (in
-            //  addBoundarySource it should not add to the source)
-            virtual bool coupled() const
-            {
-                return Pstream::parRun();
-            }
+        //- Return neighbour field of internal field
+        virtual tmp<Field<Type>> patchNeighbourField() const;
 
-            //- Return neighbour field of internal field
-            virtual tmp<Field<Type>> patchNeighbourField() const;
 
+    // Evaluation
 
-        // Evaluation functions
+        //- Initialise the evaluation of the patch field
+        virtual void initEvaluate(const Pstream::commsTypes commsType);
 
-            //- Is all data available
-            virtual bool ready() const;
+        //- Evaluate the patch field
+        virtual void evaluate(const Pstream::commsTypes commsType);
 
-            //- Initialise the evaluation of the patch field
-            virtual void initEvaluate(const Pstream::commsTypes commsType);
 
-            //- Evaluate the patch field
-            virtual void evaluate(const Pstream::commsTypes commsType);
+        // Coupled interface functionality
 
             //- Initialise neighbour matrix update
             virtual void initInterfaceMatrixUpdate
@@ -285,8 +246,44 @@ public:
                 NotImplemented;
             }
 
-        //- Write
-        // virtual void write(Ostream& os) const;
+
+    // Processor coupled interface functions
+
+        //- Return communicator used for communication
+        virtual label comm() const
+        {
+            return procInterface_.comm();
+        }
+
+        //- Return processor number
+        virtual int myProcNo() const
+        {
+            return procInterface_.myProcNo();
+        }
+
+        //- Return neighbour processor number
+        virtual int neighbProcNo() const
+        {
+            return procInterface_.myProcNo();
+        }
+
+        //- Is the transform required
+        virtual bool doTransform() const
+        {
+            return false;
+        }
+
+        //- Return face transformation tensor
+        virtual const tensorField& forwardT() const
+        {
+            return procInterface_.forwardT();
+        }
+
+        //- Return rank of component for transform
+        virtual int rank() const
+        {
+            return pTraits<Type>::rank;
+        }
 };
 
 
diff --git a/src/finiteVolume/fields/fvPatchFields/constraint/processor/processorFvPatchField.C b/src/finiteVolume/fields/fvPatchFields/constraint/processor/processorFvPatchField.C
index 3fdec71d964..19da597026a 100644
--- a/src/finiteVolume/fields/fvPatchFields/constraint/processor/processorFvPatchField.C
+++ b/src/finiteVolume/fields/fvPatchFields/constraint/processor/processorFvPatchField.C
@@ -118,10 +118,10 @@ Foam::processorFvPatchField<Type>::processorFvPatchField
             << " in file " << this->internalField().objectPath()
             << exit(FatalError);
     }
-    if (debug && !ptf.ready())
+    if (debug && !ptf.all_ready())
     {
         FatalErrorInFunction
-            << "On patch " << procPatch_.name() << " outstanding request."
+            << "Outstanding request(s) on patch " << procPatch_.name()
             << abort(FatalError);
     }
 }
@@ -143,10 +143,10 @@ Foam::processorFvPatchField<Type>::processorFvPatchField
     scalarSendBuf_(std::move(ptf.scalarSendBuf_)),
     scalarRecvBuf_(std::move(ptf.scalarRecvBuf_))
 {
-    if (debug && !ptf.ready())
+    if (debug && !ptf.all_ready())
     {
         FatalErrorInFunction
-            << "On patch " << procPatch_.name() << " outstanding request."
+            << "Outstanding request(s) on patch " << procPatch_.name()
             << abort(FatalError);
     }
 }
@@ -164,10 +164,10 @@ Foam::processorFvPatchField<Type>::processorFvPatchField
     sendRequest_(-1),
     recvRequest_(-1)
 {
-    if (debug && !ptf.ready())
+    if (debug && !ptf.all_ready())
     {
         FatalErrorInFunction
-            << "On patch " << procPatch_.name() << " outstanding request."
+            << "Outstanding request(s) on patch " << procPatch_.name()
             << abort(FatalError);
     }
 }
@@ -176,12 +176,25 @@ Foam::processorFvPatchField<Type>::processorFvPatchField
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
 template<class Type>
-bool Foam::processorFvPatchField<Type>::ready() const
+bool Foam::processorFvPatchField<Type>::all_ready() const
 {
     return UPstream::finishedRequestPair(recvRequest_, sendRequest_);
 }
 
 
+template<class Type>
+bool Foam::processorFvPatchField<Type>::ready() const
+{
+    const bool ok = UPstream::finishedRequest(recvRequest_);
+    if (ok)
+    {
+        recvRequest_ = -1;
+        if (UPstream::finishedRequest(sendRequest_)) sendRequest_ = -1;
+    }
+    return ok;
+}
+
+
 template<class Type>
 Foam::tmp<Foam::Field<Type>>
 Foam::processorFvPatchField<Type>::patchNeighbourField() const
@@ -189,8 +202,7 @@ Foam::processorFvPatchField<Type>::patchNeighbourField() const
     if (debug && !this->ready())
     {
         FatalErrorInFunction
-            << "On patch " << procPatch_.name()
-            << " outstanding request."
+            << "Outstanding request on patch " << procPatch_.name()
             << abort(FatalError);
     }
     return *this;
@@ -209,7 +221,7 @@ void Foam::processorFvPatchField<Type>::initEvaluate
 
         if
         (
-            commsType == Pstream::commsTypes::nonBlocking
+            commsType == UPstream::commsTypes::nonBlocking
          && (std::is_integral<Type>::value || !UPstream::floatTransfer)
         )
         {
@@ -263,15 +275,14 @@ void Foam::processorFvPatchField<Type>::evaluate
     {
         if
         (
-            commsType == Pstream::commsTypes::nonBlocking
+            commsType == UPstream::commsTypes::nonBlocking
          && (std::is_integral<Type>::value || !UPstream::floatTransfer)
         )
         {
             // Fast path: received into *this
 
-            // 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;
         }
@@ -324,16 +335,15 @@ void Foam::processorFvPatchField<Type>::initInterfaceMatrixUpdate
 
     if
     (
-        commsType == Pstream::commsTypes::nonBlocking
+        commsType == UPstream::commsTypes::nonBlocking
      && !UPstream::floatTransfer
     )
     {
         // Fast path.
-        if (debug && !this->ready())
+        if (debug && !this->all_ready())
         {
             FatalErrorInFunction
-                << "On patch " << procPatch_.name()
-                << " outstanding request."
+                << "Outstanding request(s) on patch " << procPatch_.name()
                 << abort(FatalError);
         }
 
@@ -392,15 +402,14 @@ void Foam::processorFvPatchField<Type>::updateInterfaceMatrix
 
     if
     (
-        commsType == Pstream::commsTypes::nonBlocking
+        commsType == UPstream::commsTypes::nonBlocking
      && !UPstream::floatTransfer
     )
     {
         // 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;
     }
@@ -447,16 +456,15 @@ void Foam::processorFvPatchField<Type>::initInterfaceMatrixUpdate
 
     if
     (
-        commsType == Pstream::commsTypes::nonBlocking
+        commsType == UPstream::commsTypes::nonBlocking
      && (std::is_integral<Type>::value || !UPstream::floatTransfer)
     )
     {
         // Fast path.
-        if (debug && !this->ready())
+        if (debug && !this->all_ready())
         {
             FatalErrorInFunction
-                << "On patch " << procPatch_.name()
-                << " outstanding request."
+                << "Outstanding request(s) on patch " << procPatch_.name()
                 << abort(FatalError);
         }
 
@@ -514,15 +522,14 @@ void Foam::processorFvPatchField<Type>::updateInterfaceMatrix
 
     if
     (
-        commsType == Pstream::commsTypes::nonBlocking
+        commsType == UPstream::commsTypes::nonBlocking
      && (std::is_integral<Type>::value || !UPstream::floatTransfer)
     )
     {
         // 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/finiteVolume/fields/fvPatchFields/constraint/processor/processorFvPatchField.H b/src/finiteVolume/fields/fvPatchFields/constraint/processor/processorFvPatchField.H
index 48e2f092ba5..7c83568c3d0 100644
--- a/src/finiteVolume/fields/fvPatchFields/constraint/processor/processorFvPatchField.H
+++ b/src/finiteVolume/fields/fvPatchFields/constraint/processor/processorFvPatchField.H
@@ -96,6 +96,12 @@ class processorFvPatchField
             mutable solveScalarField scalarRecvBuf_;
 
 
+    // Private Member Functions
+
+        //- Receive and send requests have both completed
+        virtual bool all_ready() const;
+
+
 public:
 
     //- Runtime type information
@@ -174,34 +180,34 @@ public:
 
     // Member Functions
 
-        // Access
+    // Coupling
 
-            //- Return true if running parallel
-            virtual bool coupled() const
-            {
-                return Pstream::parRun();
-            }
+        //- The patch field is coupled if running in parallel
+        virtual bool coupled() const { return UPstream::parRun(); }
 
-            //- Return neighbour field given internal field
-            virtual tmp<Field<Type>> patchNeighbourField() const;
+        //- Are all (receive) data available?
+        virtual bool ready() const;
 
+        //- Return neighbour field given internal field
+        virtual tmp<Field<Type>> patchNeighbourField() const;
 
-        // Evaluation functions
 
-            //- Initialise the evaluation of the patch field
-            virtual void initEvaluate(const Pstream::commsTypes commsType);
+    // Evaluation
 
-            //- Evaluate the patch field
-            virtual void evaluate(const Pstream::commsTypes commsType);
+        //- Initialise the evaluation of the patch field
+        virtual void initEvaluate(const Pstream::commsTypes commsType);
 
-            //- Return patch-normal gradient
-            virtual tmp<Field<Type>> snGrad
-            (
-                const scalarField& deltaCoeffs
-            ) const;
+        //- Evaluate the patch field
+        virtual void evaluate(const Pstream::commsTypes commsType);
+
+        //- Return patch-normal gradient
+        virtual tmp<Field<Type>> snGrad
+        (
+            const scalarField& deltaCoeffs
+        ) const;
 
-            //- Is all data available
-            virtual bool ready() const;
+
+        // Coupled interface functionality
 
             //- Initialise neighbour matrix update
             virtual void initInterfaceMatrixUpdate
@@ -254,43 +260,43 @@ public:
             ) const;
 
 
-        //- Processor coupled interface functions
-
-            //- Return communicator used for comms
-            virtual label comm() const
-            {
-                return procPatch_.comm();
-            }
-
-            //- Return processor number
-            virtual int myProcNo() const
-            {
-                return procPatch_.myProcNo();
-            }
-
-            //- Return neighbour processor number
-            virtual int neighbProcNo() const
-            {
-                return procPatch_.neighbProcNo();
-            }
-
-            //- Does the patch field perform the transformation
-            virtual bool doTransform() const
-            {
-                return (pTraits<Type>::rank && !procPatch_.parallel());
-            }
-
-            //- Return face transformation tensor
-            virtual const tensorField& forwardT() const
-            {
-                return procPatch_.forwardT();
-            }
-
-            //- Return rank of component for transform
-            virtual int rank() const
-            {
-                return pTraits<Type>::rank;
-            }
+    // Processor coupled interface functions
+
+        //- Return communicator used for communication
+        virtual label comm() const
+        {
+            return procPatch_.comm();
+        }
+
+        //- Return processor number
+        virtual int myProcNo() const
+        {
+            return procPatch_.myProcNo();
+        }
+
+        //- Return neighbour processor number
+        virtual int neighbProcNo() const
+        {
+            return procPatch_.neighbProcNo();
+        }
+
+        //- Does the patch field perform the transformation
+        virtual bool doTransform() const
+        {
+            return (pTraits<Type>::rank && !procPatch_.parallel());
+        }
+
+        //- Return face transformation tensor
+        virtual const tensorField& forwardT() const
+        {
+            return procPatch_.forwardT();
+        }
+
+        //- Return rank of component for transform
+        virtual int rank() const
+        {
+            return pTraits<Type>::rank;
+        }
 };
 
 
-- 
GitLab