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 e46b8c2d1e9e88d75d43c50c12ed4913398c4269..ef92cb5ac30d4935a3578854cdfb2ede1d4fe85c 100644
--- a/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaceFields/processorGAMGInterfaceField/processorGAMGInterfaceField.C
+++ b/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaceFields/processorGAMGInterfaceField/processorGAMGInterfaceField.C
@@ -109,6 +109,18 @@ Foam::processorGAMGInterfaceField::processorGAMGInterfaceField
 
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
+bool Foam::processorGAMGInterfaceField::ready() const
+{
+    const bool ok = UPstream::finishedRequest(recvRequest_);
+    if (ok)
+    {
+        recvRequest_ = -1;
+        if (UPstream::finishedRequest(sendRequest_)) sendRequest_ = -1;
+    }
+    return ok;
+}
+
+
 void Foam::processorGAMGInterfaceField::initInterfaceMatrixUpdate
 (
     solveScalarField&,
diff --git a/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaceFields/processorGAMGInterfaceField/processorGAMGInterfaceField.H b/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaceFields/processorGAMGInterfaceField/processorGAMGInterfaceField.H
index c6ae154aef32dc745ef9e152ba70bc50978c0d42..39a52d0e57e9f6123dc4b8c488522594468248f5 100644
--- a/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaceFields/processorGAMGInterfaceField/processorGAMGInterfaceField.H
+++ b/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaceFields/processorGAMGInterfaceField/processorGAMGInterfaceField.H
@@ -162,6 +162,9 @@ public:
 
         // Interface matrix update
 
+            //- Are all (receive) data available?
+            virtual bool ready() const;
+
             //- Initialise neighbour matrix update
             virtual void initInterfaceMatrixUpdate
             (
diff --git a/src/meshTools/AMIInterpolation/GAMG/interfaceFields/cyclicACMIGAMGInterfaceField/cyclicACMIGAMGInterfaceField.C b/src/meshTools/AMIInterpolation/GAMG/interfaceFields/cyclicACMIGAMGInterfaceField/cyclicACMIGAMGInterfaceField.C
index d2a7f16d2576330658948e0f1a66132fa603caf2..02afdbdae6ad35d4392880f4e1741fd858e0d854 100644
--- a/src/meshTools/AMIInterpolation/GAMG/interfaceFields/cyclicACMIGAMGInterfaceField/cyclicACMIGAMGInterfaceField.C
+++ b/src/meshTools/AMIInterpolation/GAMG/interfaceFields/cyclicACMIGAMGInterfaceField/cyclicACMIGAMGInterfaceField.C
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2013 OpenFOAM Foundation
-    Copyright (C) 2019 OpenCFD Ltd.
+    Copyright (C) 2019,2023 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -67,7 +67,9 @@ Foam::cyclicACMIGAMGInterfaceField::cyclicACMIGAMGInterfaceField
     GAMGInterfaceField(GAMGCp, fineInterface),
     cyclicACMIInterface_(refCast<const cyclicACMIGAMGInterface>(GAMGCp)),
     doTransform_(false),
-    rank_(0)
+    rank_(0),
+    sendRequests_(0),
+    recvRequests_(0)
 {
     const cyclicAMILduInterfaceField& p =
         refCast<const cyclicAMILduInterfaceField>(fineInterface);
@@ -87,7 +89,9 @@ Foam::cyclicACMIGAMGInterfaceField::cyclicACMIGAMGInterfaceField
     GAMGInterfaceField(GAMGCp, doTransform, rank),
     cyclicACMIInterface_(refCast<const cyclicACMIGAMGInterface>(GAMGCp)),
     doTransform_(doTransform),
-    rank_(rank)
+    rank_(rank),
+    sendRequests_(0),
+    recvRequests_(0)
 {}
 
 
@@ -100,7 +104,9 @@ Foam::cyclicACMIGAMGInterfaceField::cyclicACMIGAMGInterfaceField
     GAMGInterfaceField(GAMGCp, is),
     cyclicACMIInterface_(refCast<const cyclicACMIGAMGInterface>(GAMGCp)),
     doTransform_(readBool(is)),
-    rank_(readLabel(is))
+    rank_(readLabel(is)),
+    sendRequests_(0),
+    recvRequests_(0)
 {}
 
 
@@ -114,7 +120,9 @@ Foam::cyclicACMIGAMGInterfaceField::cyclicACMIGAMGInterfaceField
     GAMGInterfaceField(GAMGCp, local),
     cyclicACMIInterface_(refCast<const cyclicACMIGAMGInterface>(GAMGCp)),
     doTransform_(false),
-    rank_(0)
+    rank_(0),
+    sendRequests_(0),
+    recvRequests_(0)
 {
     const auto& p = refCast<const cyclicACMILduInterfaceField>(local);
 
@@ -123,13 +131,108 @@ Foam::cyclicACMIGAMGInterfaceField::cyclicACMIGAMGInterfaceField
 }
 
 
-// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
-Foam::cyclicACMIGAMGInterfaceField::~cyclicACMIGAMGInterfaceField()
-{}
+bool Foam::cyclicACMIGAMGInterfaceField::ready() const
+{
+    if
+    (
+        UPstream::finishedRequests
+        (
+            recvRequests_.start(),
+            recvRequests_.size()
+        )
+    )
+    {
+        recvRequests_.clear();
 
+        if
+        (
+            UPstream::finishedRequests
+            (
+                sendRequests_.start(),
+                sendRequests_.size()
+            )
+        )
+        {
+            sendRequests_.clear();
+        }
+
+        return true;
+    }
+
+    return false;
+}
+
+
+void Foam::cyclicACMIGAMGInterfaceField::initInterfaceMatrixUpdate
+(
+    solveScalarField& result,
+    const bool add,
+    const lduAddressing& lduAddr,
+    const label patchId,
+    const solveScalarField& psiInternal,
+    const scalarField& coeffs,
+    const direction cmpt,
+    const Pstream::commsTypes commsType
+) const
+{
+    const auto& AMI =
+    (
+        cyclicACMIInterface_.owner()
+      ? cyclicACMIInterface_.AMI()
+      : cyclicACMIInterface_.neighbPatch().AMI()
+    );
+
+    if (AMI.distributed())
+    {
+        DebugPout<< "cyclicACMIFvPatchField::initInterfaceMatrixUpdate() :"
+            << " interface:" << cyclicACMIInterface_.index()
+            << " size:" << cyclicACMIInterface_.size()
+            << " owner:" << cyclicACMIInterface_.owner()
+            << " AMI distributed:" << AMI.distributed()
+            << endl;
+
+        // Start sending
+        if (commsType != UPstream::commsTypes::nonBlocking)
+        {
+            FatalErrorInFunction
+                << "Can only evaluate distributed AMI with nonBlocking"
+                << exit(FatalError);
+        }
+
+        // Get neighbouring field
+        const labelList& nbrFaceCells =
+            lduAddr.patchAddr(cyclicACMIInterface_.neighbPatchID());
+
+        solveScalarField pnf(psiInternal, nbrFaceCells);
+
+        // Transform according to the transformation tensors
+        transformCoupleField(pnf, cmpt);
+
+        const auto& map =
+        (
+            cyclicACMIInterface_.owner()
+          ? AMI.tgtMap()
+          : AMI.srcMap()
+        );
+
+        // Insert send/receive requests (non-blocking). See e.g.
+        // cyclicAMIPolyPatchTemplates.C
+        const label oldWarnComm = UPstream::warnComm;
+        UPstream::warnComm = AMI.comm();
+        map.send
+        (
+            pnf,
+            sendRequests_,
+            scalarSendBufs_,
+            recvRequests_,
+            scalarRecvBufs_
+        );
+        UPstream::warnComm = oldWarnComm;
+    }
+}
 
-// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
 void Foam::cyclicACMIGAMGInterfaceField::updateInterfaceMatrix
 (
@@ -143,30 +246,73 @@ void Foam::cyclicACMIGAMGInterfaceField::updateInterfaceMatrix
     const Pstream::commsTypes
 ) const
 {
-    // Get neighbouring field
-    const labelList& nbrFaceCells =
-        lduAddr.patchAddr
+    const labelUList& faceCells = lduAddr.patchAddr(patchId);
+
+    const auto& AMI =
+    (
+        cyclicACMIInterface_.owner()
+      ? cyclicACMIInterface_.AMI()
+      : cyclicACMIInterface_.neighbPatch().AMI()
+    );
+
+    DebugPout<< "cyclicACMIGAMGInterfaceField::updateInterfaceMatrix() :"
+        << " interface:" << cyclicACMIInterface_.index()
+        << " size:" << cyclicACMIInterface_.size()
+        << " owner:" << cyclicACMIInterface_.owner()
+        << " AMI distributed:" << AMI.distributed()
+        << endl;
+
+
+    if (AMI.distributed())
+    {
+        const auto& map =
         (
-            cyclicACMIInterface_.neighbPatchID()
+            cyclicACMIInterface_.owner()
+          ? AMI.tgtMap()
+          : AMI.srcMap()
         );
 
-    solveScalarField pnf(psiInternal, nbrFaceCells);
+        // Receive (= copy) data from buffers into work. TBD: receive directly
+        // into slices of work.
+        solveScalarField work;
+        map.receive(recvRequests_, scalarRecvBufs_, work);
 
-    // Transform according to the transformation tensors
-    transformCoupleField(pnf, cmpt);
+        solveScalarField pnf(faceCells.size(), Zero);
+        AMI.weightedSum
+        (
+            cyclicACMIInterface_.owner(),
+            work,
+            pnf,               // result
+            solveScalarField::null()
+        );
 
-    if (cyclicACMIInterface_.owner())
-    {
-        pnf = cyclicACMIInterface_.AMI().interpolateToSource(pnf);
+        // Add result using coefficients
+        this->addToInternalField(result, !add, faceCells, coeffs, pnf);
     }
     else
     {
-        pnf = cyclicACMIInterface_.neighbPatch().AMI().interpolateToTarget(pnf);
-    }
+        // Get neighbouring field
+        const labelList& nbrFaceCells =
+            lduAddr.patchAddr(cyclicACMIInterface_.neighbPatchID());
 
-    const labelUList& faceCells = lduAddr.patchAddr(patchId);
+        solveScalarField pnf(psiInternal, nbrFaceCells);
+
+        // Transform according to the transformation tensors
+        transformCoupleField(pnf, cmpt);
 
-    this->addToInternalField(result, !add, faceCells, coeffs, pnf);
+        if (cyclicACMIInterface_.owner())
+        {
+            pnf = AMI.interpolateToSource(pnf);
+        }
+        else
+        {
+            pnf = AMI.interpolateToTarget(pnf);
+        }
+
+        const labelUList& faceCells = lduAddr.patchAddr(patchId);
+
+        this->addToInternalField(result, !add, faceCells, coeffs, pnf);
+    }
 }
 
 
diff --git a/src/meshTools/AMIInterpolation/GAMG/interfaceFields/cyclicACMIGAMGInterfaceField/cyclicACMIGAMGInterfaceField.H b/src/meshTools/AMIInterpolation/GAMG/interfaceFields/cyclicACMIGAMGInterfaceField/cyclicACMIGAMGInterfaceField.H
index ed3f8b6be860a24c3bc17c75c03070948d80c816..e40687e593e9bcd0e2a4e33a87b6bf1251113b4b 100644
--- a/src/meshTools/AMIInterpolation/GAMG/interfaceFields/cyclicACMIGAMGInterfaceField/cyclicACMIGAMGInterfaceField.H
+++ b/src/meshTools/AMIInterpolation/GAMG/interfaceFields/cyclicACMIGAMGInterfaceField/cyclicACMIGAMGInterfaceField.H
@@ -69,6 +69,21 @@ class cyclicACMIGAMGInterfaceField
         int rank_;
 
 
+        // Sending and receiving (distributed AMI)
+
+            //- Current range of send requests (non-blocking)
+            mutable labelRange sendRequests_;
+
+            //- Current range of recv requests (non-blocking)
+            mutable labelRange recvRequests_;
+
+            //- Scalar send buffers
+            mutable PtrList<List<solveScalar>> scalarSendBufs_;
+
+            //- Scalar receive buffers
+            mutable PtrList<List<solveScalar>> scalarRecvBufs_;
+
+
     // Private Member Functions
 
         //- No copy construct
@@ -139,7 +154,7 @@ public:
 
 
     //- Destructor
-    virtual ~cyclicACMIGAMGInterfaceField();
+    virtual ~cyclicACMIGAMGInterfaceField() = default;
 
 
     // Member Functions
@@ -155,6 +170,22 @@ public:
 
         // Interface matrix update
 
+            //- Are all (receive) data available?
+            virtual bool ready() const;
+
+            //- Initialise neighbour matrix update
+            virtual void initInterfaceMatrixUpdate
+            (
+                solveScalarField& result,
+                const bool add,
+                const lduAddressing& lduAddr,
+                const label patchId,
+                const solveScalarField& psiInternal,
+                const scalarField& coeffs,
+                const direction cmpt,
+                const Pstream::commsTypes commsType
+            ) const;
+
             //- Update result field based on interface functionality
             virtual void updateInterfaceMatrix
             (
diff --git a/src/meshTools/AMIInterpolation/GAMG/interfaceFields/cyclicAMIGAMGInterfaceField/cyclicAMIGAMGInterfaceField.C b/src/meshTools/AMIInterpolation/GAMG/interfaceFields/cyclicAMIGAMGInterfaceField/cyclicAMIGAMGInterfaceField.C
index 2255bbdac89dd69605f3e300b88a8ad45d778c53..21a7a0ce655190585bd7511f51c6d41bc944d339 100644
--- a/src/meshTools/AMIInterpolation/GAMG/interfaceFields/cyclicAMIGAMGInterfaceField/cyclicAMIGAMGInterfaceField.C
+++ b/src/meshTools/AMIInterpolation/GAMG/interfaceFields/cyclicAMIGAMGInterfaceField/cyclicAMIGAMGInterfaceField.C
@@ -67,7 +67,9 @@ Foam::cyclicAMIGAMGInterfaceField::cyclicAMIGAMGInterfaceField
     GAMGInterfaceField(GAMGCp, fineInterface),
     cyclicAMIInterface_(refCast<const cyclicAMIGAMGInterface>(GAMGCp)),
     doTransform_(false),
-    rank_(0)
+    rank_(0),
+    sendRequests_(0),
+    recvRequests_(0)
 {
     const cyclicAMILduInterfaceField& p =
         refCast<const cyclicAMILduInterfaceField>(fineInterface);
@@ -87,7 +89,9 @@ Foam::cyclicAMIGAMGInterfaceField::cyclicAMIGAMGInterfaceField
     GAMGInterfaceField(GAMGCp, doTransform, rank),
     cyclicAMIInterface_(refCast<const cyclicAMIGAMGInterface>(GAMGCp)),
     doTransform_(doTransform),
-    rank_(rank)
+    rank_(rank),
+    sendRequests_(0),
+    recvRequests_(0)
 {}
 
 
@@ -100,7 +104,9 @@ Foam::cyclicAMIGAMGInterfaceField::cyclicAMIGAMGInterfaceField
     GAMGInterfaceField(GAMGCp, is),
     cyclicAMIInterface_(refCast<const cyclicAMIGAMGInterface>(GAMGCp)),
     doTransform_(readBool(is)),
-    rank_(readLabel(is))
+    rank_(readLabel(is)),
+    sendRequests_(0),
+    recvRequests_(0)
 {}
 
 
@@ -114,7 +120,9 @@ Foam::cyclicAMIGAMGInterfaceField::cyclicAMIGAMGInterfaceField
     GAMGInterfaceField(GAMGCp, local),
     cyclicAMIInterface_(refCast<const cyclicAMIGAMGInterface>(GAMGCp)),
     doTransform_(false),
-    rank_(0)
+    rank_(0),
+    sendRequests_(0),   // assume no requests in flight for input field
+    recvRequests_(0)
 {
     const auto& p = refCast<const cyclicAMILduInterfaceField>(local);
 
@@ -123,15 +131,41 @@ Foam::cyclicAMIGAMGInterfaceField::cyclicAMIGAMGInterfaceField
 }
 
 
-// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
-Foam::cyclicAMIGAMGInterfaceField::~cyclicAMIGAMGInterfaceField()
-{}
+bool Foam::cyclicAMIGAMGInterfaceField::ready() const
+{
+    if
+    (
+        UPstream::finishedRequests
+        (
+            recvRequests_.start(),
+            recvRequests_.size()
+        )
+    )
+    {
+        recvRequests_.clear();
+
+        if
+        (
+            UPstream::finishedRequests
+            (
+                sendRequests_.start(),
+                sendRequests_.size()
+            )
+        )
+        {
+            sendRequests_.clear();
+        }
+
+        return true;
+    }
 
+    return false;
+}
 
-// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
-void Foam::cyclicAMIGAMGInterfaceField::updateInterfaceMatrix
+void Foam::cyclicAMIGAMGInterfaceField::initInterfaceMatrixUpdate
 (
     solveScalarField& result,
     const bool add,
@@ -140,50 +174,162 @@ void Foam::cyclicAMIGAMGInterfaceField::updateInterfaceMatrix
     const solveScalarField& psiInternal,
     const scalarField& coeffs,
     const direction cmpt,
-    const Pstream::commsTypes
+    const Pstream::commsTypes commsType
 ) const
 {
-    // Get neighbouring field
+    const auto& AMI =
+    (
+        cyclicAMIInterface_.owner()
+      ? cyclicAMIInterface_.AMI()
+      : cyclicAMIInterface_.neighbPatch().AMI()
+    );
 
-    const label oldWarnComm = UPstream::warnComm;
+    if (AMI.distributed())
+    {
+        //DebugPout<< "cyclicAMIFvPatchField::initInterfaceMatrixUpdate() :"
+        //    << " interface:" << cyclicAMIInterface_.index()
+        //    << " size:" << cyclicAMIInterface_.size()
+        //    << " owner:" << cyclicAMIInterface_.owner()
+        //    << " AMI distributed:" << AMI.distributed()
+        //    << " AMI low-weight:" << AMI.applyLowWeightCorrection()
+        //    << endl;
+
+        // Start sending
+        if (commsType != UPstream::commsTypes::nonBlocking)
+        {
+            FatalErrorInFunction
+                << "Can only evaluate distributed AMI with nonBlocking"
+                << exit(FatalError);
+        }
+
+        // Get neighbouring field
+        const labelList& nbrFaceCells =
+            lduAddr.patchAddr(cyclicAMIInterface_.neighbPatchID());
+
+        solveScalarField pnf(psiInternal, nbrFaceCells);
+
+        // Transform according to the transformation tensors
+        transformCoupleField(pnf, cmpt);
+
+        const auto& map =
+        (
+            cyclicAMIInterface_.owner()
+          ? AMI.tgtMap()
+          : AMI.srcMap()
+        );
 
-    const labelList& nbrFaceCells =
-        lduAddr.patchAddr
+        // Insert send/receive requests (non-blocking). See e.g.
+        // cyclicAMIPolyPatchTemplates.C
+        const label oldWarnComm = UPstream::warnComm;
+        UPstream::warnComm = AMI.comm();
+        map.send
         (
-            cyclicAMIInterface_.neighbPatchID()
+            pnf,
+            sendRequests_,
+            scalarSendBufs_,
+            recvRequests_,
+            scalarRecvBufs_
         );
+        UPstream::warnComm = oldWarnComm;
+    }
+}
+
+
+void Foam::cyclicAMIGAMGInterfaceField::updateInterfaceMatrix
+(
+    solveScalarField& result,
+    const bool add,
+    const lduAddressing& lduAddr,
+    const label patchId,
+    const solveScalarField& psiInternal,
+    const scalarField& coeffs,
+    const direction cmpt,
+    const Pstream::commsTypes commsType
+) const
+{
+    const labelUList& faceCells = lduAddr.patchAddr(patchId);
+
+    const auto& AMI =
+    (
+        cyclicAMIInterface_.owner()
+      ? cyclicAMIInterface_.AMI()
+      : cyclicAMIInterface_.neighbPatch().AMI()
+    );
 
-    solveScalarField pnf(psiInternal, nbrFaceCells);
+    solveScalarField defaultValues;
+    if (AMI.applyLowWeightCorrection())
+    {
+        defaultValues = solveScalarField(psiInternal, faceCells);
+    }
 
-    // Transform according to the transformation tensors
-    transformCoupleField(pnf, cmpt);
+    //DebugPout<< "cyclicAMIFvPatchField::updateInterfaceMatrix() :"
+    //    << " interface:" << cyclicAMIInterface_.index()
+    //    << " size:" << cyclicAMIInterface_.size()
+    //    << " owner:" << cyclicAMIInterface_.owner()
+    //    << " AMI distributed:" << AMI.distributed()
+    //    << " AMI low-weight:" << AMI.applyLowWeightCorrection()
+    //    << endl;
 
-    if (cyclicAMIInterface_.owner())
+    if (AMI.distributed())
     {
-        const auto& AMI = cyclicAMIInterface_.AMI();
+        if (commsType != UPstream::commsTypes::nonBlocking)
+        {
+            FatalErrorInFunction
+                << "Can only evaluate distributed AMI with nonBlocking"
+                << exit(FatalError);
+        }
+
+        const auto& map =
+        (
+            cyclicAMIInterface_.owner()
+          ? AMI.tgtMap()
+          : AMI.srcMap()
+        );
 
-        // Switch on warning if using wrong communicator. Can be removed if
-        // sure all is correct
-        UPstream::warnComm = AMI.comm();
+        // Receive (= copy) data from buffers into work. TBD: receive directly
+        // into slices of work.
+        solveScalarField work;
+        map.receive(recvRequests_, scalarRecvBufs_, work);
 
-        pnf = AMI.interpolateToSource(pnf);
+        solveScalarField pnf(faceCells.size(), Zero);
+        AMI.weightedSum
+        (
+            cyclicAMIInterface_.owner(),
+            work,
+            pnf,                // result
+            defaultValues
+        );
+
+        // Add result using coefficients
+        this->addToInternalField(result, !add, faceCells, coeffs, pnf);
     }
     else
     {
-        const auto& AMI = cyclicAMIInterface_.neighbPatch().AMI();
+        // Get neighbouring field
+        const labelList& nbrFaceCells =
+            lduAddr.patchAddr(cyclicAMIInterface_.neighbPatchID());
+
+        solveScalarField work(psiInternal, nbrFaceCells);
+
+        // Transform according to the transformation tensors
+        transformCoupleField(work, cmpt);
 
         // Switch on warning if using wrong communicator. Can be removed if
         // sure all is correct
         UPstream::warnComm = AMI.comm();
 
-        pnf = AMI.interpolateToTarget(pnf);
-    }
-
-    const labelUList& faceCells = lduAddr.patchAddr(patchId);
-
-    this->addToInternalField(result, !add, faceCells, coeffs, pnf);
+        solveScalarField pnf(faceCells.size(), Zero);
+        AMI.weightedSum
+        (
+            cyclicAMIInterface_.owner(),
+            work,
+            pnf,                // result
+            defaultValues
+        );
 
-    UPstream::warnComm = oldWarnComm;
+        // Add result using coefficients
+        this->addToInternalField(result, !add, faceCells, coeffs, pnf);
+    }
 }
 
 
diff --git a/src/meshTools/AMIInterpolation/GAMG/interfaceFields/cyclicAMIGAMGInterfaceField/cyclicAMIGAMGInterfaceField.H b/src/meshTools/AMIInterpolation/GAMG/interfaceFields/cyclicAMIGAMGInterfaceField/cyclicAMIGAMGInterfaceField.H
index 52ede77b5a3bda94c18ca0854d1180ee773341ee..5de13c74aef7039c98342eabad910820b514f262 100644
--- a/src/meshTools/AMIInterpolation/GAMG/interfaceFields/cyclicAMIGAMGInterfaceField/cyclicAMIGAMGInterfaceField.H
+++ b/src/meshTools/AMIInterpolation/GAMG/interfaceFields/cyclicAMIGAMGInterfaceField/cyclicAMIGAMGInterfaceField.H
@@ -68,6 +68,21 @@ class cyclicAMIGAMGInterfaceField
         int rank_;
 
 
+        // Sending and receiving (distributed AMI)
+
+            //- Current range of send requests (non-blocking)
+            mutable labelRange sendRequests_;
+
+            //- Current range of recv requests (non-blocking)
+            mutable labelRange recvRequests_;
+
+            //- Scalar send buffers
+            mutable PtrList<List<solveScalar>> scalarSendBufs_;
+
+            //- Scalar receive buffers
+            mutable PtrList<List<solveScalar>> scalarRecvBufs_;
+
+
     // Private Member Functions
 
         //- No copy construct
@@ -138,7 +153,7 @@ public:
 
 
     //- Destructor
-    virtual ~cyclicAMIGAMGInterfaceField();
+    virtual ~cyclicAMIGAMGInterfaceField() = default;
 
 
     // Member Functions
@@ -154,6 +169,22 @@ public:
 
         // Interface matrix update
 
+            //- Are all (receive) data available?
+            virtual bool ready() const;
+
+            //- Initialise neighbour matrix update
+            virtual void initInterfaceMatrixUpdate
+            (
+                solveScalarField& result,
+                const bool add,
+                const lduAddressing& lduAddr,
+                const label patchId,
+                const solveScalarField& psiInternal,
+                const scalarField& coeffs,
+                const direction cmpt,
+                const Pstream::commsTypes commsType
+            ) const;
+
             //- Update result field based on interface functionality
             virtual void updateInterfaceMatrix
             (
diff --git a/tutorials/basic/laplacianFoam/implicitAMI-nonblocking/README.txt b/tutorials/basic/laplacianFoam/twoBlocks-processorAgglom/README.txt
similarity index 100%
rename from tutorials/basic/laplacianFoam/implicitAMI-nonblocking/README.txt
rename to tutorials/basic/laplacianFoam/twoBlocks-processorAgglom/README.txt