diff --git a/applications/solvers/heatTransfer/chtMultiRegionFoam/Make/options b/applications/solvers/heatTransfer/chtMultiRegionFoam/Make/options
index 0a16d78b2f065e3fdea0435bf11252630aee4190..941407a03c38f42f22dbb36d624c347894f1bb61 100644
--- a/applications/solvers/heatTransfer/chtMultiRegionFoam/Make/options
+++ b/applications/solvers/heatTransfer/chtMultiRegionFoam/Make/options
@@ -21,6 +21,7 @@ EXE_INC = \
     -I$(LIB_SRC)/regionModels/regionModel/lnInclude \
     -I$(LIB_SRC)/regionFaModels\lnInclude
 
+
 EXE_LIBS = \
     -lfiniteVolume \
     -lfvOptions \
diff --git a/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionFoam.C b/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionFoam.C
index 299653602d2a556f39b5e70cd7f3a55fba02e518..d2293d3624ceb4560243b5ad7bab9ece9ed251c2 100644
--- a/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionFoam.C
+++ b/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionFoam.C
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2016 OpenFOAM Foundation
-    Copyright (C) 2017 OpenCFD Ltd.
+    Copyright (C) 2017-2019 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -54,6 +54,7 @@ Description
 #include "loopControl.H"
 #include "pressureControl.H"
 
+
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
 int main(int argc, char *argv[])
@@ -80,6 +81,8 @@ int main(int argc, char *argv[])
     #include "solidRegionDiffusionNo.H"
     #include "setInitialMultiRegionDeltaT.H"
 
+    #include "createCoupledRegions.H"
+
     while (runTime.run())
     {
         #include "readTimeControls.H"
@@ -109,8 +112,6 @@ int main(int argc, char *argv[])
 
             forAll(fluidRegions, i)
             {
-                Info<< "\nSolving for fluid region "
-                    << fluidRegions[i].name() << endl;
                 #include "setRegionFluidFields.H"
                 #include "readFluidMultiRegionPIMPLEControls.H"
                 #include "solveFluid.H"
@@ -118,13 +119,35 @@ int main(int argc, char *argv[])
 
             forAll(solidRegions, i)
             {
-                Info<< "\nSolving for solid region "
-                    << solidRegions[i].name() << endl;
                 #include "setRegionSolidFields.H"
                 #include "readSolidMultiRegionPIMPLEControls.H"
                 #include "solveSolid.H"
             }
 
+            if (coupled)
+            {
+                Info<< "\nSolving energy coupled regions " << endl;
+                fvMatrixAssemblyPtr->solve();
+                #include "correctThermos.H"
+
+                forAll(fluidRegions, i)
+                {
+                    #include "setRegionFluidFields.H"
+                    #include "readFluidMultiRegionPIMPLEControls.H"
+                    Info<< "\nSolving for fluid region "
+                        << fluidRegions[i].name() << endl;
+                    // --- PISO loop
+                    for (int corr=0; corr<nCorr; corr++)
+                    {
+                        #include "pEqn.H"
+                    }
+                    turbulence.correct();
+                    rho = thermo.rho();
+                    Info<< "Min/max T:" << min(thermo.T()).value() << ' '
+                        << max(thermo.T()).value() << endl;
+                }
+            }
+
             // Additional loops for energy solution only
             if (!oCorr && nOuterCorr > 1)
             {
@@ -152,10 +175,28 @@ int main(int argc, char *argv[])
                         #include "readSolidMultiRegionPIMPLEControls.H"
                         #include "solveSolid.H"
                     }
+
+                    if (coupled)
+                    {
+                        Info<< "\nSolving energy coupled regions " << endl;
+                        fvMatrixAssemblyPtr->solve();
+                        #include "correctThermos.H"
+
+                        forAll(fluidRegions, i)
+                        {
+                            #include "setRegionFluidFields.H"
+                            rho = thermo.rho();
+                        }
+                    }
                 }
             }
         }
 
+        if (coupled)
+        {
+            fvMatrixAssemblyPtr->clear();
+        }
+
         runTime.write();
 
         runTime.printExecutionTime(Info);
diff --git a/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionSimpleFoam/Make/options b/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionSimpleFoam/Make/options
index 241a4ff1a640043ff0d49ee17e6327c60bc835de..02b07edfa58d17c10f871301013d8e90d3eebad4 100644
--- a/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionSimpleFoam/Make/options
+++ b/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionSimpleFoam/Make/options
@@ -3,6 +3,7 @@ EXE_INC = \
     -I./fluid \
     -I./solid \
     -I../solid \
+    -I./../include \
     -I$(LIB_SRC)/finiteVolume/cfdTools \
     -I$(LIB_SRC)/finiteVolume/lnInclude \
     -I$(LIB_SRC)/meshTools/lnInclude \
@@ -35,3 +36,4 @@ EXE_LIBS = \
     -lregionModels \
     -lsampling \
     -lregionFaModels
+
diff --git a/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionSimpleFoam/chtMultiRegionSimpleFoam.C b/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionSimpleFoam/chtMultiRegionSimpleFoam.C
index 67dcd84f95af63a513c79e1302de7098a352df72..ab8f50c0a75158d6fac216314571713f757c48fe 100644
--- a/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionSimpleFoam/chtMultiRegionSimpleFoam.C
+++ b/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionSimpleFoam/chtMultiRegionSimpleFoam.C
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2016 OpenFOAM Foundation
-    Copyright (C) 2017 OpenCFD Ltd.
+    Copyright (C) 2017-2019 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -66,6 +66,7 @@ int main(int argc, char *argv[])
     #include "createTime.H"
     #include "createMeshes.H"
     #include "createFields.H"
+    #include "createCoupledRegions.H"
     #include "initContinuityErrs.H"
 
     while (runTime.loop())
@@ -83,13 +84,27 @@ int main(int argc, char *argv[])
 
         forAll(solidRegions, i)
         {
-            Info<< "\nSolving for solid region "
-                << solidRegions[i].name() << endl;
             #include "setRegionSolidFields.H"
             #include "readSolidMultiRegionSIMPLEControls.H"
             #include "solveSolid.H"
         }
 
+
+        if (coupled)
+        {
+            Info<< "\nSolving energy coupled regions" << endl;
+            fvMatrixAssemblyPtr->solve();
+            #include "correctThermos.H"
+
+            forAll(fluidRegions, i)
+            {
+                #include "setRegionFluidFields.H"
+                #include "readSolidMultiRegionSIMPLEControls.H"
+                #include "pEqn.H"
+                turb.correct();
+            }
+        }
+
         // Additional loops for energy solution only
         {
             loopControl looping(runTime, "SIMPLE", "energyCoupling");
@@ -116,9 +131,27 @@ int main(int argc, char *argv[])
                     #include "readSolidMultiRegionSIMPLEControls.H"
                     #include "solveSolid.H"
                 }
+
+                if (coupled)
+                {
+                    Info<< "\nSolving energy coupled regions.. " << endl;
+                    fvMatrixAssemblyPtr->solve();
+                    #include "correctThermos.H"
+
+                    forAll(fluidRegions, i)
+                    {
+                        #include "setRegionFluidFields.H"
+                        turb.correct();
+                    }
+                }
             }
         }
 
+        if (coupled)
+        {
+            fvMatrixAssemblyPtr->clear();
+        }
+
         runTime.write();
 
         runTime.printExecutionTime(Info);
diff --git a/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionSimpleFoam/fluid/EEqn.H b/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionSimpleFoam/fluid/EEqn.H
index daf3af8f2db83b177bc90ae01cf9be4d8e7187ee..526e2b8757d2d5431aa21308aa7506a85c618c99 100644
--- a/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionSimpleFoam/fluid/EEqn.H
+++ b/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionSimpleFoam/fluid/EEqn.H
@@ -20,13 +20,20 @@
 
     fvOptions.constrain(EEqn);
 
-    EEqn.solve();
+    if (coupled)
+    {
+        fvMatrixAssemblyPtr->addFvMatrix(EEqn);
+    }
+    else
+    {
+        EEqn.solve();
 
-    fvOptions.correct(he);
+        fvOptions.correct(he);
 
-    thermo.correct();
-    rad.correct();
+        thermo.correct();
+        rad.correct();
 
-    Info<< "Min/max T:" << min(thermo.T()).value() << ' '
-        << max(thermo.T()).value() << endl;
+        Info<< "Min/max T:" << min(thermo.T()).value() << ' '
+            << max(thermo.T()).value() << endl;
+    }
 }
diff --git a/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionSimpleFoam/fluid/UEqn.H b/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionSimpleFoam/fluid/UEqn.H
index f9712b548ef48c36632a866f7d79a89574165717..c279edfe344979af9504ffb117f5b418deba584c 100644
--- a/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionSimpleFoam/fluid/UEqn.H
+++ b/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionSimpleFoam/fluid/UEqn.H
@@ -2,7 +2,7 @@
 
     MRF.correctBoundaryVelocity(U);
 
-    tmp<fvVectorMatrix> tUEqn
+    UEqn =
     (
         fvm::div(phi, U)
       + MRF.DDt(rho, U)
@@ -10,7 +10,6 @@
      ==
         fvOptions(rho, U)
     );
-    fvVectorMatrix& UEqn = tUEqn.ref();
 
     UEqn.relax();
 
diff --git a/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionSimpleFoam/fluid/createFluidFields.H b/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionSimpleFoam/fluid/createFluidFields.H
index f414d0eab2956e36831a74f99019462d86fc18a5..0047fb16069e8079a10992b535dbddbdfa3e6f5f 100644
--- a/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionSimpleFoam/fluid/createFluidFields.H
+++ b/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionSimpleFoam/fluid/createFluidFields.H
@@ -21,6 +21,8 @@ PtrList<dimensionedScalar> rhoMin(fluidRegions.size());
 PtrList<IOMRFZoneList> MRFfluid(fluidRegions.size());
 PtrList<fv::options> fluidFvOptions(fluidRegions.size());
 
+PtrList<fvVectorMatrix> UEqFluid(fluidRegions.size());
+
 const uniformDimensionedVectorField& g = meshObjects::gravity::New(runTime);
 
 // Populate fluid field pointer lists
@@ -222,5 +224,11 @@ forAll(fluidRegions, i)
         new fv::options(fluidRegions[i])
     );
 
+    UEqFluid.set
+    (
+        i,
+        new fvVectorMatrix(UFluid[i], dimForce)
+    );
+
     turbulence[i].validate();
 }
diff --git a/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionSimpleFoam/fluid/pEqn.H b/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionSimpleFoam/fluid/pEqn.H
index c4cc0d6c3c69f08d56f6e7f5546bd64420e06a78..fe3d7428164790fd1f20427da40daab7730920f3 100644
--- a/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionSimpleFoam/fluid/pEqn.H
+++ b/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionSimpleFoam/fluid/pEqn.H
@@ -2,7 +2,7 @@
     volScalarField rAU("rAU", 1.0/UEqn.A());
     surfaceScalarField rhorAUf("rhorAUf", fvc::interpolate(rho*rAU));
     volVectorField HbyA(constrainHbyA(rAU*UEqn.H(), U, p_rgh));
-    tUEqn.clear();
+    //tUEqn.clear();
 
     surfaceScalarField phig(-rhorAUf*ghf*fvc::snGrad(rho)*mesh.magSf());
 
diff --git a/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionSimpleFoam/fluid/setRegionFluidFields.H b/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionSimpleFoam/fluid/setRegionFluidFields.H
index 814c930275dfb7fa8d0298d6fa867b97bfe8ca77..28c4418da82aeb7aaa4185901d6fca48ae526ce2 100644
--- a/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionSimpleFoam/fluid/setRegionFluidFields.H
+++ b/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionSimpleFoam/fluid/setRegionFluidFields.H
@@ -22,6 +22,8 @@
     IOMRFZoneList& MRF = MRFfluid[i];
     fv::options& fvOptions = fluidFvOptions[i];
 
+    fvVectorMatrix& UEqn = UEqFluid[i];
+
     const dimensionedScalar initialMass
     (
         "initialMass",
diff --git a/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionSimpleFoam/fluid/solveFluid.H b/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionSimpleFoam/fluid/solveFluid.H
index b43a9490436a6a5f4b6cf5bbc08579fd70a05dad..c033bf0396c3dbc12c85c0e935e80c5631e81dd5 100644
--- a/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionSimpleFoam/fluid/solveFluid.H
+++ b/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionSimpleFoam/fluid/solveFluid.H
@@ -12,8 +12,10 @@
 
             #include "UEqn.H"
             #include "EEqn.H"
-            #include "pEqn.H"
-
-            turb.correct();
+            if (!coupled)
+            {
+                #include "pEqn.H"
+                turb.correct();
+            }
         }
     }
diff --git a/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionSimpleFoam/solid/solveSolid.H b/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionSimpleFoam/solid/solveSolid.H
index 2b6306e5c2d04894a612d591053b718bdc193665..4c545e7a2db315315146c774d653878f3eecfa41 100644
--- a/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionSimpleFoam/solid/solveSolid.H
+++ b/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionSimpleFoam/solid/solveSolid.H
@@ -16,13 +16,21 @@
 
         fvOptions.constrain(hEqn);
 
-        hEqn.solve();
+        if (coupled)
+        {
+            fvMatrixAssemblyPtr->addFvMatrix(hEqn);
+        }
+        else
+        {
+            Info<< "\nSolving for solid region "
+                << solidRegions[i].name() << endl;
 
-        fvOptions.correct(h);
-    }
-
-    thermo.correct();
+            hEqn.solve();
+            fvOptions.correct(h);
+            thermo.correct();
 
-    Info<< "Min/max T:" << min(thermo.T()).value() << ' '
-        << max(thermo.T()).value() << endl;
+            Info<< "Min/max T:" << min(thermo.T()).value() << ' '
+                << max(thermo.T()).value() << endl;
+        }
+    }
 }
diff --git a/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionTwoPhaseEulerFoam/Make/options b/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionTwoPhaseEulerFoam/Make/options
index 4662932e47a624326b6173d19bd5b6f47313f401..566ee29621e5821132f842c35fad3071f0181fb9 100644
--- a/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionTwoPhaseEulerFoam/Make/options
+++ b/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionTwoPhaseEulerFoam/Make/options
@@ -7,6 +7,7 @@ EXE_INC = \
     -I${phaseSystem}/twoPhaseCompressibleTurbulenceModels/lnInclude \
     -I${phaseSystem}/multiphaseSystem/lnInclude \
     -I./fluid \
+    -I./solid \
     -I../solid \
     -I../fluid \
     -I../include \
diff --git a/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionTwoPhaseEulerFoam/solid/solveSolid.H b/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionTwoPhaseEulerFoam/solid/solveSolid.H
new file mode 100644
index 0000000000000000000000000000000000000000..791e0d64057cf428b80b158dd4357f84a4264ffa
--- /dev/null
+++ b/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionTwoPhaseEulerFoam/solid/solveSolid.H
@@ -0,0 +1,39 @@
+if (finalIter)
+{
+    mesh.data::add("finalIteration", true);
+}
+
+{
+    for (int nonOrth=0; nonOrth<=nNonOrthCorr; ++nonOrth)
+    {
+        fvScalarMatrix hEqn
+        (
+            fvm::ddt(betav*rho, h)
+          - (
+               thermo.isotropic()
+             ? fvm::laplacian(betav*thermo.alpha(), h, "laplacian(alpha,h)")
+             : fvm::laplacian(betav*taniAlpha(), h, "laplacian(alpha,h)")
+            )
+          ==
+            fvOptions(rho, h)
+        );
+
+        hEqn.relax();
+
+        fvOptions.constrain(hEqn);
+
+        hEqn.solve(mesh.solver(h.select(finalIter)));
+
+        fvOptions.correct(h);
+    }
+
+    thermo.correct();
+
+    Info<< "Min/max T:" << min(thermo.T()).value() << ' '
+        << max(thermo.T()).value() << endl;
+}
+
+if (finalIter)
+{
+    mesh.data::remove("finalIteration");
+}
diff --git a/applications/solvers/heatTransfer/chtMultiRegionFoam/fluid/EEqn.H b/applications/solvers/heatTransfer/chtMultiRegionFoam/fluid/EEqn.H
index 8f30905c40432794f2c7df0bc758c786fdf3a1b3..39d238abcee325aefa71263f94efcf4b4d44033b 100644
--- a/applications/solvers/heatTransfer/chtMultiRegionFoam/fluid/EEqn.H
+++ b/applications/solvers/heatTransfer/chtMultiRegionFoam/fluid/EEqn.H
@@ -27,13 +27,19 @@
 
     fvOptions.constrain(EEqn);
 
-    EEqn.solve(mesh.solver(he.select(finalIter)));
+    if (coupled)
+    {
+        fvMatrixAssemblyPtr->addFvMatrix(EEqn);
+    }
+    else
+    {
+        EEqn.solve(mesh.solver(he.select(finalIter)));
+        fvOptions.correct(he);
 
-    fvOptions.correct(he);
+        thermo.correct();
+        rad.correct();
 
-    thermo.correct();
-    rad.correct();
-
-    Info<< "Min/max T:" << min(thermo.T()).value() << ' '
-        << max(thermo.T()).value() << endl;
+        Info<< "Min/max T:" << min(thermo.T()).value() << ' '
+            << max(thermo.T()).value() << endl;
+    }
 }
diff --git a/applications/solvers/heatTransfer/chtMultiRegionFoam/fluid/UEqn.H b/applications/solvers/heatTransfer/chtMultiRegionFoam/fluid/UEqn.H
index 9b5ce0e396254576fe2cf2e26c7b5de7ae111ea3..65654eeefedf427e874c9083019361757544c6c1 100644
--- a/applications/solvers/heatTransfer/chtMultiRegionFoam/fluid/UEqn.H
+++ b/applications/solvers/heatTransfer/chtMultiRegionFoam/fluid/UEqn.H
@@ -2,7 +2,7 @@
 
     MRF.correctBoundaryVelocity(U);
 
-    tmp<fvVectorMatrix> tUEqn
+    UEqn =
     (
         fvm::ddt(rho, U) + fvm::div(phi, U)
       + MRF.DDt(rho, U)
@@ -10,7 +10,6 @@
      ==
         fvOptions(rho, U)
     );
-    fvVectorMatrix& UEqn = tUEqn.ref();
 
     UEqn.relax();
 
diff --git a/applications/solvers/heatTransfer/chtMultiRegionFoam/fluid/createFluidFields.H b/applications/solvers/heatTransfer/chtMultiRegionFoam/fluid/createFluidFields.H
index 1c9db4f887b175af25f90fa1515b12abf1bd1db0..826e27720e04b35861923c0b19f12d29c959923d 100644
--- a/applications/solvers/heatTransfer/chtMultiRegionFoam/fluid/createFluidFields.H
+++ b/applications/solvers/heatTransfer/chtMultiRegionFoam/fluid/createFluidFields.H
@@ -16,6 +16,8 @@ PtrList<multivariateSurfaceInterpolationScheme<scalar>::fieldTable>
     fieldsFluid(fluidRegions.size());
 PtrList<volScalarField> QdotFluid(fluidRegions.size());
 
+PtrList<fvVectorMatrix> UEqFluid(fluidRegions.size());
+
 List<scalar> initialMassFluid(fluidRegions.size());
 List<bool> frozenFlowFluid(fluidRegions.size(), false);
 
@@ -293,6 +295,12 @@ forAll(fluidRegions, i)
         new fv::options(fluidRegions[i])
     );
 
+    UEqFluid.set
+    (
+        i,
+        new fvVectorMatrix(UFluid[i], dimForce)
+    );
+
     turbulenceFluid[i].validate();
 
     pRefCellFluid[i] = -1;
diff --git a/applications/solvers/heatTransfer/chtMultiRegionFoam/fluid/setRegionFluidFields.H b/applications/solvers/heatTransfer/chtMultiRegionFoam/fluid/setRegionFluidFields.H
index d7710d085d79fd18c79ba7cb14713894d379abb9..4b1ade67e81f723ecc8c63992a7031cb383cc784 100644
--- a/applications/solvers/heatTransfer/chtMultiRegionFoam/fluid/setRegionFluidFields.H
+++ b/applications/solvers/heatTransfer/chtMultiRegionFoam/fluid/setRegionFluidFields.H
@@ -49,6 +49,8 @@
     IOMRFZoneList& MRF = MRFfluid[i];
     fv::options& fvOptions = fluidFvOptions[i];
 
+    fvVectorMatrix& UEqn = UEqFluid[i];
+
     const dimensionedScalar initialMass
     (
         "initialMass",
diff --git a/applications/solvers/heatTransfer/chtMultiRegionFoam/fluid/solveFluid.H b/applications/solvers/heatTransfer/chtMultiRegionFoam/fluid/solveFluid.H
index d4d18e9fddb4750d97aaa1d7c7d1592ad139c3b1..d111ffd366680aa73b7d661a5e36f5493f80c6fc 100644
--- a/applications/solvers/heatTransfer/chtMultiRegionFoam/fluid/solveFluid.H
+++ b/applications/solvers/heatTransfer/chtMultiRegionFoam/fluid/solveFluid.H
@@ -18,15 +18,20 @@ else
     #include "YEqn.H"
     #include "EEqn.H"
 
-    // --- PISO loop
-    for (int corr=0; corr<nCorr; corr++)
+    if (!coupled)
     {
-        #include "pEqn.H"
-    }
+        Info<< "\nSolving for fluid region " << fluidRegions[i].name() << endl;
+
+        // --- PISO loop
+        for (int corr=0; corr<nCorr; corr++)
+        {
+            #include "pEqn.H"
+        }
 
-    turbulence.correct();
+        turbulence.correct();
 
-    rho = thermo.rho();
+        rho = thermo.rho();
+    }
 }
 
 if (finalIter)
diff --git a/applications/solvers/heatTransfer/chtMultiRegionFoam/include/correctThermos.H b/applications/solvers/heatTransfer/chtMultiRegionFoam/include/correctThermos.H
new file mode 100644
index 0000000000000000000000000000000000000000..7c8619b0ae27a43911a6e6d9af73e0d448830c75
--- /dev/null
+++ b/applications/solvers/heatTransfer/chtMultiRegionFoam/include/correctThermos.H
@@ -0,0 +1,20 @@
+forAll(fluidRegions, i)
+{
+    rhoThermo& thermo = thermoFluid[i];
+    radiation::radiationModel& rad = radiation[i];
+    fv::options& fvOptions = fluidFvOptions[i];
+    volScalarField& he = thermo.he();
+    fvOptions.correct(he);
+    thermo.correct();
+    rad.correct();
+}
+
+forAll(solidRegions, i)
+{
+    solidThermo& thermo = thermos[i];
+    fv::options& fvOptions = solidHeatSources[i];
+    volScalarField& h = thermo.he();
+    fvOptions.correct(h);
+    thermo.correct();
+}
+
diff --git a/applications/solvers/heatTransfer/chtMultiRegionFoam/include/createCoupledRegions.H b/applications/solvers/heatTransfer/chtMultiRegionFoam/include/createCoupledRegions.H
new file mode 100644
index 0000000000000000000000000000000000000000..8503be210a35519187cd9dab97f8e0d4cf2447e5
--- /dev/null
+++ b/applications/solvers/heatTransfer/chtMultiRegionFoam/include/createCoupledRegions.H
@@ -0,0 +1,51 @@
+fvSolution solutionDict(runTime);
+
+bool coupled(solutionDict.getOrDefault("coupledEnergyField", false));
+
+autoPtr<fvMatrix<scalar>> fvMatrixAssemblyPtr;
+
+forAll(fluidRegions, i)
+{
+    const rhoThermo& thermo = refCast<const rhoThermo>(thermoFluid[i]);
+    const auto& bpsi = thermo.T().boundaryField();
+
+    forAll (bpsi, patchI)
+    {
+        if (bpsi[patchI].useImplicit())
+        {
+            coupled = true;
+        }
+    }
+}
+
+forAll(solidRegions, i)
+{
+    solidThermo& thermo = thermos[i];
+    const auto& bpsi = thermo.T().boundaryField();
+
+    forAll (bpsi, patchI)
+    {
+        if (bpsi[patchI].useImplicit())
+        {
+            coupled = true;
+        }
+    }
+}
+
+forAll(fluidRegions, i)
+{
+    const rhoThermo& thermo = refCast<const rhoThermo>(thermoFluid[i]);
+    if (coupled)
+    {
+        Info << "Create fvMatrixAssembly." << endl;
+        fvMatrixAssemblyPtr.reset
+        (
+            new fvMatrix<scalar>
+            (
+                thermo.he(),
+                dimEnergy/dimTime
+            )
+        );
+        break;
+    }
+}
diff --git a/applications/solvers/heatTransfer/chtMultiRegionFoam/solid/solveSolid.H b/applications/solvers/heatTransfer/chtMultiRegionFoam/solid/solveSolid.H
index 791e0d64057cf428b80b158dd4357f84a4264ffa..913d20bce6e297b84d1ae707fa8e28d564c03f16 100644
--- a/applications/solvers/heatTransfer/chtMultiRegionFoam/solid/solveSolid.H
+++ b/applications/solvers/heatTransfer/chtMultiRegionFoam/solid/solveSolid.H
@@ -1,39 +1,45 @@
-if (finalIter)
 {
-    mesh.data::add("finalIteration", true);
-}
-
-{
-    for (int nonOrth=0; nonOrth<=nNonOrthCorr; ++nonOrth)
+    fvScalarMatrix hEqn
+    (
+        fvm::ddt(betav*rho, h)
+        - (
+            thermo.isotropic()
+            ? fvm::laplacian(betav*thermo.alpha(), h, "laplacian(alpha,h)")
+            : fvm::laplacian(betav*taniAlpha(), h, "laplacian(alpha,h)")
+        )
+        ==
+        fvOptions(rho, h)
+    );
+
+    hEqn.relax();
+
+    fvOptions.constrain(hEqn);
+
+    if (coupled)
+    {
+        fvMatrixAssemblyPtr->addFvMatrix(hEqn);
+    }
+    else
     {
-        fvScalarMatrix hEqn
-        (
-            fvm::ddt(betav*rho, h)
-          - (
-               thermo.isotropic()
-             ? fvm::laplacian(betav*thermo.alpha(), h, "laplacian(alpha,h)")
-             : fvm::laplacian(betav*taniAlpha(), h, "laplacian(alpha,h)")
-            )
-          ==
-            fvOptions(rho, h)
-        );
-
-        hEqn.relax();
-
-        fvOptions.constrain(hEqn);
+        Info<< "\nSolving for solid region "<< solidRegions[i].name() << endl;
+
+        if (finalIter)
+        {
+            mesh.data::add("finalIteration", true);
+        }
 
         hEqn.solve(mesh.solver(h.select(finalIter)));
 
         fvOptions.correct(h);
-    }
 
-    thermo.correct();
+        thermo.correct();
 
-    Info<< "Min/max T:" << min(thermo.T()).value() << ' '
-        << max(thermo.T()).value() << endl;
-}
+        Info<< "Min/max T:" << min(thermo.T()).value() << ' '
+            << max(thermo.T()).value() << endl;
 
-if (finalIter)
-{
-    mesh.data::remove("finalIteration");
+        if (finalIter)
+        {
+            mesh.data::remove("finalIteration");
+        }
+    }
 }
diff --git a/applications/solvers/incompressible/pimpleFoam/pEqn.H b/applications/solvers/incompressible/pimpleFoam/pEqn.H
index d1c090f7d1c6d241598e914eeae61a44575134ab..35182c9415b4e2a1eb5afde9f4c4a932c655fcf3 100644
--- a/applications/solvers/incompressible/pimpleFoam/pEqn.H
+++ b/applications/solvers/incompressible/pimpleFoam/pEqn.H
@@ -11,6 +11,7 @@ else
     phiHbyA += MRF.zeroFilter(fvc::interpolate(rAU));
 }
 
+
 MRF.makeRelative(phiHbyA);
 
 if (p.needReference())
diff --git a/applications/solvers/multiphase/interCondensatingEvaporatingFoam/temperaturePhaseChangeTwoPhaseMixtures/Make/options b/applications/solvers/multiphase/interCondensatingEvaporatingFoam/temperaturePhaseChangeTwoPhaseMixtures/Make/options
index 98ce2f94772fc20cbc8f241bb106cb6bfaec799d..b9fc8596f5eb8f7cab8663104ab5c8895ef30d93 100644
--- a/applications/solvers/multiphase/interCondensatingEvaporatingFoam/temperaturePhaseChangeTwoPhaseMixtures/Make/options
+++ b/applications/solvers/multiphase/interCondensatingEvaporatingFoam/temperaturePhaseChangeTwoPhaseMixtures/Make/options
@@ -1,5 +1,6 @@
 EXE_INC = \
     -I$(LIB_SRC)/finiteVolume/lnInclude \
+    -I$(LIB_SRC)/meshTools/lnInclude \
     -I$(LIB_SRC)/thermophysicalModels/basic/lnInclude \
     -I$(LIB_SRC)/transportModels \
     -I$(LIB_SRC)/transportModels/twoPhaseMixture/lnInclude \
@@ -9,6 +10,7 @@ EXE_INC = \
 
 LIB_LIBS = \
     -lfiniteVolume \
+    -lmeshTools \
     -lgeometricVoF \
     -ltwoPhaseMixture \
     -linterfaceProperties \
diff --git a/applications/solvers/multiphase/interPhaseChangeFoam/phaseChangeTwoPhaseMixtures/Make/options b/applications/solvers/multiphase/interPhaseChangeFoam/phaseChangeTwoPhaseMixtures/Make/options
index 2e61e4ba77d0be0dc1abb39def18867c4c7dba18..6f70f673dcf392b274f88f5a737f7bb0615631a3 100644
--- a/applications/solvers/multiphase/interPhaseChangeFoam/phaseChangeTwoPhaseMixtures/Make/options
+++ b/applications/solvers/multiphase/interPhaseChangeFoam/phaseChangeTwoPhaseMixtures/Make/options
@@ -1,6 +1,7 @@
 EXE_INC = \
     -I$(LIB_SRC)/transportModels/twoPhaseMixture/lnInclude \
     -I$(LIB_SRC)/transportModels \
+    -I$(LIB_SRC)/meshTools/lnInclude \
     -I$(LIB_SRC)/transportModels/incompressible/lnInclude \
     -I$(LIB_SRC)/finiteVolume/lnInclude
 
@@ -8,4 +9,5 @@ LIB_LIBS = \
     -ltwoPhaseMixture \
     -ltwoPhaseProperties \
     -lincompressibleTransportModels \
-    -lfiniteVolume
+    -lfiniteVolume \
+    -lmeshTools
diff --git a/src/OpenFOAM/Make/files b/src/OpenFOAM/Make/files
index f37def5122c111a05fb413a629ac890a1cd7a3ba..1af3509c2f7553fa31fce4514bd1cd63e83456b3 100644
--- a/src/OpenFOAM/Make/files
+++ b/src/OpenFOAM/Make/files
@@ -431,6 +431,7 @@ $(lduAddressing)/lduAddressing.C
 $(lduAddressing)/lduInterface/lduInterface.C
 $(lduAddressing)/lduInterface/processorLduInterface.C
 $(lduAddressing)/lduInterface/cyclicLduInterface.C
+$(lduAddressing)/lduInterface/lduPrimitiveProcessorInterface.C
 
 lduInterfaceFields = $(lduAddressing)/lduInterfaceFields
 $(lduInterfaceFields)/lduInterfaceField/lduInterfaceField.C
diff --git a/src/OpenFOAM/matrices/LduMatrix/LduMatrix/LduInterfaceField/LduInterfaceField.H b/src/OpenFOAM/matrices/LduMatrix/LduMatrix/LduInterfaceField/LduInterfaceField.H
index c9d138baa543ed50e0c2bd45ac49070d889ae0d8..404a5a34a5dedb7befafd6162ef148db98cb49d8 100644
--- a/src/OpenFOAM/matrices/LduMatrix/LduMatrix/LduInterfaceField/LduInterfaceField.H
+++ b/src/OpenFOAM/matrices/LduMatrix/LduMatrix/LduInterfaceField/LduInterfaceField.H
@@ -48,8 +48,7 @@ SourceFiles
 namespace Foam
 {
 
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
+// Forward declarations
 class lduMatrix;
 
 /*---------------------------------------------------------------------------*\
@@ -101,6 +100,8 @@ public:
             (
                 Field<Type>&,
                 const bool add,
+                const lduAddressing&,
+                const label interfacei,
                 const Field<Type>&,
                 const scalarField&,
                 const Pstream::commsTypes commsType
@@ -115,6 +116,8 @@ public:
             (
                 Field<Type>&,
                 const bool add,
+                const lduAddressing&,
+                const label interfacei,
                 const Field<Type>&,
                 const scalarField&,
                 const Pstream::commsTypes commsType
diff --git a/src/OpenFOAM/matrices/LduMatrix/LduMatrix/LduMatrixUpdateMatrixInterfaces.C b/src/OpenFOAM/matrices/LduMatrix/LduMatrix/LduMatrixUpdateMatrixInterfaces.C
index 3d6aed4ca5dee4f7a8bb1b658b8dae59d8403d73..d549f2e73a79aea6d60eaac1f8c1fadbad56acbc 100644
--- a/src/OpenFOAM/matrices/LduMatrix/LduMatrix/LduMatrixUpdateMatrixInterfaces.C
+++ b/src/OpenFOAM/matrices/LduMatrix/LduMatrix/LduMatrixUpdateMatrixInterfaces.C
@@ -6,6 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2017 OpenFOAM Foundation
+    Copyright (C) 2019 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -53,6 +54,8 @@ void Foam::LduMatrix<Type, DType, LUType>::initMatrixInterfaces
                 (
                     result,
                     add,
+                    lduMesh_.lduAddr(),
+                    interfacei,
                     psiif,
                     interfaceCoeffs[interfacei],
                     //Amultiplier<Type, LUType>(interfaceCoeffs[interfacei]),
@@ -80,6 +83,8 @@ void Foam::LduMatrix<Type, DType, LUType>::initMatrixInterfaces
                 (
                     result,
                     add,
+                    lduMesh_.lduAddr(),
+                    interfacei,
                     psiif,
                     interfaceCoeffs[interfacei],
                     //Amultiplier<Type, LUType>(interfaceCoeffs[interfacei]),
@@ -128,6 +133,8 @@ void Foam::LduMatrix<Type, DType, LUType>::updateMatrixInterfaces
                 (
                     result,
                     add,
+                    lduMesh_.lduAddr(),
+                    interfacei,
                     psiif,
                     interfaceCoeffs[interfacei],
                     //Amultiplier<Type, LUType>(interfaceCoeffs[interfacei]),
@@ -153,6 +160,8 @@ void Foam::LduMatrix<Type, DType, LUType>::updateMatrixInterfaces
                     (
                         result,
                         add,
+                        lduMesh_.lduAddr(),
+                        interfacei,
                         psiif,
                         interfaceCoeffs[interfacei],
                       //Amultiplier<Type, LUType>(interfaceCoeffs[interfacei]),
@@ -165,6 +174,8 @@ void Foam::LduMatrix<Type, DType, LUType>::updateMatrixInterfaces
                     (
                         result,
                         add,
+                        lduMesh_.lduAddr(),
+                        interfacei,
                         psiif,
                         interfaceCoeffs[interfacei],
                       //Amultiplier<Type, LUType>(interfaceCoeffs[interfacei]),
@@ -189,6 +200,8 @@ void Foam::LduMatrix<Type, DType, LUType>::updateMatrixInterfaces
                 (
                     result,
                     add,
+                    lduMesh_.lduAddr(),
+                    interfacei,
                     psiif,
                     interfaceCoeffs[interfacei],
                     //Amultiplier<Type, LUType>(interfaceCoeffs[interfacei]),
diff --git a/src/OpenFOAM/matrices/lduMatrix/lduAddressing/lduInterface/lduInterface.H b/src/OpenFOAM/matrices/lduMatrix/lduAddressing/lduInterface/lduInterface.H
index 430322a993961ac89edf1147cf8379ac5a8f9ebf..25ea7c1dae1b3409211654cf27c9d54f0c588a8a 100644
--- a/src/OpenFOAM/matrices/lduMatrix/lduAddressing/lduInterface/lduInterface.H
+++ b/src/OpenFOAM/matrices/lduMatrix/lduAddressing/lduInterface/lduInterface.H
@@ -72,6 +72,7 @@ public:
 
     // Member Functions
 
+
         // Access
 
             //- Return faceCell addressing
@@ -87,6 +88,14 @@ public:
                 const labelUList& internalData
             ) const = 0;
 
+            //- Return the values of the given internal data adjacent to
+            //- the interface as a field using faceCell mapping
+            virtual tmp<labelField> interfaceInternalField
+            (
+                const labelUList& internalData,
+                const labelUList& faceCells
+            ) const = 0;
+
             //- Initialise transfer of internal field adjacent to the interface
             virtual void initInternalFieldTransfer
             (
@@ -95,12 +104,23 @@ public:
             ) const
             {}
 
+            //- Initialise transfer of internal field adjacent to the interface
+            //- using faceCells mapping
+            virtual void initInternalFieldTransfer
+            (
+                const Pstream::commsTypes commsType,
+                const labelUList& iF,
+                const labelUList& faceCells
+            ) const
+            {}
+
             //- Transfer and return internal field adjacent to the interface
             virtual tmp<labelField> internalFieldTransfer
             (
                 const Pstream::commsTypes commsType,
                 const labelUList& iF
             ) const = 0;
+
 };
 
 
diff --git a/src/overset/lduPrimitiveProcessorInterface/lduPrimitiveProcessorInterface.C b/src/OpenFOAM/matrices/lduMatrix/lduAddressing/lduInterface/lduPrimitiveProcessorInterface.C
similarity index 78%
rename from src/overset/lduPrimitiveProcessorInterface/lduPrimitiveProcessorInterface.C
rename to src/OpenFOAM/matrices/lduMatrix/lduAddressing/lduInterface/lduPrimitiveProcessorInterface.C
index 13ca7bff6c29c87a82ba517df6962badcb8dd9b9..2df7eeec308264344e2f3ca114a5b496766e042a 100644
--- a/src/overset/lduPrimitiveProcessorInterface/lduPrimitiveProcessorInterface.C
+++ b/src/OpenFOAM/matrices/lduMatrix/lduAddressing/lduInterface/lduPrimitiveProcessorInterface.C
@@ -5,7 +5,7 @@
     \\  /    A nd           | www.openfoam.com
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
-    Copyright (C) 2016-2017 OpenCFD Ltd.
+    Copyright (C) 2016-2019 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -65,11 +65,23 @@ Foam::lduPrimitiveProcessorInterface::interfaceInternalField
     const labelUList& internalData
 ) const
 {
-    tmp<labelField> tfld(new labelField(faceCells_.size()));
-    labelField& fld = tfld.ref();
-    forAll(faceCells_, i)
+    return interfaceInternalField(internalData, faceCells_);
+}
+
+
+Foam::tmp<Foam::labelField>
+Foam::lduPrimitiveProcessorInterface::interfaceInternalField
+(
+    const labelUList& internalData,
+    const labelUList& faceCells
+) const
+{
+    auto tfld = tmp<labelField>::New(faceCells.size());
+    auto& fld = tfld.ref();
+
+    forAll(faceCells, i)
     {
-        fld[i] = internalData[faceCells_[i]];
+        fld[i] = internalData[faceCells[i]];
     }
     return tfld;
 }
@@ -85,6 +97,21 @@ void Foam::lduPrimitiveProcessorInterface::initInternalFieldTransfer
 }
 
 
+void Foam::lduPrimitiveProcessorInterface::initInternalFieldTransfer
+(
+    const Pstream::commsTypes commsType,
+    const labelUList& iF,
+    const labelUList& faceCells
+) const
+{
+    processorLduInterface::send
+    (
+        commsType,
+        interfaceInternalField(iF, faceCells)()
+    );
+}
+
+
 Foam::tmp<Foam::labelField>
 Foam::lduPrimitiveProcessorInterface::internalFieldTransfer
 (
@@ -95,5 +122,4 @@ Foam::lduPrimitiveProcessorInterface::internalFieldTransfer
     return processorLduInterface::receive<label>(commsType, faceCells_.size());
 }
 
-
 // ************************************************************************* //
diff --git a/src/overset/lduPrimitiveProcessorInterface/lduPrimitiveProcessorInterface.H b/src/OpenFOAM/matrices/lduMatrix/lduAddressing/lduInterface/lduPrimitiveProcessorInterface.H
similarity index 89%
rename from src/overset/lduPrimitiveProcessorInterface/lduPrimitiveProcessorInterface.H
rename to src/OpenFOAM/matrices/lduMatrix/lduAddressing/lduInterface/lduPrimitiveProcessorInterface.H
index 53c28e70c119e4be09f9d527b2a5f01d776968e9..47217dc6a2ed4ce3ba9e9be816b7fc128e4261f9 100644
--- a/src/overset/lduPrimitiveProcessorInterface/lduPrimitiveProcessorInterface.H
+++ b/src/OpenFOAM/matrices/lduMatrix/lduAddressing/lduInterface/lduPrimitiveProcessorInterface.H
@@ -56,7 +56,7 @@ class lduPrimitiveProcessorInterface
     public lduInterface,
     public processorLduInterface
 {
-    // Private data
+    // Private Data
 
         const labelList faceCells_;
 
@@ -126,12 +126,20 @@ public:
         // Interface transfer functions
 
             //- Return the values of the given internal data adjacent to
-            //  the interface as a field
+            //- the interface as a field
             virtual tmp<labelField> interfaceInternalField
             (
                 const labelUList& internalData
             ) const;
 
+            //- Return the values of the given internal data adjacent to
+            //- the interface as a field using faceCells mapping
+            virtual tmp<labelField> interfaceInternalField
+            (
+                const labelUList& internalData,
+                const labelUList& faceCells
+            ) const;
+
             //- Initialise neighbour field transfer
             virtual void initInternalFieldTransfer
             (
@@ -139,6 +147,14 @@ public:
                 const labelUList& iF
             ) const;
 
+            //- Initialise neighbour field transfer using faceCells
+            virtual void initInternalFieldTransfer
+            (
+                const Pstream::commsTypes commsType,
+                const labelUList& iF,
+                const labelUList& faceCells
+            ) const;
+
             //- Transfer and return internal field adjacent to the interface
             virtual tmp<labelField> internalFieldTransfer
             (
diff --git a/src/OpenFOAM/matrices/lduMatrix/lduAddressing/lduInterfaceFields/lduInterfaceField/lduInterfaceField.H b/src/OpenFOAM/matrices/lduMatrix/lduAddressing/lduInterfaceFields/lduInterfaceField/lduInterfaceField.H
index 977a2f0750ad4844cf7879182fba601e6a7154fa..cb3e9da1fdbb8c47fae44b00e311d167f55696e9 100644
--- a/src/OpenFOAM/matrices/lduMatrix/lduAddressing/lduInterfaceFields/lduInterfaceField/lduInterfaceField.H
+++ b/src/OpenFOAM/matrices/lduMatrix/lduAddressing/lduInterfaceFields/lduInterfaceField/lduInterfaceField.H
@@ -42,14 +42,14 @@ SourceFiles
 #include "lduInterface.H"
 #include "primitiveFieldsFwd.H"
 #include "Pstream.H"
+#include "lduAddressing.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
 namespace Foam
 {
 
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
+// Forward declarations
 class lduMatrix;
 
 /*---------------------------------------------------------------------------*\
@@ -58,7 +58,7 @@ class lduMatrix;
 
 class lduInterfaceField
 {
-    // Private data
+    // Private Data
 
         //- Reference to the coupled patch this field is defined for
         const lduInterface& interface_;
@@ -140,6 +140,8 @@ public:
             (
                 solveScalarField& result,
                 const bool add,
+                const lduAddressing&,
+                const label interfacei,
                 const solveScalarField& psiInternal,
                 const scalarField& coeffs,
                 const direction cmpt,
@@ -153,6 +155,8 @@ public:
             (
                 solveScalarField& result,
                 const bool add,
+                const lduAddressing&,
+                const label interfacei,
                 const solveScalarField& psiInternal,
                 const scalarField& coeffs,
                 const direction cmpt,
@@ -165,6 +169,7 @@ public:
             (
                 Field<Type>& result,
                 const bool add,
+                const labelUList& faceCells,
                 const scalarField& coeffs,
                 const Field<Type>& vals
             ) const;
diff --git a/src/OpenFOAM/matrices/lduMatrix/lduAddressing/lduInterfaceFields/lduInterfaceField/lduInterfaceFieldTemplates.C b/src/OpenFOAM/matrices/lduMatrix/lduAddressing/lduInterfaceFields/lduInterfaceField/lduInterfaceFieldTemplates.C
index 3746e3f6fdead9b21b9cebca45bba3b0b0e09ce0..9190412c22031ce61f2c185665ed1a60fea7e92c 100644
--- a/src/OpenFOAM/matrices/lduMatrix/lduAddressing/lduInterfaceFields/lduInterfaceField/lduInterfaceFieldTemplates.C
+++ b/src/OpenFOAM/matrices/lduMatrix/lduAddressing/lduInterfaceFields/lduInterfaceField/lduInterfaceFieldTemplates.C
@@ -5,7 +5,7 @@
     \\  /    A nd           | www.openfoam.com
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
-    Copyright (C) 2017 OpenCFD Ltd.
+    Copyright (C) 2017-2019 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -32,24 +32,23 @@ void Foam::lduInterfaceField::addToInternalField
 (
     Field<Type>& result,
     const bool add,
+    const labelUList& faceCells,
     const scalarField& coeffs,
     const Field<Type>& vals
 ) const
 {
-    const labelUList& faceCells = this->interface().faceCells();
-
     if (add)
     {
-        forAll(faceCells, elemI)
+        forAll(faceCells, elemi)
         {
-            result[faceCells[elemI]] += coeffs[elemI]*vals[elemI];
+            result[faceCells[elemi]] += coeffs[elemi]*vals[elemi];
         }
     }
     else
     {
-        forAll(faceCells, elemI)
+        forAll(faceCells, elemi)
         {
-            result[faceCells[elemI]] -= coeffs[elemI]*vals[elemI];
+            result[faceCells[elemi]] -= coeffs[elemi]*vals[elemi];
         }
     }
 }
diff --git a/src/OpenFOAM/matrices/lduMatrix/lduMatrix/lduMatrix.C b/src/OpenFOAM/matrices/lduMatrix/lduMatrix/lduMatrix.C
index 9c11818c2a73d240974d7e6999d1927d9e46a7b5..791dfbfb16c8f3c97c6bc47735fa4b4dfd40c48c 100644
--- a/src/OpenFOAM/matrices/lduMatrix/lduMatrix/lduMatrix.C
+++ b/src/OpenFOAM/matrices/lduMatrix/lduMatrix/lduMatrix.C
@@ -325,7 +325,7 @@ void Foam::lduMatrix::setResidualField
     const bool initial
 ) const
 {
-    if (!lduMesh_.hasDb())
+    if (!mesh().hasDb())
     {
         return;
     }
@@ -341,12 +341,12 @@ void Foam::lduMatrix::setResidualField
     }
 
     scalarIOField* residualPtr =
-        lduMesh_.thisDb().getObjectPtr<scalarIOField>(lookupName);
+        mesh().thisDb().getObjectPtr<scalarIOField>(lookupName);
 
     if (residualPtr)
     {
         const IOdictionary* dataPtr =
-            lduMesh_.thisDb().findObject<IOdictionary>("data");
+            mesh().thisDb().findObject<IOdictionary>("data");
 
         if (dataPtr)
         {
diff --git a/src/OpenFOAM/matrices/lduMatrix/lduMatrix/lduMatrix.H b/src/OpenFOAM/matrices/lduMatrix/lduMatrix/lduMatrix.H
index a99c488474301186d9b3e4649acb6bb9caf6bd7b..644de9caa0df36b69d8bbfae87b259800a3ae7d8 100644
--- a/src/OpenFOAM/matrices/lduMatrix/lduMatrix/lduMatrix.H
+++ b/src/OpenFOAM/matrices/lduMatrix/lduMatrix/lduMatrix.H
@@ -86,7 +86,8 @@ class lduMatrix
     // private data
 
         //- LDU mesh reference
-        const lduMesh& lduMesh_;
+        //const lduMesh& lduMesh_;
+        std::reference_wrapper<const lduMesh> lduMesh_;
 
         //- Coefficients (not including interfaces)
         scalarField *lowerPtr_, *diagPtr_, *upperPtr_;
@@ -569,10 +570,16 @@ public:
                 return lduMesh_;
             }
 
+            //- Set the LDU mesh containing the addressing is obtained
+            void setLduMesh(const lduMesh& m)
+            {
+                lduMesh_ = m;
+            }
+
             //- Return the LDU addressing
             const lduAddressing& lduAddr() const
             {
-                return lduMesh_.lduAddr();
+                return mesh().lduAddr();
             }
 
             //- Return the patch evaluation schedule
diff --git a/src/OpenFOAM/matrices/lduMatrix/lduMatrix/lduMatrixSolver.C b/src/OpenFOAM/matrices/lduMatrix/lduMatrix/lduMatrixSolver.C
index d3da2cf324d20a75f4cbf34d9e684175e3856717..b750b74a65b1b736d5076f2c9079268abab6f76f 100644
--- a/src/OpenFOAM/matrices/lduMatrix/lduMatrix/lduMatrixSolver.C
+++ b/src/OpenFOAM/matrices/lduMatrix/lduMatrix/lduMatrixSolver.C
@@ -204,13 +204,13 @@ Foam::solveScalarField::cmptType Foam::lduMatrix::solver::normFactor
     // --- Calculate A dot reference value of psi
     matrix_.sumA(tmpField, interfaceBouCoeffs_, interfaces_);
 
-    tmpField *= gAverage(psi, matrix_.lduMesh_.comm());
+    tmpField *= gAverage(psi, matrix_.mesh().comm());
 
     return
         gSum
         (
             (mag(Apsi - tmpField) + mag(source - tmpField))(),
-            matrix_.lduMesh_.comm()
+            matrix_.mesh().comm()
         )
       + solverPerformance::small_;
 
diff --git a/src/OpenFOAM/matrices/lduMatrix/lduMatrix/lduMatrixUpdateMatrixInterfaces.C b/src/OpenFOAM/matrices/lduMatrix/lduMatrix/lduMatrixUpdateMatrixInterfaces.C
index 914fbf4f156584b99d9caa950300268afb3002a6..e3c7421c6c604a7604d207c9f70f63109a9be172 100644
--- a/src/OpenFOAM/matrices/lduMatrix/lduMatrix/lduMatrixUpdateMatrixInterfaces.C
+++ b/src/OpenFOAM/matrices/lduMatrix/lduMatrix/lduMatrixUpdateMatrixInterfaces.C
@@ -54,6 +54,8 @@ void Foam::lduMatrix::initMatrixInterfaces
                 (
                     result,
                     add,
+                    mesh().lduAddr(),
+                    interfacei,
                     psiif,
                     coupleCoeffs[interfacei],
                     cmpt,
@@ -81,6 +83,8 @@ void Foam::lduMatrix::initMatrixInterfaces
                 (
                     result,
                     add,
+                    mesh().lduAddr(),
+                    interfacei,
                     psiif,
                     coupleCoeffs[interfacei],
                     cmpt,
@@ -120,6 +124,8 @@ void Foam::lduMatrix::updateMatrixInterfaces
                 (
                     result,
                     add,
+                    mesh().lduAddr(),
+                    interfacei,
                     psiif,
                     coupleCoeffs[interfacei],
                     cmpt,
@@ -149,6 +155,8 @@ void Foam::lduMatrix::updateMatrixInterfaces
                             (
                                 result,
                                 add,
+                                mesh().lduAddr(),
+                                interfacei,
                                 psiif,
                                 coupleCoeffs[interfacei],
                                 cmpt,
@@ -197,6 +205,8 @@ void Foam::lduMatrix::updateMatrixInterfaces
                 (
                     result,
                     add,
+                    mesh().lduAddr(),
+                    interfacei,
                     psiif,
                     coupleCoeffs[interfacei],
                     cmpt,
@@ -210,18 +220,20 @@ void Foam::lduMatrix::updateMatrixInterfaces
         const lduSchedule& patchSchedule = this->patchSchedule();
 
         // Loop over all the "normal" interfaces relating to standard patches
-        forAll(patchSchedule, i)
+        for (const auto& sched : patchSchedule)
         {
-            label interfacei = patchSchedule[i].patch;
+            const label interfacei = sched.patch;
 
             if (interfaces.set(interfacei))
             {
-                if (patchSchedule[i].init)
+                if (sched.init)
                 {
                     interfaces[interfacei].initInterfaceMatrixUpdate
                     (
                         result,
                         add,
+                        mesh().lduAddr(),
+                        interfacei,
                         psiif,
                         coupleCoeffs[interfacei],
                         cmpt,
@@ -234,6 +246,8 @@ void Foam::lduMatrix::updateMatrixInterfaces
                     (
                         result,
                         add,
+                        mesh().lduAddr(),
+                        interfacei,
                         psiif,
                         coupleCoeffs[interfacei],
                         cmpt,
@@ -258,6 +272,8 @@ void Foam::lduMatrix::updateMatrixInterfaces
                 (
                     result,
                     add,
+                    mesh().lduAddr(),
+                    interfacei,
                     psiif,
                     coupleCoeffs[interfacei],
                     cmpt,
diff --git a/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/GAMGAgglomerations/GAMGAgglomeration/GAMGAgglomerateLduAddressing.C b/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/GAMGAgglomerations/GAMGAgglomeration/GAMGAgglomerateLduAddressing.C
index 6c1c9f8e257980ace7d9eb4f3da018bb03f75cea..8cde62c9d0bd0c3a3e32ee0fdb43d91663566aed 100644
--- a/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/GAMGAgglomerations/GAMGAgglomeration/GAMGAgglomerateLduAddressing.C
+++ b/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/GAMGAgglomerations/GAMGAgglomeration/GAMGAgglomerateLduAddressing.C
@@ -29,6 +29,7 @@ License
 #include "GAMGAgglomeration.H"
 #include "GAMGInterface.H"
 #include "processorGAMGInterface.H"
+#include "cyclicLduInterface.H"
 
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
@@ -43,7 +44,7 @@ void Foam::GAMGAgglomeration::agglomerateLduAddressing
     const labelUList& upperAddr = fineMeshAddr.upperAddr();
     const labelUList& lowerAddr = fineMeshAddr.lowerAddr();
 
-    label nFineFaces = upperAddr.size();
+    const label nFineFaces = upperAddr.size();
 
     // Get restriction map for current level
     const labelField& restrictMap = restrictAddressing(fineLevelIndex);
@@ -282,15 +283,29 @@ void Foam::GAMGAgglomeration::agglomerateLduAddressing
     const label nReq = Pstream::nRequests();
 
     // Initialise transfer of restrict addressing on the interface
+    // The finest mesh uses patchAddr from the original lduAdressing.
+    // the coarser levels create their own adressing for faceCells
     forAll(fineInterfaces, inti)
     {
         if (fineInterfaces.set(inti))
         {
-            fineInterfaces[inti].initInternalFieldTransfer
-            (
-                Pstream::commsTypes::nonBlocking,
-                restrictMap
-            );
+            if (fineLevelIndex == 0)
+            {
+                fineInterfaces[inti].initInternalFieldTransfer
+                (
+                    Pstream::commsTypes::nonBlocking,
+                    restrictMap,
+                    fineMeshAddr.patchAddr(inti)
+                );
+            }
+            else
+            {
+                fineInterfaces[inti].initInternalFieldTransfer
+                (
+                    Pstream::commsTypes::nonBlocking,
+                    restrictMap
+                );
+            }
         }
     }
 
@@ -320,6 +335,51 @@ void Foam::GAMGAgglomeration::agglomerateLduAddressing
     {
         if (fineInterfaces.set(inti))
         {
+            tmp<labelField> restrictMapInternalField;
+
+            // The finest mesh uses patchAddr from the original lduAdressing.
+            // the coarser levels create thei own adressing for faceCells
+            if (fineLevelIndex == 0)
+            {
+                restrictMapInternalField =
+                    fineInterfaces[inti].interfaceInternalField
+                    (
+                        restrictMap,
+                        fineMeshAddr.patchAddr(inti)
+                    );
+            }
+            else
+            {
+                restrictMapInternalField =
+                    fineInterfaces[inti].interfaceInternalField
+                    (
+                        restrictMap
+                    );
+            }
+
+            tmp<labelField> nbrRestrictMapInternalField =
+                fineInterfaces[inti].internalFieldTransfer
+                (
+                    Pstream::commsTypes::nonBlocking,
+                    restrictMap
+                );
+
+            coarseInterfaces.set
+            (
+                inti,
+                GAMGInterface::New
+                (
+                    inti,
+                    meshLevels_[fineLevelIndex].rawInterfaces(),
+                    fineInterfaces[inti],
+                    restrictMapInternalField(),
+                    nbrRestrictMapInternalField(),
+                    fineLevelIndex,
+                    fineMesh.comm()
+                ).ptr()
+            );
+
+            /* Same as below:
             coarseInterfaces.set
             (
                 inti,
@@ -338,6 +398,7 @@ void Foam::GAMGAgglomeration::agglomerateLduAddressing
                     fineMesh.comm()
                 ).ptr()
             );
+            */
 
             nPatchFaces[inti] = coarseInterfaces[inti].faceCells().size();
             patchFineToCoarse[inti] = refCast<const GAMGInterface>
diff --git a/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/GAMGAgglomerations/GAMGAgglomeration/GAMGAgglomeration.C b/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/GAMGAgglomerations/GAMGAgglomeration/GAMGAgglomeration.C
index 28a7cf83497c44325b78a86128fa0e4d5812e412..cf9b4aa1dc01170ca383863d9a137eec6ef847f7 100644
--- a/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/GAMGAgglomerations/GAMGAgglomeration/GAMGAgglomeration.C
+++ b/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/GAMGAgglomerations/GAMGAgglomeration/GAMGAgglomeration.C
@@ -295,13 +295,17 @@ const Foam::GAMGAgglomeration& Foam::GAMGAgglomeration::New
     const dictionary& controlDict
 )
 {
-    if
-    (
-        !mesh.thisDb().foundObject<GAMGAgglomeration>
+    const GAMGAgglomeration* agglomPtr =
+        mesh.thisDb().cfindObject<GAMGAgglomeration>
         (
             GAMGAgglomeration::typeName
-        )
-    )
+        );
+
+    if (agglomPtr)
+    {
+        return *agglomPtr;
+    }
+
     {
         const word agglomeratorType
         (
@@ -331,13 +335,6 @@ const Foam::GAMGAgglomeration& Foam::GAMGAgglomeration::New
 
         return store(cstrIter()(mesh, controlDict).ptr());
     }
-    else
-    {
-        return mesh.thisDb().lookupObject<GAMGAgglomeration>
-        (
-            GAMGAgglomeration::typeName
-        );
-    }
 }
 
 
@@ -349,13 +346,17 @@ const Foam::GAMGAgglomeration& Foam::GAMGAgglomeration::New
 {
     const lduMesh& mesh = matrix.mesh();
 
-    if
-    (
-        !mesh.thisDb().foundObject<GAMGAgglomeration>
+    const GAMGAgglomeration* agglomPtr =
+        mesh.thisDb().cfindObject<GAMGAgglomeration>
         (
             GAMGAgglomeration::typeName
-        )
-    )
+        );
+
+    if (agglomPtr)
+    {
+        return *agglomPtr;
+    }
+
     {
         const word agglomeratorType
         (
@@ -385,17 +386,10 @@ const Foam::GAMGAgglomeration& Foam::GAMGAgglomeration::New
             return store(cstrIter()(matrix, controlDict).ptr());
         }
     }
-    else
-    {
-        return mesh.thisDb().lookupObject<GAMGAgglomeration>
-        (
-            GAMGAgglomeration::typeName
-        );
-    }
 }
 
 
-Foam::autoPtr<Foam::GAMGAgglomeration> Foam::GAMGAgglomeration::New
+const Foam::GAMGAgglomeration& Foam::GAMGAgglomeration::New
 (
     const lduMesh& mesh,
     const scalarField& cellVolumes,
@@ -403,40 +397,54 @@ Foam::autoPtr<Foam::GAMGAgglomeration> Foam::GAMGAgglomeration::New
     const dictionary& controlDict
 )
 {
-    const word agglomeratorType
-    (
-        controlDict.getOrDefault<word>("agglomerator", "faceAreaPair")
-    );
-
-    mesh.thisDb().time().libs().open
-    (
-        controlDict,
-        "geometricGAMGAgglomerationLibs",
-        geometryConstructorTablePtr_
-    );
 
-    auto cstrIter = geometryConstructorTablePtr_->cfind(agglomeratorType);
+    const GAMGAgglomeration* agglomPtr =
+        mesh.thisDb().cfindObject<GAMGAgglomeration>
+        (
+            GAMGAgglomeration::typeName
+        );
 
-    if (!cstrIter.found())
+    if (agglomPtr)
     {
-        FatalErrorInFunction
-            << "Unknown GAMGAgglomeration type "
-            << agglomeratorType << ".\n"
-            << "Valid geometric GAMGAgglomeration types :"
-            << geometryConstructorTablePtr_->sortedToc()
-            << exit(FatalError);
+        return *agglomPtr;
     }
 
-    return autoPtr<GAMGAgglomeration>
-    (
-        cstrIter()
+    {
+        const word agglomeratorType
         (
-            mesh,
-            cellVolumes,
-            faceAreas,
-            controlDict
-        )
-    );
+            controlDict.lookupOrDefault<word>("agglomerator", "faceAreaPair")
+        );
+
+        const_cast<Time&>(mesh.thisDb().time()).libs().open
+        (
+            controlDict,
+            "geometricGAMGAgglomerationLibs",
+            geometryConstructorTablePtr_
+        );
+
+        auto cstrIter = geometryConstructorTablePtr_->cfind(agglomeratorType);
+
+        if (!cstrIter.found())
+        {
+            FatalErrorInFunction
+                << "Unknown GAMGAgglomeration type "
+                << agglomeratorType << ".\n"
+                << "Valid geometric GAMGAgglomeration types :"
+                << geometryConstructorTablePtr_->sortedToc()
+                << exit(FatalError);
+        }
+
+        return store
+        (
+            cstrIter()
+            (
+                mesh,
+                cellVolumes,
+                faceAreas,
+                controlDict
+            ).ptr()
+        );
+    }
 }
 
 
@@ -609,8 +617,8 @@ bool Foam::GAMGAgglomeration::checkRestriction
 
         forAll(lower, facei)
         {
-            label own = lower[facei];
-            label nei = upper[facei];
+            const label own = lower[facei];
+            const label nei = upper[facei];
 
             if (restriction[own] == restriction[nei])
             {
@@ -683,7 +691,7 @@ bool Foam::GAMGAgglomeration::checkRestriction
         {
             const label coarseI = restriction[celli];
 
-            label index = coarseToMasters[coarseI].find(master[celli]);
+            const label index = coarseToMasters[coarseI].find(master[celli]);
             newRestrict[celli] = coarseToNewCoarse[coarseI][index];
         }
 
diff --git a/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/GAMGAgglomerations/GAMGAgglomeration/GAMGAgglomeration.H b/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/GAMGAgglomerations/GAMGAgglomeration/GAMGAgglomeration.H
index 0dd96c71505fe2a9e1b2d5b72b06ec2daafeabce..7377d0c95ab5bf645c97a865578f07de2f4aa978 100644
--- a/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/GAMGAgglomerations/GAMGAgglomeration/GAMGAgglomeration.H
+++ b/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/GAMGAgglomerations/GAMGAgglomeration/GAMGAgglomeration.H
@@ -306,7 +306,7 @@ public:
         );
 
         //- Return the selected geometric agglomerator
-        static autoPtr<GAMGAgglomeration> New
+        static const GAMGAgglomeration& New
         (
             const lduMesh& mesh,
             const scalarField& cellVolumes,
diff --git a/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaceFields/GAMGInterfaceField/GAMGInterfaceField.H b/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaceFields/GAMGInterfaceField/GAMGInterfaceField.H
index 79e34272e85e7c51ce4b9188e13bcc0482bb1354..714760b0f9c9e3e93326d917e7c3588a34770d19 100644
--- a/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaceFields/GAMGInterfaceField/GAMGInterfaceField.H
+++ b/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaceFields/GAMGInterfaceField/GAMGInterfaceField.H
@@ -6,6 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2013 OpenFOAM Foundation
+    Copyright (C) 2019 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
diff --git a/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaceFields/cyclicGAMGInterfaceField/cyclicGAMGInterfaceField.C b/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaceFields/cyclicGAMGInterfaceField/cyclicGAMGInterfaceField.C
index e8da82ea641578af8932e349d530ae41c7a972cd..7418b0cb4ec1bbe2b95cc28d90f72945dd60770c 100644
--- a/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaceFields/cyclicGAMGInterfaceField/cyclicGAMGInterfaceField.C
+++ b/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaceFields/cyclicGAMGInterfaceField/cyclicGAMGInterfaceField.C
@@ -107,6 +107,8 @@ void Foam::cyclicGAMGInterfaceField::updateInterfaceMatrix
 (
     solveScalarField& result,
     const bool add,
+    const lduAddressing& lduAddr,
+    const label patchId,
     const solveScalarField& psiInternal,
     const scalarField& coeffs,
     const direction cmpt,
@@ -114,14 +116,20 @@ void Foam::cyclicGAMGInterfaceField::updateInterfaceMatrix
 ) const
 {
     // Get neighbouring field
-    solveScalarField pnf
-    (
-        cyclicInterface_.neighbPatch().interfaceInternalField(psiInternal)
-    );
+
+    const labelList& nbrFaceCells =
+        lduAddr.patchAddr
+        (
+            cyclicInterface_.neighbPatchID()
+        );
+
+    solveScalarField pnf(psiInternal, nbrFaceCells);
 
     transformCoupleField(pnf, cmpt);
 
-    this->addToInternalField(result, !add, coeffs, pnf);
+    const labelList& faceCells = lduAddr.patchAddr(patchId);
+
+    this->addToInternalField(result, !add, faceCells, coeffs, pnf);
 }
 
 
diff --git a/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaceFields/cyclicGAMGInterfaceField/cyclicGAMGInterfaceField.H b/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaceFields/cyclicGAMGInterfaceField/cyclicGAMGInterfaceField.H
index 825f73b3d087b5e5075a66493d98a70beebeaceb..53571f8776ec8f2bb32efbe6c6515401a2da27bb 100644
--- a/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaceFields/cyclicGAMGInterfaceField/cyclicGAMGInterfaceField.H
+++ b/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaceFields/cyclicGAMGInterfaceField/cyclicGAMGInterfaceField.H
@@ -150,6 +150,8 @@ public:
             (
                 solveScalarField& result,
                 const bool add,
+                const lduAddressing& lduAddr,
+                const label patchId,
                 const solveScalarField& psiInternal,
                 const scalarField& coeffs,
                 const direction cmpt,
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 f72e69de5bfc716ba46d48c526a4c7fd31b987be..2451f8f6e752f4da2e2b01119a594d39fcc34133 100644
--- a/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaceFields/processorGAMGInterfaceField/processorGAMGInterfaceField.C
+++ b/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaceFields/processorGAMGInterfaceField/processorGAMGInterfaceField.C
@@ -91,6 +91,8 @@ void Foam::processorGAMGInterfaceField::initInterfaceMatrixUpdate
 (
     solveScalarField&,
     const bool,
+    const lduAddressing& lduAddr,
+    const label patchId,
     const solveScalarField& psiInternal,
     const scalarField&,
     const direction,
@@ -142,6 +144,8 @@ void Foam::processorGAMGInterfaceField::updateInterfaceMatrix
 (
     solveScalarField& result,
     const bool add,
+    const lduAddressing& lduAddr,
+    const label patchId,
     const solveScalarField&,
     const scalarField& coeffs,
     const direction cmpt,
@@ -153,6 +157,8 @@ void Foam::processorGAMGInterfaceField::updateInterfaceMatrix
         return;
     }
 
+    const labelUList& faceCells = lduAddr.patchAddr(patchId);
+
     if
     (
         commsType == Pstream::commsTypes::nonBlocking
@@ -178,7 +184,7 @@ void Foam::processorGAMGInterfaceField::updateInterfaceMatrix
         transformCoupleField(scalarReceiveBuf_, cmpt);
 
         // Multiply the field by coefficients and add into the result
-        addToInternalField(result, !add, coeffs, scalarReceiveBuf_);
+        addToInternalField(result, !add, faceCells, coeffs, scalarReceiveBuf_);
     }
     else
     {
@@ -192,7 +198,7 @@ void Foam::processorGAMGInterfaceField::updateInterfaceMatrix
         );
         transformCoupleField(pnf, cmpt);
 
-        addToInternalField(result, !add, coeffs, pnf);
+        addToInternalField(result, !add, faceCells, coeffs, pnf);
     }
 
     const_cast<processorGAMGInterfaceField&>(*this).updatedMatrix() = true;
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 db9c320b39bf6b36070fcf2525942ebd3788bfac..c4f945742740a883f39a5c12f24f386c7fca0a78 100644
--- a/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaceFields/processorGAMGInterfaceField/processorGAMGInterfaceField.H
+++ b/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaceFields/processorGAMGInterfaceField/processorGAMGInterfaceField.H
@@ -142,6 +142,8 @@ public:
             (
                 solveScalarField& result,
                 const bool add,
+                const lduAddressing& lduAddr,
+                const label patchId,
                 const solveScalarField& psiInternal,
                 const scalarField& coeffs,
                 const direction cmpt,
@@ -153,6 +155,8 @@ public:
             (
                 solveScalarField& result,
                 const bool add,
+                const lduAddressing& lduAddr,
+                const label patchId,
                 const solveScalarField& psiInternal,
                 const scalarField& coeffs,
                 const direction cmpt,
diff --git a/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaces/GAMGInterface/GAMGInterface.C b/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaces/GAMGInterface/GAMGInterface.C
index a9e14b01faf92a276639d3d6cc0b53389f8b7130..0b8d4aa592254196e676ba3fb5ee0a2fec3a6ead 100644
--- a/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaces/GAMGInterface/GAMGInterface.C
+++ b/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaces/GAMGInterface/GAMGInterface.C
@@ -6,6 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2016 OpenFOAM Foundation
+    Copyright (C) 2019 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -77,13 +78,23 @@ Foam::tmp<Foam::labelField> Foam::GAMGInterface::interfaceInternalField
 }
 
 
+Foam::tmp<Foam::labelField> Foam::GAMGInterface::interfaceInternalField
+(
+    const labelUList& internalData,
+    const labelUList& faceCells
+) const
+{
+    return interfaceInternalField<label>(internalData, faceCells);
+}
+
+
 Foam::tmp<Foam::scalarField> Foam::GAMGInterface::agglomerateCoeffs
 (
     const scalarField& fineCoeffs
 ) const
 {
-    tmp<scalarField> tcoarseCoeffs(new scalarField(size(), Zero));
-    scalarField& coarseCoeffs = tcoarseCoeffs.ref();
+    auto tcoarseCoeffs = tmp<scalarField>::New(size(), Zero);
+    auto& coarseCoeffs = tcoarseCoeffs.ref();
 
     if (fineCoeffs.size() != faceRestrictAddressing_.size())
     {
diff --git a/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaces/GAMGInterface/GAMGInterface.H b/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaces/GAMGInterface/GAMGInterface.H
index 5a9a0ad9d9c9cb1d7d5e915939a2eea2a77ae010..f8c861515ca2cd4fbdac362a3bc0ab68e5eb3496 100644
--- a/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaces/GAMGInterface/GAMGInterface.H
+++ b/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaces/GAMGInterface/GAMGInterface.H
@@ -6,6 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2016 OpenFOAM Foundation
+    Copyright (C) 2019 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -27,7 +28,7 @@ Class
     Foam::GAMGInterface
 
 Description
-     Abstract base class for GAMG agglomerated interfaces.
+    Abstract base class for GAMG agglomerated interfaces.
 
 SourceFiles
     GAMGInterface.C
@@ -55,7 +56,6 @@ class GAMGInterface
 :
     public lduInterface
 {
-
 protected:
 
     // Protected data
@@ -73,9 +73,7 @@ protected:
         labelList faceRestrictAddressing_;
 
 
-private:
-
-    // Private Member Functions
+    // Protected Member Functions
 
         //- No copy construct
         GAMGInterface(const GAMGInterface&) = delete;
@@ -245,6 +243,15 @@ public:
                 const UList<Type>& internalData
             ) const;
 
+            //- Return the interface internal field of the given field
+            //- using faceCell mapping
+            template<class Type>
+            tmp<Field<Type>> interfaceInternalField
+            (
+                const UList<Type>& internalData,
+                const labelUList& faceCells
+            ) const;
+
             //- Get the interface internal field of the given field
             template<class Type>
             void interfaceInternalField
@@ -260,6 +267,14 @@ public:
                 const labelUList& internalData
             ) const;
 
+            //- Return the values of the given internal data adjacent to
+            //- the interface as a field using faceCell mapping
+            virtual tmp<labelField> interfaceInternalField
+            (
+                const labelUList& internalData,
+                const labelUList& faceCells
+            ) const;
+
 
         // Agglomeration
 
diff --git a/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaces/GAMGInterface/GAMGInterfaceTemplates.C b/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaces/GAMGInterface/GAMGInterfaceTemplates.C
index b7d27316bfc93a3209e85b23352a903a7432c95f..ac3c1cfa563360e2bbdb63f1f41406281d8824d2 100644
--- a/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaces/GAMGInterface/GAMGInterfaceTemplates.C
+++ b/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaces/GAMGInterface/GAMGInterfaceTemplates.C
@@ -6,6 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2016 OpenFOAM Foundation
+    Copyright (C) 2019 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -35,12 +36,30 @@ Foam::tmp<Foam::Field<Type>> Foam::GAMGInterface::interfaceInternalField
     const UList<Type>& iF
 ) const
 {
-    tmp<Field<Type>> tresult(new Field<Type>(size()));
+    auto tresult = tmp<Field<Type>>::New(size());
     interfaceInternalField(iF, tresult.ref());
     return tresult;
 }
 
 
+template<class Type>
+Foam::tmp<Foam::Field<Type>> Foam::GAMGInterface::interfaceInternalField
+(
+    const UList<Type>& iF,
+    const labelUList& faceCells
+) const
+{
+    auto tresult = tmp<Field<Type>>::New(faceCells.size());
+    auto& result = tresult.ref();
+
+    forAll(result, elemi)
+    {
+        result[elemi] = iF[faceCells[elemi]];
+    }
+    return tresult;
+}
+
+
 template<class Type>
 void Foam::GAMGInterface::interfaceInternalField
 (
@@ -48,11 +67,11 @@ void Foam::GAMGInterface::interfaceInternalField
     List<Type>& result
 ) const
 {
-    result.setSize(size());
+    result.resize(size());
 
-    forAll(result, elemI)
+    forAll(result, elemi)
     {
-        result[elemI] = iF[faceCells_[elemI]];
+        result[elemi] = iF[faceCells_[elemi]];
     }
 }
 
diff --git a/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaces/cyclicGAMGInterface/cyclicGAMGInterface.C b/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaces/cyclicGAMGInterface/cyclicGAMGInterface.C
index d8c18b53e170b888b5ea2426ce360b4861a930dd..937aecdbbb67b1f46672d67f5d240388b6bfeb50 100644
--- a/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaces/cyclicGAMGInterface/cyclicGAMGInterface.C
+++ b/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaces/cyclicGAMGInterface/cyclicGAMGInterface.C
@@ -166,7 +166,7 @@ Foam::cyclicGAMGInterface::cyclicGAMGInterface
 
 Foam::tmp<Foam::labelField> Foam::cyclicGAMGInterface::internalFieldTransfer
 (
-    const Pstream::commsTypes,
+    const Pstream::commsTypes commsType,
     const labelUList& iF
 ) const
 {
diff --git a/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaces/cyclicGAMGInterface/cyclicGAMGInterface.H b/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaces/cyclicGAMGInterface/cyclicGAMGInterface.H
index 95856c9f8fd60084f25c7502f28012d92ec9c017..d6f56a48d5289e74944d5ea22b2868b35fec5a10 100644
--- a/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaces/cyclicGAMGInterface/cyclicGAMGInterface.H
+++ b/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaces/cyclicGAMGInterface/cyclicGAMGInterface.H
@@ -162,7 +162,7 @@ public:
         // I/O
 
             //- Write to stream
-            virtual void write(Ostream&) const;
+            virtual void write(Ostream& os) const;
 };
 
 
diff --git a/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaces/processorGAMGInterface/processorGAMGInterface.C b/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaces/processorGAMGInterface/processorGAMGInterface.C
index b74567d029b89c85303d0367f1a99576ebbb69ab..eeb7807c9a654137a3808b759e9ea58580d8f6ea 100644
--- a/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaces/processorGAMGInterface/processorGAMGInterface.C
+++ b/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaces/processorGAMGInterface/processorGAMGInterface.C
@@ -191,13 +191,24 @@ void Foam::processorGAMGInterface::initInternalFieldTransfer
 }
 
 
+void Foam::processorGAMGInterface::initInternalFieldTransfer
+(
+    const Pstream::commsTypes commsType,
+    const labelUList& iF,
+    const labelUList& faceCells
+) const
+{
+    send(commsType, interfaceInternalField(iF, faceCells)());
+}
+
+
 Foam::tmp<Foam::labelField> Foam::processorGAMGInterface::internalFieldTransfer
 (
     const Pstream::commsTypes commsType,
     const labelUList& iF
 ) const
 {
-    tmp<Field<label>> tfld(receive<label>(commsType, this->size()));
+    tmp<labelField> tfld(receive<label>(commsType, this->size()));
 
     return tfld;
 }
diff --git a/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaces/processorGAMGInterface/processorGAMGInterface.H b/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaces/processorGAMGInterface/processorGAMGInterface.H
index 5c674c704a29ffebe7a871646e72e6beb359b62b..e4150c53334069e1b18ee9a6f2500fef6a72c785 100644
--- a/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaces/processorGAMGInterface/processorGAMGInterface.H
+++ b/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaces/processorGAMGInterface/processorGAMGInterface.H
@@ -90,7 +90,7 @@ public:
     // Constructors
 
         //- Construct from fine-level interface,
-        //  local and neighbour restrict addressing
+        //- local and neighbour restrict addressing
         processorGAMGInterface
         (
             const label index,
@@ -140,6 +140,15 @@ public:
                 const labelUList& iF
             ) const;
 
+
+            //- Initialise neighbour field transfer using faceCells mapping
+            virtual void initInternalFieldTransfer
+            (
+                const Pstream::commsTypes commsType,
+                const labelUList& iF,
+                const labelUList& faceCells
+            ) const;
+
             //- Transfer and return internal field adjacent to the interface
             virtual tmp<labelField> internalFieldTransfer
             (
@@ -184,7 +193,7 @@ public:
         // I/O
 
             //- Write to stream
-            virtual void write(Ostream&) const;
+            virtual void write(Ostream& os) const;
 };
 
 
diff --git a/src/OpenFOAM/meshes/lduMesh/lduMesh.H b/src/OpenFOAM/meshes/lduMesh/lduMesh.H
index 3cfb0f79f9eb1e0783e51c7219c3121ee9cd08d3..84edbffb39eb5cb786b4a438392954c599ecc683 100644
--- a/src/OpenFOAM/meshes/lduMesh/lduMesh.H
+++ b/src/OpenFOAM/meshes/lduMesh/lduMesh.H
@@ -89,7 +89,7 @@ public:
             virtual const lduAddressing& lduAddr() const = 0;
 
             //- Return a list of pointers for each patch
-            //  with only those pointing to interfaces being set
+            //- with only those pointing to interfaces being set
             virtual lduInterfacePtrsList interfaces() const = 0;
 
             //- Return communicator used for parallel communication
diff --git a/src/OpenFOAM/meshes/lduMesh/lduPrimitiveMesh.C b/src/OpenFOAM/meshes/lduMesh/lduPrimitiveMesh.C
index 5915ba55a308af27f86473f77425007c20cfcfc7..45177b822b8a7230853914e3e012366899141e3a 100644
--- a/src/OpenFOAM/meshes/lduMesh/lduPrimitiveMesh.C
+++ b/src/OpenFOAM/meshes/lduMesh/lduPrimitiveMesh.C
@@ -41,23 +41,24 @@ namespace Foam
     //- Less operator for pairs of \<processor\>\<index\>
     class procLess
     {
-        const labelPairList& lst_;
+        const labelPairList& list_;
 
     public:
 
-        procLess(const labelPairList& lst)
+        procLess(const labelPairList& list)
         :
-            lst_(lst)
+            list_(list)
         {}
 
         bool operator()(const label a, const label b)
         {
-            return lst_[a].first() < lst_[b].first();
+            return list_[a].first() < list_[b].first();
         }
     };
 
 }
 
+
 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
 
 void Foam::lduPrimitiveMesh::checkUpperTriangular
@@ -85,7 +86,7 @@ void Foam::lduPrimitiveMesh::checkUpperTriangular
         }
     }
 
-    for (label facei=1; facei < l.size(); facei++)
+    for (label facei=1; facei < l.size(); ++facei)
     {
         if (l[facei-1] > l[facei])
         {
@@ -113,6 +114,132 @@ void Foam::lduPrimitiveMesh::checkUpperTriangular
 }
 
 
+Foam::labelListList Foam::lduPrimitiveMesh::globalCellCells
+(
+    const lduMesh& mesh,
+    const globalIndex& globalNumbering
+)
+{
+    const lduAddressing& addr = mesh.lduAddr();
+    lduInterfacePtrsList interfaces = mesh.interfaces();
+
+    const labelList globalIndices
+    (
+        identity
+        (
+            addr.size(),
+            globalNumbering.localStart(UPstream::myProcNo(mesh.comm()))
+        )
+    );
+
+    // Get the interface cells
+    PtrList<labelList> nbrGlobalCells(interfaces.size());
+    {
+        // Initialise transfer of restrict addressing on the interface
+        forAll(interfaces, inti)
+        {
+            if (interfaces.set(inti))
+            {
+                interfaces[inti].initInternalFieldTransfer
+                (
+                    Pstream::commsTypes::nonBlocking,
+                    globalIndices
+                );
+            }
+        }
+
+        if (Pstream::parRun())
+        {
+            Pstream::waitRequests();
+        }
+
+        forAll(interfaces, inti)
+        {
+            if (interfaces.set(inti))
+            {
+                nbrGlobalCells.set
+                (
+                    inti,
+                    new labelList
+                    (
+                        interfaces[inti].internalFieldTransfer
+                        (
+                            Pstream::commsTypes::nonBlocking,
+                            globalIndices
+                        )
+                    )
+                );
+            }
+        }
+    }
+
+
+    // Scan the neighbour list to find out how many times the cell
+    // appears as a neighbour of the face. Done this way to avoid guessing
+    // and resizing list
+    labelList nNbrs(addr.size(), Zero);
+
+    const labelUList& nbr = addr.upperAddr();
+    const labelUList& own = addr.lowerAddr();
+
+    {
+        forAll(nbr, facei)
+        {
+            nNbrs[nbr[facei]]++;
+            nNbrs[own[facei]]++;
+        }
+
+        forAll(interfaces, inti)
+        {
+            if (interfaces.set(inti))
+            {
+                for (const label celli : interfaces[inti].faceCells())
+                {
+                    nNbrs[celli]++;
+                }
+            }
+        }
+    }
+
+
+    // Create cell-cells addressing
+    labelListList cellCells(addr.size());
+
+    forAll(cellCells, celli)
+    {
+        cellCells[celli].setSize(nNbrs[celli], -1);
+    }
+
+    // Reset the list of number of neighbours to zero
+    nNbrs = 0;
+
+    // Scatter the neighbour faces
+    forAll(nbr, facei)
+    {
+        const label c0 = own[facei];
+        const label c1 = nbr[facei];
+
+        cellCells[c0][nNbrs[c0]++] = globalIndices[c1];
+        cellCells[c1][nNbrs[c1]++] = globalIndices[c0];
+    }
+    forAll(interfaces, inti)
+    {
+        if (interfaces.set(inti))
+        {
+            const labelUList& faceCells = interfaces[inti].faceCells();
+
+            forAll(faceCells, facei)
+            {
+                const label c0 = faceCells[facei];
+                cellCells[c0][nNbrs[c0]++] = nbrGlobalCells[inti][facei];
+            }
+        }
+    }
+
+    return cellCells;
+}
+
+
 Foam::label Foam::lduPrimitiveMesh::totalSize
 (
     const PtrList<lduPrimitiveMesh>& meshes
@@ -164,7 +291,7 @@ Foam::labelList Foam::lduPrimitiveMesh::upperTriOrder
     labelList cellToFaces(offsets.last());
     forAll(upper, facei)
     {
-        label celli = lower[facei];
+        const label celli = lower[facei];
         cellToFaces[nNbrs[celli]++] = facei;
     }
 
@@ -172,17 +299,19 @@ Foam::labelList Foam::lduPrimitiveMesh::upperTriOrder
 
     labelList oldToNew(lower.size());
 
-    labelList order;
-    labelList nbr;
+    DynamicList<label> order;
+    DynamicList<label> nbr;
 
     label newFacei = 0;
 
-    for (label celli = 0; celli < nCells; celli++)
+    for (label celli = 0; celli < nCells; ++celli)
     {
-        label startOfCell = offsets[celli];
-        label nNbr = offsets[celli+1] - startOfCell;
+        const label startOfCell = offsets[celli];
+        const label nNbr = offsets[celli+1] - startOfCell;
+
+        nbr.resize(nNbr);
+        order.resize(nNbr);
 
-        nbr.setSize(nNbr);
         forAll(nbr, i)
         {
             nbr[i] = upper[cellToFaces[offsets[celli]+i]];
@@ -216,7 +345,6 @@ Foam::lduPrimitiveMesh::lduPrimitiveMesh
     comm_(comm)
 {}
 
-
 void Foam::lduPrimitiveMesh::addInterfaces
 (
     lduInterfacePtrsList& interfaces,
@@ -238,6 +366,16 @@ void Foam::lduPrimitiveMesh::addInterfaces
 }
 
 
+Foam::lduPrimitiveMesh::lduPrimitiveMesh
+(
+    const label nCells
+)
+:
+    lduAddressing(nCells),
+    comm_(0)
+{}
+
+
 Foam::lduPrimitiveMesh::lduPrimitiveMesh
 (
     const label nCells,
@@ -251,7 +389,7 @@ Foam::lduPrimitiveMesh::lduPrimitiveMesh
     lduAddressing(nCells),
     lowerAddr_(l, true),
     upperAddr_(u, true),
-    primitiveInterfaces_(0),
+    primitiveInterfaces_(),
     patchSchedule_(ps),
     comm_(comm)
 {
@@ -286,10 +424,6 @@ Foam::lduPrimitiveMesh::lduPrimitiveMesh
 )
 :
     lduAddressing(myMesh.lduAddr().size() + totalSize(otherMeshes)),
-    lowerAddr_(0),
-    upperAddr_(0),
-    interfaces_(0),
-    patchSchedule_(0),
     comm_(comm)
 {
     const label currentComm = myMesh.comm();
@@ -338,7 +472,7 @@ Foam::lduPrimitiveMesh::lduPrimitiveMesh
     // Cells get added in order.
     cellOffsets.setSize(nMeshes+1);
     cellOffsets[0] = 0;
-    for (label procMeshI = 0; procMeshI < nMeshes; procMeshI++)
+    for (label procMeshI = 0; procMeshI < nMeshes; ++procMeshI)
     {
         const lduMesh& procMesh = mesh(myMesh, otherMeshes, procMeshI);
 
@@ -351,7 +485,7 @@ Foam::lduPrimitiveMesh::lduPrimitiveMesh
     // Faces initially get added in order, sorted later
     labelList internalFaceOffsets(nMeshes+1);
     internalFaceOffsets[0] = 0;
-    for (label procMeshI = 0; procMeshI < nMeshes; procMeshI++)
+    for (label procMeshI = 0; procMeshI < nMeshes; ++procMeshI)
     {
         const lduMesh& procMesh = mesh(myMesh, otherMeshes, procMeshI);
 
@@ -380,7 +514,7 @@ Foam::lduPrimitiveMesh::lduPrimitiveMesh
     label nOtherInterfaces = 0;
     labelList nCoupledFaces(nMeshes, Zero);
 
-    for (label procMeshI = 0; procMeshI < nMeshes; procMeshI++)
+    for (label procMeshI = 0; procMeshI < nMeshes; ++procMeshI)
     {
         const lduInterfacePtrsList interfaces =
             mesh(myMesh, otherMeshes, procMeshI).interfaces();
@@ -539,7 +673,7 @@ Foam::lduPrimitiveMesh::lduPrimitiveMesh
     faceOffsets.setSize(nMeshes+1);
     faceOffsets[0] = 0;
     faceMap.setSize(nMeshes);
-    for (label procMeshI = 0; procMeshI < nMeshes; procMeshI++)
+    for (label procMeshI = 0; procMeshI < nMeshes; ++procMeshI)
     {
         const lduMesh& procMesh = mesh(myMesh, otherMeshes, procMeshI);
         label nInternal = procMesh.lduAddr().lowerAddr().size();
@@ -566,7 +700,7 @@ Foam::lduPrimitiveMesh::lduPrimitiveMesh
     // Old internal faces and resolved coupled interfaces
     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-    for (label procMeshI = 0; procMeshI < nMeshes; procMeshI++)
+    for (label procMeshI = 0; procMeshI < nMeshes; ++procMeshI)
     {
         const lduMesh& procMesh = mesh(myMesh, otherMeshes, procMeshI);
 
@@ -961,7 +1095,7 @@ void Foam::lduPrimitiveMesh::gather
         otherMeshes.setSize(procIDs.size()-1);
 
         // Slave meshes
-        for (label i = 1; i < procIDs.size(); i++)
+        for (label i = 1; i < procIDs.size(); ++i)
         {
             //Pout<< "on master :"
             //    << " receiving from slave " << procIDs[i] << endl;
diff --git a/src/OpenFOAM/meshes/lduMesh/lduPrimitiveMesh.H b/src/OpenFOAM/meshes/lduMesh/lduPrimitiveMesh.H
index 665c50d99d336b40a6f807e1eb171cacf8a6ca80..5f1a8a6d68fa9cfc9a557ccc16f34f42f7aabfba 100644
--- a/src/OpenFOAM/meshes/lduMesh/lduPrimitiveMesh.H
+++ b/src/OpenFOAM/meshes/lduMesh/lduPrimitiveMesh.H
@@ -28,7 +28,7 @@ Class
     Foam::lduPrimitiveMesh
 
 Description
-    Simplest contrete lduMesh which stores the addressing needed by lduMatrix.
+    Simplest concrete lduMesh that stores the addressing needed by lduMatrix.
 
 SourceFiles
     lduPrimitiveMesh.C
@@ -99,6 +99,9 @@ public:
 
     // Constructors
 
+        //- Construct from number of cells
+        explicit lduPrimitiveMesh(const label nCells);
+
         //- Construct from components but without interfaces. Add interfaces
         //  separately using addInterfaces
         lduPrimitiveMesh
@@ -110,6 +113,7 @@ public:
             bool reuse
         );
 
+
         //- Add interfaces to a mesh constructed without
         void addInterfaces
         (
@@ -186,13 +190,32 @@ public:
                 return *this;
             }
 
+            //- Return non-const ldu addressing
+            virtual lduAddressing& lduAddr()
+            {
+                return *this;
+            }
+
             //- Return a list of pointers for each patch
-            //  with only those pointing to interfaces being set
+            //- with only those pointing to interfaces being set
             virtual lduInterfacePtrsList interfaces() const
             {
                 return interfaces_;
             }
 
+            //- Return a non-const list of pointers for each patch
+            //- with only those pointing to interfaces being set
+            virtual lduInterfacePtrsList& interfaces()
+            {
+                return interfaces_;
+            }
+
+            //- Return a non-const list of primitive interfaces
+            PtrList<const lduInterface>& primitiveInterfaces()
+            {
+                return primitiveInterfaces_;
+            }
+
             //- Return a list of pointers for each patch
             //  with only those pointing to interfaces being set
             //  (reference to cached interfaces)
@@ -219,6 +242,18 @@ public:
                 return upperAddr_;
             }
 
+            //- Return non-const Lower addressing
+            virtual labelList& lowerAddr()
+            {
+                return lowerAddr_;
+            }
+
+            //- Return non-const Upper addressing
+            virtual labelList& upperAddr()
+            {
+                return upperAddr_;
+            }
+
             //- Return patch addressing
             virtual const labelUList& patchAddr(const label i) const
             {
@@ -271,6 +306,13 @@ public:
                 const labelUList& l,
                 const labelUList& u
             );
+
+            //- Calculate global cell-cells
+            static labelListList globalCellCells
+            (
+                const lduMesh& mesh,
+                const globalIndex& globalNumbering
+            );
 };
 
 
diff --git a/src/OpenFOAM/meshes/polyMesh/polyPatches/basic/coupled/coupledPolyPatch.C b/src/OpenFOAM/meshes/polyMesh/polyPatches/basic/coupled/coupledPolyPatch.C
index c41960bc731f34d740baa3fd2e28bd363020bb06..c850d08db2e13e6041ee2ea306714c8321083910 100644
--- a/src/OpenFOAM/meshes/polyMesh/polyPatches/basic/coupled/coupledPolyPatch.C
+++ b/src/OpenFOAM/meshes/polyMesh/polyPatches/basic/coupled/coupledPolyPatch.C
@@ -70,9 +70,9 @@ void Foam::coupledPolyPatch::writeOBJ
     const labelList& pointLabels
 )
 {
-    forAll(pointLabels, i)
+    for (const label pointi : pointLabels)
     {
-        writeOBJ(os, points[pointLabels[i]]);
+        writeOBJ(os, points[pointi]);
     }
 }
 
@@ -108,10 +108,8 @@ void Foam::coupledPolyPatch::writeOBJ
 
     label vertI = 0;
 
-    forAll(faces, i)
+    for (const face& f : faces)
     {
-        const face& f = faces[i];
-
         forAll(f, fp)
         {
             if (foamToObj.insert(f[fp], vertI))
@@ -526,6 +524,18 @@ Foam::coupledPolyPatch::coupledPolyPatch
 {}
 
 
+Foam::coupledPolyPatch::coupledPolyPatch
+(
+    const coupledPolyPatch& pp,
+    const labelList& faceCells
+)
+:
+    polyPatch(pp, faceCells),
+    matchTolerance_(pp.matchTolerance_),
+    transform_(pp.transform_)
+{}
+
+
 Foam::coupledPolyPatch::coupledPolyPatch
 (
     const coupledPolyPatch& pp,
diff --git a/src/OpenFOAM/meshes/polyMesh/polyPatches/basic/coupled/coupledPolyPatch.H b/src/OpenFOAM/meshes/polyMesh/polyPatches/basic/coupled/coupledPolyPatch.H
index 8d27edca12718a8bc3686282a0a6cd08e3eb71f8..63a278641768fe6aab1b97ef36679b4783a9060a 100644
--- a/src/OpenFOAM/meshes/polyMesh/polyPatches/basic/coupled/coupledPolyPatch.H
+++ b/src/OpenFOAM/meshes/polyMesh/polyPatches/basic/coupled/coupledPolyPatch.H
@@ -6,6 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2015 OpenFOAM Foundation
+    Copyright (C) 2019 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -207,11 +208,14 @@ public:
             const word& patchType
         );
 
-        //- Construct as copy, resetting the boundary mesh
-        coupledPolyPatch(const coupledPolyPatch&, const polyBoundaryMesh&);
+        //- Copy construct, resetting the boundary mesh
+        coupledPolyPatch(const coupledPolyPatch&, const polyBoundaryMesh& bm);
+
+        //- Copy construct, resetting the faceCells
+        coupledPolyPatch(const coupledPolyPatch&, const labelList& faceCells);
 
         //- Construct given the original patch and resetting the
-        //  face list and boundary mesh information
+        //- face list and boundary mesh information
         coupledPolyPatch
         (
             const coupledPolyPatch& pp,
@@ -238,6 +242,7 @@ public:
 
     // Member Functions
 
+
         // Access
 
             //- Return true because this patch is coupled
@@ -360,7 +365,7 @@ public:
         );
 
         //- Write the polyPatch data as a dictionary
-        virtual void write(Ostream&) const;
+        virtual void write(Ostream& os) const;
 };
 
 
diff --git a/src/OpenFOAM/meshes/polyMesh/polyPatches/constraint/cyclic/cyclicPolyPatch.C b/src/OpenFOAM/meshes/polyMesh/polyPatches/constraint/cyclic/cyclicPolyPatch.C
index aea5b63c8c0fbe784fe852b33e88a73835f80353..6b62c55f54634170fe3b944d46b3fb5c7fb85c10 100644
--- a/src/OpenFOAM/meshes/polyMesh/polyPatches/constraint/cyclic/cyclicPolyPatch.C
+++ b/src/OpenFOAM/meshes/polyMesh/polyPatches/constraint/cyclic/cyclicPolyPatch.C
@@ -734,6 +734,28 @@ Foam::cyclicPolyPatch::cyclicPolyPatch
 }
 
 
+Foam::cyclicPolyPatch::cyclicPolyPatch
+(
+    const cyclicPolyPatch& pp,
+    const label nrbPatchID,
+    const labelList& faceCells
+)
+:
+    coupledPolyPatch(pp, faceCells),
+    neighbPatchName_(pp.neighbPatchName_),
+    coupleGroup_(pp.coupleGroup_),
+    neighbPatchID_(nrbPatchID),
+    rotationAxis_(pp.rotationAxis_),
+    rotationCentre_(pp.rotationCentre_),
+    separationVector_(pp.separationVector_),
+    coupledPointsPtr_(nullptr),
+    coupledEdgesPtr_(nullptr)
+{
+    // Neighbour patch might not be valid yet so no transformation
+    // calculation possible.
+}
+
+
 Foam::cyclicPolyPatch::cyclicPolyPatch
 (
     const cyclicPolyPatch& pp,
diff --git a/src/OpenFOAM/meshes/polyMesh/polyPatches/constraint/cyclic/cyclicPolyPatch.H b/src/OpenFOAM/meshes/polyMesh/polyPatches/constraint/cyclic/cyclicPolyPatch.H
index 082e77b1a8c15fc75f0bed5a89f8a2bfac3573c8..13302a8f46978b92ea2d5289eda4b3a059853a73 100644
--- a/src/OpenFOAM/meshes/polyMesh/polyPatches/constraint/cyclic/cyclicPolyPatch.H
+++ b/src/OpenFOAM/meshes/polyMesh/polyPatches/constraint/cyclic/cyclicPolyPatch.H
@@ -6,6 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2015 OpenFOAM Foundation
+    Copyright (C) 2019 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -234,11 +235,19 @@ public:
             const word& patchType
         );
 
-        //- Construct as copy, resetting the boundary mesh
+        //- Copy construct, resetting the boundary mesh
         cyclicPolyPatch(const cyclicPolyPatch&, const polyBoundaryMesh&);
 
+        //- Copy construct, resetting nbrPatchID and faceCells
+        cyclicPolyPatch
+        (
+            const cyclicPolyPatch&,
+            label nbrPatchID,
+            const labelList& faceCells
+        );
+
         //- Construct given the original patch and resetting the
-        //  face list and boundary mesh information
+        //- face list and boundary mesh information
         cyclicPolyPatch
         (
             const cyclicPolyPatch& pp,
@@ -312,6 +321,49 @@ public:
 
     // Member Functions
 
+        // Implicit Functions
+
+             //- Return number of new internal of this polyPatch faces
+            virtual void newInternalProcFaces
+            (
+                label& newFaces,
+                label& newProcFaces
+            ) const
+            {
+                newFaces = this->size();
+                newProcFaces = neighbPatch().size() - this->size();
+            }
+
+            //- Return nbrCells
+            virtual const labelUList& nbrCells() const
+            {
+                return neighbPatch().faceCells();
+            }
+
+            virtual label neighbPolyPatchID() const
+            {
+                return this->neighbPatchID();
+            }
+
+            virtual refPtr<labelListList> mapCollocatedFaces() const
+            {
+                refPtr<labelListList> tMap(new labelListList(this->size()));
+                labelListList& map = tMap.ref();
+                forAll (map, i)
+                {
+                    labelList& subMap = map[i];
+                    subMap.setSize(1);
+                    subMap[0] = i;
+                }
+                return tMap;
+            }
+
+            //- Return implicit master
+            virtual bool masterImplicit() const
+            {
+                return owner();
+            }
+
         //- Neighbour patch name
         const word& neighbPatchName() const;
 
diff --git a/src/OpenFOAM/meshes/polyMesh/polyPatches/polyPatch/polyPatch.C b/src/OpenFOAM/meshes/polyMesh/polyPatches/polyPatch/polyPatch.C
index 39ab12285e380ab47643da7d01eac1d4e0f29c7b..d466d6f174f93157157bbb6f2e2c4a518cd56a16 100644
--- a/src/OpenFOAM/meshes/polyMesh/polyPatches/polyPatch/polyPatch.C
+++ b/src/OpenFOAM/meshes/polyMesh/polyPatches/polyPatch/polyPatch.C
@@ -252,6 +252,18 @@ Foam::polyPatch::polyPatch(const polyPatch& p)
 {}
 
 
+Foam::polyPatch::polyPatch
+(
+    const polyPatch& p,
+    const labelList& faceCells
+)
+:
+    polyPatch(p)
+{
+    faceCellsPtr_ = new labelList::subList(faceCells, faceCells.size());
+}
+
+
 // * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
 
 Foam::polyPatch::~polyPatch()
diff --git a/src/OpenFOAM/meshes/polyMesh/polyPatches/polyPatch/polyPatch.H b/src/OpenFOAM/meshes/polyMesh/polyPatches/polyPatch/polyPatch.H
index 66145d39a7fcf53316d67bdfa0e4b85a8f6f9243..ba7570e96d5450f1933b958b27b540cc990c3d3f 100644
--- a/src/OpenFOAM/meshes/polyMesh/polyPatches/polyPatch/polyPatch.H
+++ b/src/OpenFOAM/meshes/polyMesh/polyPatches/polyPatch/polyPatch.H
@@ -203,11 +203,11 @@ public:
             const word& patchType
         );
 
-        //- Construct as copy, resetting the boundary mesh
+        //- Copy construct, resetting the boundary mesh
         polyPatch(const polyPatch&, const polyBoundaryMesh&);
 
         //- Construct given the original patch and resetting the
-        //  face list and boundary mesh information
+        //- face list and boundary mesh information
         polyPatch
         (
             const polyPatch& pp,
@@ -227,8 +227,19 @@ public:
             const label newStart
         );
 
-        //- Construct as copy
-        polyPatch(const polyPatch&);
+        //- Copy construct
+        polyPatch(const polyPatch& p);
+
+        //- Copy construct, setting faceCells
+        //  \note The faceCells are held by the caller
+        polyPatch(const polyPatch& p, const labelList& faceCells);
+
+        //- Construct and return a clone, setting faceCells
+        //  \note The faceCells are held by the caller
+        virtual autoPtr<polyPatch> clone(const labelList& faceCells) const
+        {
+            return autoPtr<polyPatch>::New(*this, faceCells);
+        }
 
         //- Construct and return a clone, resetting the boundary mesh
         virtual autoPtr<polyPatch> clone(const polyBoundaryMesh& bm) const
@@ -266,8 +277,7 @@ public:
 
     // Selectors
 
-        //- Return a pointer to a new patch created on freestore from
-        //  components
+        //- Return pointer to a new patch created on freestore from components
         static autoPtr<polyPatch> New
         (
             const word& patchType,
@@ -278,8 +288,7 @@ public:
             const polyBoundaryMesh& bm
         );
 
-        //- Return a pointer to a new patch created on freestore from
-        //  dictionary
+        //- Return pointer to a new patch created on freestore from dictionary
         static autoPtr<polyPatch> New
         (
             const word& name,
@@ -288,8 +297,7 @@ public:
             const polyBoundaryMesh& bm
         );
 
-        //- Return a pointer to a new patch created on freestore from
-        //  dictionary
+        //- Return pointer to a new patch created on freestore from dictionary
         static autoPtr<polyPatch> New
         (
             const word& patchType,
@@ -306,6 +314,51 @@ public:
 
     // Member Functions
 
+
+        // Implicit treatment functions
+
+            //- Return number of new internal of this polyPatch faces
+            virtual void newInternalProcFaces(label&, label&) const
+            {
+                NotImplemented;
+            }
+
+            //- Return nbrCells
+            virtual const labelUList& nbrCells() const
+            {
+                NotImplemented
+                return faceCells();
+            }
+
+            //- Return nbr patchID
+            virtual label neighbPolyPatchID() const
+            {
+                NotImplemented;
+                return -1;
+            }
+
+            //- Return mapped collocated faces
+            virtual refPtr<labelListList> mapCollocatedFaces() const
+            {
+                NotImplemented;
+                refPtr<labelListList> tMap(new labelListList(size()));
+                return tMap;
+            }
+
+            //- Return implicit master
+            virtual bool masterImplicit() const
+            {
+                NotImplemented;
+                return false;
+            }
+
+            //- Return neighbour region name
+            virtual word neighbRegionID() const
+            {
+                return word("none");
+            }
+
+
         //- The offset where this patch starts in the boundary face list
         //  The value is the same as  patch.start() - mesh.nInternalFaces()
         label offset() const;
@@ -364,7 +417,7 @@ public:
 
 
         //- Write the polyPatch data as a dictionary
-        virtual void write(Ostream&) const;
+        virtual void write(Ostream& os) const;
 
 
         // Geometric data; point list required
diff --git a/src/TurbulenceModels/compressible/Make/options b/src/TurbulenceModels/compressible/Make/options
index 84a090e9214bbaf069cc15a32467816cf0b9c134..d7b28de2521800cbbd412eee7286bf31bf5f0ba0 100644
--- a/src/TurbulenceModels/compressible/Make/options
+++ b/src/TurbulenceModels/compressible/Make/options
@@ -2,6 +2,7 @@ EXE_INC = \
     -I../turbulenceModels/lnInclude \
     -I$(LIB_SRC)/finiteVolume/lnInclude \
     -I$(LIB_SRC)/meshTools/lnInclude \
+    -I$(LIB_SRC)/regionCoupled/lnInclude \
     -I$(LIB_SRC)/transportModels/compressible/lnInclude \
     -I$(LIB_SRC)/thermophysicalModels/basic/lnInclude \
     -I$(LIB_SRC)/thermophysicalModels/radiation/lnInclude \
diff --git a/src/TurbulenceModels/compressible/turbulentFluidThermoModels/derivedFvPatchFields/turbulentTemperatureCoupledBaffleMixed/turbulentTemperatureCoupledBaffleMixedFvPatchScalarField.C b/src/TurbulenceModels/compressible/turbulentFluidThermoModels/derivedFvPatchFields/turbulentTemperatureCoupledBaffleMixed/turbulentTemperatureCoupledBaffleMixedFvPatchScalarField.C
index 259903f2193dcd59b64a074058b67631c0599257..94b977d6039c89b16d62a846166a93eebab4f05b 100644
--- a/src/TurbulenceModels/compressible/turbulentFluidThermoModels/derivedFvPatchFields/turbulentTemperatureCoupledBaffleMixed/turbulentTemperatureCoupledBaffleMixedFvPatchScalarField.C
+++ b/src/TurbulenceModels/compressible/turbulentFluidThermoModels/derivedFvPatchFields/turbulentTemperatureCoupledBaffleMixed/turbulentTemperatureCoupledBaffleMixedFvPatchScalarField.C
@@ -118,6 +118,23 @@ turbulentTemperatureCoupledBaffleMixedFvPatchScalarField
     kappaLayers_(0),
     contactRes_(0.0)
 {
+    if (!isA<mappedPatchBase>(this->patch().patch()))
+    {
+        FatalErrorInFunction
+            << "' not type '" << mappedPatchBase::typeName << "'"
+            << "\n    for patch " << p.name()
+            << " of field " << internalField().name()
+            << " in file " << internalField().objectPath()
+            << exit(FatalError);
+    }
+
+    WarningInFunction
+        << "This BC has been superseded by "
+        << "compressible::turbulentTemperatureRadCoupledMixed "
+        << "which has more functionalities and it can handle "
+        << "the assemble coupled option for energy. "
+        << endl;
+
     if (dict.readIfPresent("thicknessLayers", thicknessLayers_))
     {
         dict.readEntry("kappaLayers", kappaLayers_);
@@ -349,6 +366,53 @@ void turbulentTemperatureCoupledBaffleMixedFvPatchScalarField::updateCoeffs()
 }
 
 
+void turbulentTemperatureCoupledBaffleMixedFvPatchScalarField::manipulateMatrix
+(
+    fvMatrix<scalar>& m,
+    const label iMatrix,
+    const direction cmpt
+)
+{
+    FatalErrorInFunction
+        << "This BC does not support energy coupling "
+        << "Use compressible::turbulentTemperatureRadCoupledMixed "
+        << "which has more functionalities and it can handle "
+        << "the assemble coupled option for energy. "
+        << abort(FatalError);
+}
+
+
+tmp<Field<scalar>>
+turbulentTemperatureCoupledBaffleMixedFvPatchScalarField::coeffs
+(
+    fvMatrix<scalar>& matrix,
+    const Field<scalar>& coeffs,
+    const label mat
+) const
+{
+    FatalErrorInFunction
+        << "This BC does not support energy coupling "
+        << "Use compressible::turbulentTemperatureRadCoupledMixed "
+        << "which has more functionalities and it can handle "
+        << "the assemble coupled option for energy. "
+        << abort(FatalError);
+    /*
+    const label index(this->patch().index());
+
+    const label nSubFaces(matrix.lduMesh().cellBoundMap()[mat][index].size());
+
+    Field<scalar> mapCoeffs(nSubFaces, Zero);
+
+    label subFaceI = 0;
+    forAll(*this, faceI)
+    {
+
+    }
+    */
+    return tmp<Field<scalar>>(new Field<scalar>());
+}
+
+
 void turbulentTemperatureCoupledBaffleMixedFvPatchScalarField::write
 (
     Ostream& os
diff --git a/src/TurbulenceModels/compressible/turbulentFluidThermoModels/derivedFvPatchFields/turbulentTemperatureCoupledBaffleMixed/turbulentTemperatureCoupledBaffleMixedFvPatchScalarField.H b/src/TurbulenceModels/compressible/turbulentFluidThermoModels/derivedFvPatchFields/turbulentTemperatureCoupledBaffleMixed/turbulentTemperatureCoupledBaffleMixedFvPatchScalarField.H
index 358066580ce619099578cfbf1da8bfedaaac5031..4c419b680e04431f3508765cfc0ab52585ef8dec 100644
--- a/src/TurbulenceModels/compressible/turbulentFluidThermoModels/derivedFvPatchFields/turbulentTemperatureCoupledBaffleMixed/turbulentTemperatureCoupledBaffleMixedFvPatchScalarField.H
+++ b/src/TurbulenceModels/compressible/turbulentFluidThermoModels/derivedFvPatchFields/turbulentTemperatureCoupledBaffleMixed/turbulentTemperatureCoupledBaffleMixedFvPatchScalarField.H
@@ -117,6 +117,17 @@ class turbulentTemperatureCoupledBaffleMixedFvPatchScalarField
         scalar contactRes_;
 
 
+    // Private member functions
+
+        //- Calculate coefficients for assembly matrix
+        tmp<Field<scalar>> coeffs
+        (
+            fvMatrix<scalar>& matrix,
+            const Field<scalar>&,
+            const label
+        ) const;
+
+
 public:
 
     //- Runtime type information
@@ -193,13 +204,22 @@ public:
         }
 
 
-    // Member functions
+    // Member Functions
 
         //- Update the coefficients associated with the patch field
         virtual void updateCoeffs();
 
+        //- Manipulate matrix
+        virtual void manipulateMatrix
+        (
+            fvMatrix<scalar>& m,
+            const label iMatrix,
+            const direction cmpt
+        );
+
+
         //- Write
-        virtual void write(Ostream&) const;
+        virtual void write(Ostream& os) const;
 };
 
 
diff --git a/src/TurbulenceModels/compressible/turbulentFluidThermoModels/derivedFvPatchFields/turbulentTemperatureRadCoupledMixed/turbulentTemperatureRadCoupledMixedFvPatchScalarField.C b/src/TurbulenceModels/compressible/turbulentFluidThermoModels/derivedFvPatchFields/turbulentTemperatureRadCoupledMixed/turbulentTemperatureRadCoupledMixedFvPatchScalarField.C
index 9648d5f7985c9894343be589b3c1ca1d5bf278a1..81722295df1768c06f48b2bbd55cfb45eaff5843 100644
--- a/src/TurbulenceModels/compressible/turbulentFluidThermoModels/derivedFvPatchFields/turbulentTemperatureRadCoupledMixed/turbulentTemperatureRadCoupledMixedFvPatchScalarField.C
+++ b/src/TurbulenceModels/compressible/turbulentFluidThermoModels/derivedFvPatchFields/turbulentTemperatureRadCoupledMixed/turbulentTemperatureRadCoupledMixedFvPatchScalarField.C
@@ -69,6 +69,7 @@ turbulentTemperatureRadCoupledMixedFvPatchScalarField
     this->refValue() = 0.0;
     this->refGrad() = 0.0;
     this->valueFraction() = 1.0;
+    this->source() = 0.0;
 }
 
 
@@ -152,6 +153,19 @@ turbulentTemperatureRadCoupledMixedFvPatchScalarField
         refGrad() = 0.0;
         valueFraction() = 1.0;
     }
+
+    if (dict.found("useImplicit"))
+    {
+        useImplicit() = dict.get<Switch>("useImplicit");
+    }
+    if (dict.found("source"))
+    {
+        source() = scalarField("source", dict, p.size());
+    }
+    else
+    {
+        source() = 0.0;
+    }
 }
 
 
@@ -320,6 +334,19 @@ void turbulentTemperatureRadCoupledMixedFvPatchScalarField::updateCoeffs()
         refGrad() = (qr + qrNbr)/kappa(Tp);
     }
 
+    source() = Zero;
+
+    // If useImplicit is true we need the source term associated with this BC
+    if (this->useImplicit())
+    {
+        source() =
+            alphaSfDelta()*
+            (
+                valueFraction()*deltaH()
+              + (qr + qrNbr)/beta()
+            );
+    }
+
     mixedFvPatchScalarField::updateCoeffs();
 
     if (debug)
@@ -345,6 +372,138 @@ void turbulentTemperatureRadCoupledMixedFvPatchScalarField::updateCoeffs()
 }
 
 
+void turbulentTemperatureRadCoupledMixedFvPatchScalarField::manipulateMatrix
+(
+    fvMatrix<scalar>& m,
+    const label iMatrix,
+    const direction cmpt
+)
+{
+    FatalErrorInFunction
+        << "This T BC does not support energy coupling "
+        << "It is implemented on he field "
+        << abort(FatalError);
+}
+
+
+tmp<Field<scalar>> turbulentTemperatureRadCoupledMixedFvPatchScalarField::coeffs
+(
+    fvMatrix<scalar>& matrix,
+    const Field<scalar>& coeffs,
+    const label mat
+) const
+{
+    FatalErrorInFunction
+        << "This BC does not support energy coupling "
+        << "Use compressible::turbulentTemperatureRadCoupledMixed "
+        << "which has more functionalities and it can handle "
+        << "the assemble coupled option for energy. "
+        << abort(FatalError);
+
+    return tmp<Field<scalar>>(new Field<scalar>());
+}
+
+
+tmp<scalarField>
+turbulentTemperatureRadCoupledMixedFvPatchScalarField::alphaSfDelta() const
+{
+    return (alpha(*this)*patch().deltaCoeffs()*patch().magSf());
+}
+
+
+tmp<scalarField> turbulentTemperatureRadCoupledMixedFvPatchScalarField::
+beta() const
+{
+    const mappedPatchBase& mpp =
+        refCast<const mappedPatchBase>(patch().patch());
+
+    const label samplePatchi = mpp.samplePolyPatch().index();
+    const polyMesh& nbrMesh = mpp.sampleMesh();
+
+    const fvPatch& nbrPatch =
+        refCast<const fvMesh>(nbrMesh).boundary()[samplePatchi];
+
+    const turbulentTemperatureRadCoupledMixedFvPatchScalarField&
+        nbrField = refCast
+            <const turbulentTemperatureRadCoupledMixedFvPatchScalarField>
+            (
+                nbrPatch.lookupPatchField<volScalarField, scalar>(TnbrName_)
+            );
+
+    // Swap to obtain full local values of neighbour internal field
+    scalarField TcNbr(nbrField.patchInternalField());
+    mpp.distribute(TcNbr);
+
+    scalarField alphaDeltaNbr
+    (
+        nbrField.alpha(TcNbr)*nbrPatch.deltaCoeffs()
+    );
+    mpp.distribute(alphaDeltaNbr);
+
+    scalarField alphaDelta
+    (
+         alpha(*this)*patch().deltaCoeffs()
+    );
+
+    return (alphaDeltaNbr + alphaDelta);
+}
+
+
+tmp<scalarField> turbulentTemperatureRadCoupledMixedFvPatchScalarField::
+deltaH() const
+{
+
+    const mappedPatchBase& mpp =
+        refCast<const mappedPatchBase>(patch().patch());
+
+    const polyMesh& nbrMesh = mpp.sampleMesh();
+
+    const basicThermo* nbrThermo =
+        nbrMesh.cfindObject<basicThermo>(basicThermo::dictName);
+
+    const polyMesh& mesh = patch().boundaryMesh().mesh();
+
+    const basicThermo* localThermo =
+        mesh.cfindObject<basicThermo>(basicThermo::dictName);
+
+
+    if (nbrThermo && localThermo)
+    {
+        const label patchi = patch().index();
+        const scalarField& pp = localThermo->p().boundaryField()[patchi];
+        const scalarField& Tp = *this;
+
+        const mappedPatchBase& mpp =
+            refCast<const mappedPatchBase>(patch().patch());
+
+        const label patchiNrb = mpp.samplePolyPatch().index();
+
+        const scalarField& ppNbr = nbrThermo->p().boundaryField()[patchiNrb];
+        //const scalarField& TpNbr = nbrThermo->T().boundaryField()[patchiNrb];
+
+        // Use this Tp to evaluate he jump as this is updated while doing
+        // updateCoeffs on boundary fields which set T values on patches
+        // then non consistent Tp and Tpnbr could be used from different
+        // updated values (specially when T changes drastically between time
+        // steps/
+        return
+        (
+          -  localThermo->he(pp, Tp, patchi)
+          +  nbrThermo->he(ppNbr, Tp, patchiNrb)
+        );
+    }
+    else
+    {
+        FatalErrorInFunction
+            << "Can't find thermos on mapped patch "
+            << " method, but thermo package not available"
+            << exit(FatalError);
+    }
+
+    return tmp<scalarField>::New(patch().size(), Zero);
+}
+
+
 void turbulentTemperatureRadCoupledMixedFvPatchScalarField::write
 (
     Ostream& os
diff --git a/src/TurbulenceModels/compressible/turbulentFluidThermoModels/derivedFvPatchFields/turbulentTemperatureRadCoupledMixed/turbulentTemperatureRadCoupledMixedFvPatchScalarField.H b/src/TurbulenceModels/compressible/turbulentFluidThermoModels/derivedFvPatchFields/turbulentTemperatureRadCoupledMixed/turbulentTemperatureRadCoupledMixedFvPatchScalarField.H
index 304bff518665061a8b4da907bcf4b64f6e31124d..31b28e368048f6cb7a29941d80d9c48474dff34c 100644
--- a/src/TurbulenceModels/compressible/turbulentFluidThermoModels/derivedFvPatchFields/turbulentTemperatureRadCoupledMixed/turbulentTemperatureRadCoupledMixedFvPatchScalarField.H
+++ b/src/TurbulenceModels/compressible/turbulentFluidThermoModels/derivedFvPatchFields/turbulentTemperatureRadCoupledMixed/turbulentTemperatureRadCoupledMixedFvPatchScalarField.H
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2017 OpenFOAM Foundation
-    Copyright (C) 2017 OpenCFD Ltd
+    Copyright (C) 2017-2019 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -100,12 +100,13 @@ class turbulentTemperatureRadCoupledMixedFvPatchScalarField
     public mixedFvPatchScalarField,
     public temperatureCoupledBase
 {
-    // Private data
+
+    // Private Data
 
         //- Name of field on the neighbour region
         const word TnbrName_;
 
-         //- Name of the radiative heat flux in the neighbour region
+        //- Name of the radiative heat flux in the neighbour region
         const word qrNbrName_;
 
         //- Name of the radiative heat flux in local region
@@ -124,6 +125,27 @@ class turbulentTemperatureRadCoupledMixedFvPatchScalarField
         Switch thermalInertia_;
 
 
+     // Private Functions
+
+            //- Return local alphaSfDelta
+            tmp<scalarField> alphaSfDelta() const;
+
+            //- Return delta enthalpy between regions
+            tmp<scalarField> deltaH() const;
+
+            //- Return the sum of deltaCoeff*alpha from nbr and local
+            tmp<scalarField> beta() const;
+
+
+            //- Calculate coefficients for assembly matrix
+            tmp<Field<scalar>> coeffs
+            (
+                fvMatrix<scalar>& matrix,
+                const Field<scalar>&,
+                const label
+            ) const;
+
+
 public:
 
     //- Runtime type information
@@ -195,13 +217,22 @@ public:
         }
 
 
-    // Member functions
+    // Member Functions
 
         //- Update the coefficients associated with the patch field
         virtual void updateCoeffs();
 
+        //- Manipulate matrix
+        virtual void manipulateMatrix
+        (
+            fvMatrix<scalar>& m,
+            const label iMatrix,
+            const direction cmpt
+        );
+
+
         //- Write
-        virtual void write(Ostream&) const;
+        virtual void write(Ostream& os) const;
 };
 
 
diff --git a/src/TurbulenceModels/turbulenceModels/derivedFvPatchFields/porousBafflePressure/porousBafflePressureFvPatchField.C b/src/TurbulenceModels/turbulenceModels/derivedFvPatchFields/porousBafflePressure/porousBafflePressureFvPatchField.C
index 4a84834687dda1d0cd8f6f94b95b310f2e4e739a..f1c573f4712494eae9a1d06bba5a3b8b202b3045 100644
--- a/src/TurbulenceModels/turbulenceModels/derivedFvPatchFields/porousBafflePressure/porousBafflePressureFvPatchField.C
+++ b/src/TurbulenceModels/turbulenceModels/derivedFvPatchFields/porousBafflePressure/porousBafflePressureFvPatchField.C
@@ -130,8 +130,7 @@ void Foam::porousBafflePressureFvPatchField::updateCoeffs()
         return;
     }
 
-    const surfaceScalarField& phi =
-            db().lookupObject<surfaceScalarField>(phiName_);
+    const auto& phi = db().lookupObject<surfaceScalarField>(phiName_);
 
     const fvsPatchField<scalar>& phip =
         patch().patchField<surfaceScalarField, scalar>(phi);
diff --git a/src/finiteArea/faMesh/faPatches/constraint/cyclic/cyclicFaPatch.C b/src/finiteArea/faMesh/faPatches/constraint/cyclic/cyclicFaPatch.C
index b4c3177da25bd84afe3b206f6c32fbb81e9924d8..0bee133c3000428a83b5f6538de8ed3391c5a76a 100644
--- a/src/finiteArea/faMesh/faPatches/constraint/cyclic/cyclicFaPatch.C
+++ b/src/finiteArea/faMesh/faPatches/constraint/cyclic/cyclicFaPatch.C
@@ -6,6 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2016-2017 Wikki Ltd
+    Copyright (C) 2019 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -48,6 +49,7 @@ void Foam::cyclicFaPatch::calcTransforms()
 {
     if (size() > 0)
     {
+        // const label sizeby2 = this->size()/2;
         pointField half0Ctrs(size()/2);
         pointField half1Ctrs(size()/2);
         for (label i=0; i<size()/2; ++i)
@@ -153,7 +155,7 @@ void Foam::cyclicFaPatch::makeWeights(scalarField& w) const
     const scalarField& magL = magEdgeLengths();
 
     const scalarField deltas(edgeNormals() & faPatch::delta());
-    label sizeby2 = deltas.size()/2;
+    const label sizeby2 = deltas.size()/2;
 
     scalar maxMatchError = 0;
     label errorEdge = -1;
@@ -206,7 +208,7 @@ void Foam::cyclicFaPatch::makeWeights(scalarField& w) const
 void Foam::cyclicFaPatch::makeDeltaCoeffs(scalarField& dc) const
 {
     const scalarField deltas(edgeNormals() & faPatch::delta());
-    label sizeby2 = deltas.size()/2;
+    const label sizeby2 = deltas.size()/2;
 
     for (label edgei = 0; edgei < sizeby2; ++edgei)
     {
@@ -248,10 +250,10 @@ void Foam::cyclicFaPatch::movePoints(const pointField& p)
 Foam::tmp<Foam::vectorField> Foam::cyclicFaPatch::delta() const
 {
     const vectorField patchD(faPatch::delta());
-    label sizeby2 = patchD.size()/2;
+    const label sizeby2 = patchD.size()/2;
 
-    tmp<vectorField> tpdv(new vectorField(patchD.size()));
-    vectorField& pdv = tpdv.ref();
+    auto tpdv = tmp<vectorField>::New(patchD.size());
+    auto& pdv = tpdv.ref();
 
     // Do the transformation if necessary
     if (parallel())
@@ -290,16 +292,26 @@ Foam::tmp<Foam::labelField> Foam::cyclicFaPatch::interfaceInternalField
 }
 
 
+Foam::tmp<Foam::labelField> Foam::cyclicFaPatch::interfaceInternalField
+(
+    const labelUList& internalData,
+    const labelUList& edgeFaces
+) const
+{
+    return patchInternalField(internalData, edgeFaces);
+}
+
+
 Foam::tmp<Foam::labelField> Foam::cyclicFaPatch::transfer
 (
-    const Pstream::commsTypes,
+    const Pstream::commsTypes commsType,
     const labelUList& interfaceData
 ) const
 {
-    tmp<labelField> tpnf(new labelField(this->size()));
-    labelField& pnf = tpnf.ref();
+    auto tpnf = tmp<labelField>::New(this->size());
+    auto& pnf = tpnf.ref();
 
-    label sizeby2 = this->size()/2;
+    const label sizeby2 = this->size()/2;
 
     for (label edgei=0; edgei<sizeby2; ++edgei)
     {
@@ -317,12 +329,21 @@ Foam::tmp<Foam::labelField> Foam::cyclicFaPatch::internalFieldTransfer
     const labelUList& iF
 ) const
 {
-    const labelUList& edgeCells = this->faceCells();
+    return internalFieldTransfer(commsType, iF, this->faceCells());
+}
+
 
-    tmp<labelField> tpnf(new labelField(this->size()));
-    labelField& pnf = tpnf.ref();
+Foam::tmp<Foam::labelField> Foam::cyclicFaPatch::internalFieldTransfer
+(
+    const Pstream::commsTypes commsType,
+    const labelUList& iF,
+    const labelUList& edgeCells
+) const
+{
+    auto tpnf = tmp<labelField>::New(this->size());
+    auto& pnf = tpnf.ref();
 
-    label sizeby2 = this->size()/2;
+    const label sizeby2 = this->size()/2;
 
     for (label edgei=0; edgei<sizeby2; ++edgei)
     {
diff --git a/src/finiteArea/faMesh/faPatches/constraint/cyclic/cyclicFaPatch.H b/src/finiteArea/faMesh/faPatches/constraint/cyclic/cyclicFaPatch.H
index 56e7d555a9dec27e95d4355db3bafe3f88266db1..bb28ab5b9570df7de0749a565f00f17ecab941e7 100644
--- a/src/finiteArea/faMesh/faPatches/constraint/cyclic/cyclicFaPatch.H
+++ b/src/finiteArea/faMesh/faPatches/constraint/cyclic/cyclicFaPatch.H
@@ -167,12 +167,22 @@ public:
         // Interface transfer functions
 
             //- Return the values of the given internal data adjacent to
-            //  the interface as a field
+            //- the interface as a field
             virtual tmp<labelField> interfaceInternalField
             (
                 const labelUList& internalData
             ) const;
 
+
+            //- Return the values of the given internal data adjacent to
+            //- the interface as a field using edgeFace mapping
+            virtual tmp<labelField> interfaceInternalField
+            (
+                const labelUList& internalData,
+                const labelUList& edgeFaces
+            ) const;
+
+
             //- Transfer and return neighbour field
             virtual tmp<labelField> transfer
             (
@@ -186,6 +196,15 @@ public:
                 const Pstream::commsTypes commsType,
                 const labelUList& internalData
             ) const;
+
+
+            //- Return neighbour field using edgeCells mapping
+            virtual tmp<labelField> internalFieldTransfer
+            (
+                const Pstream::commsTypes commsType,
+                const labelUList& internalData,
+                const labelUList& edgeCells
+            ) const;
 };
 
 
diff --git a/src/finiteArea/faMesh/faPatches/constraint/processor/processorFaPatch.C b/src/finiteArea/faMesh/faPatches/constraint/processor/processorFaPatch.C
index b05ae98dee06cd1a817dc44e32896f1c65676c16..d257e4a199c0ac828b46ac000e488b48db834b5f 100644
--- a/src/finiteArea/faMesh/faPatches/constraint/processor/processorFaPatch.C
+++ b/src/finiteArea/faMesh/faPatches/constraint/processor/processorFaPatch.C
@@ -6,6 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2016-2017 Wikki Ltd
+    Copyright (C) 2019 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -77,7 +78,6 @@ void Foam::processorFaPatch::makeNonGlobalPatchPoints() const
     (
         !Pstream::parRun()
      || !boundaryMesh().mesh()().globalData().nGlobalPoints()
-//     || !boundaryMesh().mesh().globalData().nGlobalPoints()
     )
     {
         nonGlobalPatchPointsPtr_ = new labelList(nPoints());
@@ -464,6 +464,16 @@ Foam::tmp<Foam::labelField> Foam::processorFaPatch::interfaceInternalField
 }
 
 
+Foam::tmp<Foam::labelField> Foam::processorFaPatch::interfaceInternalField
+(
+    const labelUList& internalData,
+    const labelUList& edgeFaces
+) const
+{
+    return patchInternalField(internalData, edgeFaces);
+}
+
+
 void Foam::processorFaPatch::initTransfer
 (
     const Pstream::commsTypes commsType,
@@ -504,6 +514,17 @@ Foam::tmp<Foam::labelField> Foam::processorFaPatch::internalFieldTransfer
 }
 
 
+Foam::tmp<Foam::labelField> Foam::processorFaPatch::internalFieldTransfer
+(
+    const Pstream::commsTypes commsType,
+    const labelUList&,
+    const labelUList&
+) const
+{
+    return receive<label>(commsType, this->size());
+}
+
+
 void Foam::processorFaPatch::write(Ostream& os) const
 {
     faPatch::write(os);
diff --git a/src/finiteArea/faMesh/faPatches/constraint/processor/processorFaPatch.H b/src/finiteArea/faMesh/faPatches/constraint/processor/processorFaPatch.H
index c48962843c6bdcc1b5136f0cc0640ff4c4af84f6..5924eaae01782c767526d3e5c6df60726e5dec36 100644
--- a/src/finiteArea/faMesh/faPatches/constraint/processor/processorFaPatch.H
+++ b/src/finiteArea/faMesh/faPatches/constraint/processor/processorFaPatch.H
@@ -6,6 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2016-2017 Wikki Ltd
+    Copyright (C) 2019 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -264,12 +265,20 @@ public:
         // Interface transfer functions
 
             //- Return the values of the given internal data adjacent to
-            //  the interface as a field
+            //- the interface as a field
             virtual tmp<labelField> interfaceInternalField
             (
                 const labelUList& internalData
             ) const;
 
+            //- Return the values of the given internal data adjacent to
+            //- the interface as a field using edgeFaces
+            virtual tmp<labelField> interfaceInternalField
+            (
+                const labelUList& internalData,
+                const labelUList& edgeFaces
+            ) const;
+
             //- Initialise interface data transfer
             virtual void initTransfer
             (
@@ -298,8 +307,16 @@ public:
                 const labelUList& internalData
             ) const;
 
+            //- Return neighbour field using mapping
+            virtual tmp<labelField> internalFieldTransfer
+            (
+                const Pstream::commsTypes commsType,
+                const labelUList& internalData,
+                const labelUList& edgeCells
+            ) const;
+
             //- Write the patch data as a dictionary
-            virtual void write(Ostream&) const;
+            virtual void write(Ostream& os) const;
 };
 
 
diff --git a/src/finiteArea/faMesh/faPatches/faPatch/faPatch.H b/src/finiteArea/faMesh/faPatches/faPatch/faPatch.H
index 98bb9efe764d2decfdf002567567c79a44750ebe..61333db78132109f48a1232d7969f6e1182b91ab 100644
--- a/src/finiteArea/faMesh/faPatches/faPatch/faPatch.H
+++ b/src/finiteArea/faMesh/faPatches/faPatch/faPatch.H
@@ -357,6 +357,15 @@ public:
             template<class Type>
             tmp<Field<Type>> patchInternalField(const UList<Type>&) const;
 
+            //- Return given internal field next to patch as patch field
+            //  providing addressing
+            template<class Type>
+            tmp<Foam::Field<Type>> patchInternalField
+            (
+                const UList<Type>& f,
+                const labelUList& edgeFaces
+            ) const;
+
             //- Return the corresponding patchField of the named field
             template<class GeometricField, class Type>
             const typename GeometricField::Patch& patchField
diff --git a/src/finiteArea/faMesh/faPatches/faPatch/faPatchTemplates.C b/src/finiteArea/faMesh/faPatches/faPatch/faPatchTemplates.C
index 68371ef43c4ac7f134e6de0fbe38784547d05ea1..72d36b50f102436c2fb92525674a6435621e3ec4 100644
--- a/src/finiteArea/faMesh/faPatches/faPatch/faPatchTemplates.C
+++ b/src/finiteArea/faMesh/faPatches/faPatch/faPatchTemplates.C
@@ -6,6 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2016-2017 Wikki Ltd
+    Copyright (C) 2019 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -35,10 +36,19 @@ Foam::tmp<Foam::Field<Type>> Foam::faPatch::patchInternalField
     const UList<Type>& f
 ) const
 {
-    tmp<Field<Type>> tpif (new Field<Type>(size()));
-    Field<Type>& pif = tpif.ref();
+    return patchInternalField(f, this->edgeFaces());
+}
+
 
-    const labelUList& edgeFaces = this->edgeFaces();
+template<class Type>
+Foam::tmp<Foam::Field<Type>> Foam::faPatch::patchInternalField
+(
+    const UList<Type>& f,
+    const labelUList& edgeFaces
+) const
+{
+    auto tpif = tmp<Field<Type>>::New(size());
+    auto& pif = tpif.ref();
 
     forAll(pif, facei)
     {
diff --git a/src/finiteArea/fields/faPatchFields/basic/coupled/coupledFaPatchField.H b/src/finiteArea/fields/faPatchFields/basic/coupled/coupledFaPatchField.H
index 66bcf9929a628a0824d97402475d642a3f433ac6..8f6a2db48ecd1e0afc5354c61ef7d532bc9cc8ce 100644
--- a/src/finiteArea/fields/faPatchFields/basic/coupled/coupledFaPatchField.H
+++ b/src/finiteArea/fields/faPatchFields/basic/coupled/coupledFaPatchField.H
@@ -193,6 +193,8 @@ public:
             (
                 solveScalarField& result,
                 const bool add,
+                const lduAddressing& lduAddr,
+                const label patchId,
                 const solveScalarField& psiInternal,
                 const scalarField& coeffs,
                 const direction,
@@ -204,6 +206,8 @@ public:
             (
                 Field<Type>& result,
                 const bool add,
+                const lduAddressing& lduAddr,
+                const label patchId,
                 const Field<Type>&,
                 const scalarField& coeffs,
                 const Pstream::commsTypes commsType
diff --git a/src/finiteArea/fields/faPatchFields/constraint/cyclic/cyclicFaPatchField.C b/src/finiteArea/fields/faPatchFields/constraint/cyclic/cyclicFaPatchField.C
index 4323ce3e30d19128c6787f4cc2864b13cd25d16b..9e034b59959eb98a08c820e1c8a012551bba6bdf 100644
--- a/src/finiteArea/fields/faPatchFields/constraint/cyclic/cyclicFaPatchField.C
+++ b/src/finiteArea/fields/faPatchFields/constraint/cyclic/cyclicFaPatchField.C
@@ -129,7 +129,7 @@ Foam::cyclicFaPatchField<Type>::patchNeighbourField() const
     tmp<Field<Type>> tpnf(new Field<Type>(this->size()));
     Field<Type>& pnf = tpnf.ref();
 
-    label sizeby2 = this->size()/2;
+    const label sizeby2 = this->size()/2;
 
     if (doTransform())
     {
@@ -164,6 +164,8 @@ void Foam::cyclicFaPatchField<Type>::updateInterfaceMatrix
 (
     solveScalarField& result,
     const bool add,
+    const lduAddressing& lduAddr,
+    const label patchId,
     const solveScalarField& psiInternal,
     const scalarField& coeffs,
     const direction cmpt,
@@ -172,7 +174,7 @@ void Foam::cyclicFaPatchField<Type>::updateInterfaceMatrix
 {
     solveScalarField pnf(this->size());
 
-    label sizeby2 = this->size()/2;
+    const label sizeby2 = this->size()/2;
     const labelUList& faceCells = cyclicPatch_.faceCells();
 
     for (label facei = 0; facei < sizeby2; ++facei)
@@ -207,6 +209,8 @@ void Foam::cyclicFaPatchField<Type>::updateInterfaceMatrix
 (
     Field<Type>& result,
     const bool add,
+    const lduAddressing& lduAddr,
+    const label patchId,
     const Field<Type>& psiInternal,
     const scalarField& coeffs,
     const Pstream::commsTypes commsType
@@ -214,7 +218,7 @@ void Foam::cyclicFaPatchField<Type>::updateInterfaceMatrix
 {
     Field<Type> pnf(this->size());
 
-    label sizeby2 = this->size()/2;
+    const label sizeby2 = this->size()/2;
     const labelUList& faceCells = cyclicPatch_.faceCells();
 
     for (label facei = 0; facei < sizeby2; ++facei)
diff --git a/src/finiteArea/fields/faPatchFields/constraint/cyclic/cyclicFaPatchField.H b/src/finiteArea/fields/faPatchFields/constraint/cyclic/cyclicFaPatchField.H
index 1599ef56f2ac9a79db23a38b0fa26b9e11aaa228..63da81ed3864314bb2569e812463408f2d7a3ec8 100644
--- a/src/finiteArea/fields/faPatchFields/constraint/cyclic/cyclicFaPatchField.H
+++ b/src/finiteArea/fields/faPatchFields/constraint/cyclic/cyclicFaPatchField.H
@@ -179,6 +179,8 @@ public:
             (
                 solveScalarField& result,
                 const bool add,
+                const lduAddressing& lduAddr,
+                const label patchId,
                 const solveScalarField& psiInternal,
                 const scalarField& coeffs,
                 const direction cmpt,
@@ -190,6 +192,8 @@ public:
             (
                 Field<Type>& result,
                 const bool add,
+                const lduAddressing& lduAddr,
+                const label patchId,
                 const Field<Type>&,
                 const scalarField& coeffs,
                 const Pstream::commsTypes commsType
diff --git a/src/finiteArea/fields/faPatchFields/constraint/processor/processorFaPatchField.C b/src/finiteArea/fields/faPatchFields/constraint/processor/processorFaPatchField.C
index 05bd56c8bee8edcc9e9bafca1a54a397931b6e40..1f8ed1ee8f02dc3746ab10cc035ff38d6d111390 100644
--- a/src/finiteArea/fields/faPatchFields/constraint/processor/processorFaPatchField.C
+++ b/src/finiteArea/fields/faPatchFields/constraint/processor/processorFaPatchField.C
@@ -192,6 +192,8 @@ void Foam::processorFaPatchField<Type>::initInterfaceMatrixUpdate
 (
     solveScalarField& result,
     const bool add,
+    const lduAddressing& lduAddr,
+    const label patchId,
     const solveScalarField& psiInternal,
     const scalarField& coeffs,
     const direction,
@@ -211,6 +213,8 @@ void Foam::processorFaPatchField<Type>::updateInterfaceMatrix
 (
     solveScalarField& result,
     const bool add,
+    const lduAddressing& lduAddr,
+    const label patchId,
     const solveScalarField&,
     const scalarField& coeffs,
     const direction cmpt,
@@ -251,6 +255,8 @@ void Foam::processorFaPatchField<Type>::initInterfaceMatrixUpdate
 (
     Field<Type>& result,
     const bool add,
+    const lduAddressing& lduAddr,
+    const label patchId,
     const Field<Type>& psiInternal,
     const scalarField& coeffs,
     const Pstream::commsTypes commsType
@@ -269,6 +275,8 @@ void Foam::processorFaPatchField<Type>::updateInterfaceMatrix
 (
     Field<Type>& result,
     const bool add,
+    const lduAddressing& lduAddr,
+    const label patchId,
     const Field<Type>&,
     const scalarField& coeffs,
     const Pstream::commsTypes commsType
diff --git a/src/finiteArea/fields/faPatchFields/constraint/processor/processorFaPatchField.H b/src/finiteArea/fields/faPatchFields/constraint/processor/processorFaPatchField.H
index 734a705c730e976614d7815e78935da178c4ac32..dcd279dabf9a5a597aa8f67aa4fbd5f3db0aeec0 100644
--- a/src/finiteArea/fields/faPatchFields/constraint/processor/processorFaPatchField.H
+++ b/src/finiteArea/fields/faPatchFields/constraint/processor/processorFaPatchField.H
@@ -193,6 +193,8 @@ public:
             (
                 solveScalarField& result,
                 const bool add,
+                const lduAddressing& lduAddr,
+                const label patchId,
                 const solveScalarField& psiInternal,
                 const scalarField& coeffs,
                 const direction cmpt,
@@ -204,6 +206,8 @@ public:
             (
                 solveScalarField& result,
                 const bool add,
+                const lduAddressing& lduAddr,
+                const label patchId,
                 const solveScalarField& psiInternal,
                 const scalarField& coeffs,
                 const direction cmpt,
@@ -215,6 +219,8 @@ public:
             (
                 Field<Type>& result,
                 const bool add,
+                const lduAddressing& lduAddr,
+                const label patchId,
                 const Field<Type>&,
                 const scalarField& coeffs,
                 const Pstream::commsTypes commsType
@@ -225,6 +231,8 @@ public:
             (
                 Field<Type>& result,
                 const bool add,
+                const lduAddressing& lduAddr,
+                const label patchId,
                 const Field<Type>&,
                 const scalarField& coeffs,
                 const Pstream::commsTypes commsType
diff --git a/src/finiteArea/fields/faPatchFields/constraint/processor/processorFaPatchScalarField.C b/src/finiteArea/fields/faPatchFields/constraint/processor/processorFaPatchScalarField.C
index 73166245bd3f5ed5e7b671c93f5435709d4510e9..b06e2d7736566fe446483dfd7f198906468c8a0b 100644
--- a/src/finiteArea/fields/faPatchFields/constraint/processor/processorFaPatchScalarField.C
+++ b/src/finiteArea/fields/faPatchFields/constraint/processor/processorFaPatchScalarField.C
@@ -44,6 +44,8 @@ void Foam::processorFaPatchField<Foam::scalar>::initInterfaceMatrixUpdate
 (
     solveScalarField& result,
     const bool add,
+    const lduAddressing& lduAddr,
+    const label patchId,
     const solveScalarField& psiInternal,
     const scalarField& coeffs,
     const direction,
@@ -63,6 +65,8 @@ void Foam::processorFaPatchField<Foam::scalar>::updateInterfaceMatrix
 (
     solveScalarField& result,
     const bool add,
+    const lduAddressing& lduAddr,
+    const label patchId,
     const solveScalarField&,
     const scalarField& coeffs,
     const direction,
diff --git a/src/finiteArea/fields/faPatchFields/constraint/processor/processorFaPatchScalarField.H b/src/finiteArea/fields/faPatchFields/constraint/processor/processorFaPatchScalarField.H
index 017f09a026dec32843aefeb22954a17bee4580bf..a7227f5de2b215c2d174add38df60d1fbe2a5738 100644
--- a/src/finiteArea/fields/faPatchFields/constraint/processor/processorFaPatchScalarField.H
+++ b/src/finiteArea/fields/faPatchFields/constraint/processor/processorFaPatchScalarField.H
@@ -51,6 +51,8 @@ void processorFaPatchField<scalar>::initInterfaceMatrixUpdate
 (
     solveScalarField& result,
     const bool add,
+    const lduAddressing& lduAddr,
+    const label patchId,
     const solveScalarField&,
     const scalarField& coeffs,
     const direction,
@@ -63,6 +65,8 @@ void processorFaPatchField<scalar>::updateInterfaceMatrix
 (
     solveScalarField& result,
     const bool add,
+    const lduAddressing& lduAddr,
+    const label patchId,
     const solveScalarField&,
     const scalarField& coeffs,
     const direction,
diff --git a/src/finiteVolume/Make/files b/src/finiteVolume/Make/files
index ef849f6dff00d28cb8ca4d9ca51b4ba0a857f0c4..e0300c915241a01b3da3e105bf007550d57528a9 100644
--- a/src/finiteVolume/Make/files
+++ b/src/finiteVolume/Make/files
@@ -142,6 +142,7 @@ $(constraintFvPatchFields)/jumpCyclicAMI/jumpCyclicAMIFvPatchFields.C
 $(constraintFvPatchFields)/nonuniformTransformCyclic/nonuniformTransformCyclicFvPatchFields.C
 $(constraintFvPatchFields)/processor/processorFvPatchFields.C
 $(constraintFvPatchFields)/processorCyclic/processorCyclicFvPatchFields.C
+$(constraintFvPatchFields)/calculatedProcessor/calculatedProcessorFvPatchFields.C
 $(constraintFvPatchFields)/symmetryPlane/symmetryPlaneFvPatchFields.C
 $(constraintFvPatchFields)/symmetryPlane/symmetryPlaneFvPatchScalarField.C
 $(constraintFvPatchFields)/symmetry/symmetryFvPatchFields.C
@@ -516,4 +517,9 @@ $(fvOptions)/fvOptionIO.C
 $(fvOptions)/fvOptionList.C
 $(fvOptions)/fvOptions.C
 
+lduPrimitiveMeshAssembly/AssemblyFvPatches.C
+lduPrimitiveMeshAssembly/lduPrimitiveMeshAssembly.C
+lduPrimitiveMeshAssembly/assemblyFaceAreaPairGAMGAgglomeration/assemblyFaceAreaPairGAMGAgglomeration.C
+
+
 LIB = $(FOAM_LIBBIN)/libfiniteVolume
diff --git a/src/finiteVolume/Make/options b/src/finiteVolume/Make/options
index ea11ab0d45a46d24a226464a14238a684ff6278a..0927690c0d299170ea94a710f064f51c5cfdbcd5 100644
--- a/src/finiteVolume/Make/options
+++ b/src/finiteVolume/Make/options
@@ -9,3 +9,4 @@ LIB_LIBS = \
     -lfileFormats \
     -lsurfMesh \
     -lmeshTools
+
diff --git a/src/finiteVolume/fields/fvPatchFields/basic/coupled/coupledFvPatchField.H b/src/finiteVolume/fields/fvPatchFields/basic/coupled/coupledFvPatchField.H
index 234302ba031dcb1d5b1cc9df323429b2a09a788c..968768fb5f83ea242af965efc9a39f0c26acc3de 100644
--- a/src/finiteVolume/fields/fvPatchFields/basic/coupled/coupledFvPatchField.H
+++ b/src/finiteVolume/fields/fvPatchFields/basic/coupled/coupledFvPatchField.H
@@ -211,6 +211,8 @@ public:
             (
                 solveScalarField& result,
                 const bool add,
+                const lduAddressing& lduAddr,
+                const label patchId,
                 const solveScalarField& psiInternal,
                 const scalarField& coeffs,
                 const direction,
@@ -222,6 +224,8 @@ public:
             (
                 Field<Type>&,
                 const bool add,
+                const lduAddressing& lduAddr,
+                const label patchId,
                 const Field<Type>&,
                 const scalarField&,
                 const Pstream::commsTypes commsType
diff --git a/src/finiteVolume/fields/fvPatchFields/basic/mixed/mixedFvPatchField.C b/src/finiteVolume/fields/fvPatchFields/basic/mixed/mixedFvPatchField.C
index 96bdc60732c6c6541517a5944619e0cec55f56d4..a1ec7e3b996a1e0b3e7167263b22f2f6551953d6 100644
--- a/src/finiteVolume/fields/fvPatchFields/basic/mixed/mixedFvPatchField.C
+++ b/src/finiteVolume/fields/fvPatchFields/basic/mixed/mixedFvPatchField.C
@@ -39,7 +39,8 @@ Foam::mixedFvPatchField<Type>::mixedFvPatchField
     fvPatchField<Type>(p, iF),
     refValue_(p.size()),
     refGrad_(p.size()),
-    valueFraction_(p.size())
+    valueFraction_(p.size()),
+    source_(p.size(), Zero)
 {}
 
 
@@ -54,7 +55,8 @@ Foam::mixedFvPatchField<Type>::mixedFvPatchField
     fvPatchField<Type>(p, iF, dict, false),
     refValue_("refValue", dict, p.size()),
     refGrad_("refGradient", dict, p.size()),
-    valueFraction_("valueFraction", dict, p.size())
+    valueFraction_("valueFraction", dict, p.size()),
+    source_(p.size(), Zero)
 {
     // Could also check/clip fraction to 0-1 range
     evaluate();
@@ -73,7 +75,8 @@ Foam::mixedFvPatchField<Type>::mixedFvPatchField
     fvPatchField<Type>(ptf, p, iF, mapper),
     refValue_(ptf.refValue_, mapper),
     refGrad_(ptf.refGrad_, mapper),
-    valueFraction_(ptf.valueFraction_, mapper)
+    valueFraction_(ptf.valueFraction_, mapper),
+    source_(ptf.source_, mapper)
 {
     if (notNull(iF) && mapper.hasUnmapped())
     {
@@ -96,7 +99,8 @@ Foam::mixedFvPatchField<Type>::mixedFvPatchField
     fvPatchField<Type>(ptf),
     refValue_(ptf.refValue_),
     refGrad_(ptf.refGrad_),
-    valueFraction_(ptf.valueFraction_)
+    valueFraction_(ptf.valueFraction_),
+    source_(ptf.source_)
 {}
 
 
@@ -110,7 +114,8 @@ Foam::mixedFvPatchField<Type>::mixedFvPatchField
     fvPatchField<Type>(ptf, iF),
     refValue_(ptf.refValue_),
     refGrad_(ptf.refGrad_),
-    valueFraction_(ptf.valueFraction_)
+    valueFraction_(ptf.valueFraction_),
+    source_(ptf.source_)
 {}
 
 
@@ -126,6 +131,7 @@ void Foam::mixedFvPatchField<Type>::autoMap
     refValue_.autoMap(m);
     refGrad_.autoMap(m);
     valueFraction_.autoMap(m);
+    source_.autoMap(m);
 }
 
 
@@ -144,12 +150,14 @@ void Foam::mixedFvPatchField<Type>::rmap
     refValue_.rmap(mptf.refValue_, addr);
     refGrad_.rmap(mptf.refGrad_, addr);
     valueFraction_.rmap(mptf.valueFraction_, addr);
+    source_.rmap(mptf.source_, addr);
 }
 
 
 template<class Type>
 void Foam::mixedFvPatchField<Type>::evaluate(const Pstream::commsTypes)
 {
+
     if (!this->updated())
     {
         this->updateCoeffs();
@@ -158,9 +166,8 @@ void Foam::mixedFvPatchField<Type>::evaluate(const Pstream::commsTypes)
     Field<Type>::operator=
     (
         valueFraction_*refValue_
-      +
-        (1.0 - valueFraction_)*
-        (
+      + (1.0 - valueFraction_)
+       *(
             this->patchInternalField()
           + refGrad_/this->patch().deltaCoeffs()
         )
@@ -190,7 +197,6 @@ Foam::mixedFvPatchField<Type>::valueInternalCoeffs
 ) const
 {
     return Type(pTraits<Type>::one)*(1.0 - valueFraction_);
-
 }
 
 
@@ -202,8 +208,8 @@ Foam::mixedFvPatchField<Type>::valueBoundaryCoeffs
 ) const
 {
     return
-         valueFraction_*refValue_
-       + (1.0 - valueFraction_)*refGrad_/this->patch().deltaCoeffs();
+        valueFraction_*refValue_
+      + (1.0 - valueFraction_)*refGrad_/this->patch().deltaCoeffs();
 }
 
 
@@ -232,6 +238,7 @@ void Foam::mixedFvPatchField<Type>::write(Ostream& os) const
     refValue_.writeEntry("refValue", os);
     refGrad_.writeEntry("refGradient", os);
     valueFraction_.writeEntry("valueFraction", os);
+    source_.writeEntry("source", os);
     this->writeEntry("value", os);
 }
 
diff --git a/src/finiteVolume/fields/fvPatchFields/basic/mixed/mixedFvPatchField.H b/src/finiteVolume/fields/fvPatchFields/basic/mixed/mixedFvPatchField.H
index 9f1bcf08670484b19f2d73080d6ac91fd1284261..deec0f77d9538834d123b389aefb82d46385c1ee 100644
--- a/src/finiteVolume/fields/fvPatchFields/basic/mixed/mixedFvPatchField.H
+++ b/src/finiteVolume/fields/fvPatchFields/basic/mixed/mixedFvPatchField.H
@@ -100,6 +100,9 @@ class mixedFvPatchField
         //- Fraction (0-1) of value used for boundary condition
         scalarField valueFraction_;
 
+        //- Source field
+        Field<Type> source_;
+
 
 public:
 
@@ -219,6 +222,16 @@ public:
                 return valueFraction_;
             }
 
+            virtual Field<Type>& source()
+            {
+                return source_;
+            }
+
+            virtual const Field<Type>& source() const
+            {
+                return source_;
+            }
+
 
         // Mapping functions
 
diff --git a/src/overset/lduPrimitiveProcessorInterface/calculatedProcessorFvPatchField.C b/src/finiteVolume/fields/fvPatchFields/constraint/calculatedProcessor/calculatedProcessorFvPatchField.C
similarity index 93%
rename from src/overset/lduPrimitiveProcessorInterface/calculatedProcessorFvPatchField.C
rename to src/finiteVolume/fields/fvPatchFields/constraint/calculatedProcessor/calculatedProcessorFvPatchField.C
index 5d0b4f30c7cbc43fc55fc34a9420dc13034a4c7e..2713b4e8fb8c51c8218d25ef0587eb6fbe3fbf36 100644
--- a/src/overset/lduPrimitiveProcessorInterface/calculatedProcessorFvPatchField.C
+++ b/src/finiteVolume/fields/fvPatchFields/constraint/calculatedProcessor/calculatedProcessorFvPatchField.C
@@ -37,7 +37,6 @@ Foam::calculatedProcessorFvPatchField<Type>::calculatedProcessorFvPatchField
     const DimensionedField<Type, volMesh>& iF
 )
 :
-    //lduInterfaceField(interface),
     coupledFvPatchField<Type>(p, iF),
     procInterface_(refCast<const lduPrimitiveProcessorInterface>(interface)),
     sendBuf_(interface.faceCells().size()),
@@ -55,7 +54,6 @@ Foam::calculatedProcessorFvPatchField<Type>::calculatedProcessorFvPatchField
     const calculatedProcessorFvPatchField<Type>& ptf
 )
 :
-    //lduInterfaceField(ptf.procInterface_),
     coupledFvPatchField<Type>(ptf),
     procInterface_(ptf.procInterface_),
     sendBuf_(procInterface_.faceCells().size()),
@@ -75,7 +73,6 @@ Foam::calculatedProcessorFvPatchField<Type>::calculatedProcessorFvPatchField
     const DimensionedField<Type, volMesh>& iF
 )
 :
-    //lduInterfaceField(ptf.procInterface_),
     coupledFvPatchField<Type>(ptf, iF),
     procInterface_(ptf.procInterface_),
     sendBuf_(procInterface_.faceCells().size()),
@@ -98,9 +95,7 @@ bool Foam::calculatedProcessorFvPatchField<Type>::ready() const
      && this->outstandingSendRequest_ < Pstream::nRequests()
     )
     {
-        bool finished =
-            UPstream::finishedRequest(this->outstandingSendRequest_);
-        if (!finished)
+        if (!UPstream::finishedRequest(this->outstandingSendRequest_))
         {
             return false;
         }
@@ -113,9 +108,7 @@ bool Foam::calculatedProcessorFvPatchField<Type>::ready() const
      && this->outstandingRecvRequest_ < Pstream::nRequests()
     )
     {
-        bool finished =
-            UPstream::finishedRequest(this->outstandingRecvRequest_);
-        if (!finished)
+        if (!UPstream::finishedRequest(this->outstandingRecvRequest_))
         {
             return false;
         }
@@ -130,7 +123,7 @@ template<class Type>
 Foam::tmp<Foam::Field<Type>>
 Foam::calculatedProcessorFvPatchField<Type>::patchNeighbourField() const
 {
-    if (debug && !this->ready())
+    if (!this->ready())
     {
         FatalErrorInFunction
             << "On patch of size " << procInterface_.faceCells().size()
@@ -217,6 +210,8 @@ void Foam::calculatedProcessorFvPatchField<Type>::initInterfaceMatrixUpdate
 (
     solveScalarField& result,
     const bool add,
+    const lduAddressing& lduAddr,
+    const label patchId,
     const solveScalarField& psiInternal,
     const scalarField& coeffs,
     const direction cmpt,
@@ -224,14 +219,16 @@ void Foam::calculatedProcessorFvPatchField<Type>::initInterfaceMatrixUpdate
 ) const
 {
     // Bypass patchInternalField since uses fvPatch addressing
-    const labelList& fc = procInterface_.faceCells();
+
+    const labelList& fc = lduAddr.patchAddr(patchId);
+
     scalarSendBuf_.setSize(fc.size());
     forAll(fc, i)
     {
         scalarSendBuf_[i] = psiInternal[fc[i]];
     }
 
-    if (debug && !this->ready())
+    if (!this->ready())
     {
         FatalErrorInFunction
             << "On patch " //<< interface_.name()
@@ -240,8 +237,10 @@ void Foam::calculatedProcessorFvPatchField<Type>::initInterfaceMatrixUpdate
     }
 
 
+
     scalarReceiveBuf_.setSize(scalarSendBuf_.size());
     outstandingRecvRequest_ = UPstream::nRequests();
+
     UIPstream::read
     (
         Pstream::commsTypes::nonBlocking,
@@ -253,6 +252,7 @@ void Foam::calculatedProcessorFvPatchField<Type>::initInterfaceMatrixUpdate
     );
 
     outstandingSendRequest_ = UPstream::nRequests();
+
     UOPstream::write
     (
         Pstream::commsTypes::nonBlocking,
@@ -303,6 +303,8 @@ void Foam::calculatedProcessorFvPatchField<Type>::updateInterfaceMatrix
 (
     solveScalarField& result,
     const bool add,
+    const lduAddressing& lduAddr,
+    const label patchId,
     const solveScalarField& psiInternal,
     const scalarField& coeffs,
     const direction cmpt,
@@ -314,6 +316,7 @@ void Foam::calculatedProcessorFvPatchField<Type>::updateInterfaceMatrix
         return;
     }
 
+
     if
     (
         outstandingRecvRequest_ >= 0
@@ -337,13 +340,4 @@ void Foam::calculatedProcessorFvPatchField<Type>::updateInterfaceMatrix
 }
 
 
-//template<class Type>
-//void Foam::calculatedProcessorFvPatchField<Type>::write(Ostream& os) const
-//{
-//    //zeroGradientFvPatchField<Type>::write(os);
-//    fvPatchField<Type>::write(os);
-//    this->writeEntry("value", os);
-//}
-
-
 // ************************************************************************* //
diff --git a/src/overset/lduPrimitiveProcessorInterface/calculatedProcessorFvPatchField.H b/src/finiteVolume/fields/fvPatchFields/constraint/calculatedProcessor/calculatedProcessorFvPatchField.H
similarity index 94%
rename from src/overset/lduPrimitiveProcessorInterface/calculatedProcessorFvPatchField.H
rename to src/finiteVolume/fields/fvPatchFields/constraint/calculatedProcessor/calculatedProcessorFvPatchField.H
index 1753182ecb82a3a40eb8b8d449405f092bf16401..b2fd32a7bcd4da0d12bc53761d3a37940a0c6a38 100644
--- a/src/overset/lduPrimitiveProcessorInterface/calculatedProcessorFvPatchField.H
+++ b/src/finiteVolume/fields/fvPatchFields/constraint/calculatedProcessor/calculatedProcessorFvPatchField.H
@@ -30,7 +30,7 @@ Group
     grpGenericBoundaryConditions
 
 Description
-    processorFvPatchField type bypassing fvPatch
+    A processorFvPatchField type bypassing fvPatch
 
     Used to temporarily add updateInterfaceMatrix capabilities to a matrix
     during overset solving. Supplies:
@@ -68,7 +68,7 @@ class calculatedProcessorFvPatchField
 {
 protected:
 
-    // Private data
+    // Protected data
 
          //- Local reference cast into the interface
          const lduPrimitiveProcessorInterface& procInterface_;
@@ -94,8 +94,7 @@ protected:
             mutable label outstandingRecvRequest_;
 
 
-
-    // Private Member Functions
+    // Protected Member Functions
 
         void addToInternalField
         (
@@ -234,6 +233,8 @@ public:
             (
                 solveScalarField& result,
                 const bool add,
+                const lduAddressing& lduAddr,
+                const label patchId,
                 const solveScalarField& psiInternal,
                 const scalarField& coeffs,
                 const direction cmpt,
@@ -245,6 +246,8 @@ public:
             (
                 solveScalarField& result,
                 const bool add,
+                const lduAddressing& lduAddr,
+                const label patchId,
                 const solveScalarField& psiInternal,
                 const scalarField& coeffs,
                 const direction cmpt,
@@ -256,6 +259,8 @@ public:
             (
                 Field<Type>& result,
                 const bool add,
+                const lduAddressing& lduAddr,
+                const label patchId,
                 const Field<Type>& psiInternal,
                 const scalarField& coeffs,
                 const Pstream::commsTypes commsType
@@ -269,6 +274,8 @@ public:
             (
                 Field<Type>& result,
                 const bool add,
+                const lduAddressing& lduAddr,
+                const label patchId,
                 const Field<Type>& psiInternal,
                 const scalarField& coeffs,
                 const Pstream::commsTypes commsType
@@ -278,7 +285,7 @@ public:
             }
 
         //- Write
-        //virtual void write(Ostream&) const;
+        // virtual void write(Ostream& os) const;
 };
 
 
diff --git a/src/overset/lduPrimitiveProcessorInterface/calculatedProcessorFvPatchFields.C b/src/finiteVolume/fields/fvPatchFields/constraint/calculatedProcessor/calculatedProcessorFvPatchFields.C
similarity index 83%
rename from src/overset/lduPrimitiveProcessorInterface/calculatedProcessorFvPatchFields.C
rename to src/finiteVolume/fields/fvPatchFields/constraint/calculatedProcessor/calculatedProcessorFvPatchFields.C
index 580664a6397f7726bdfeb09d9bc14dd31560f824..e26c93931c3dc28926ca82285b35d5182afe13e8 100644
--- a/src/overset/lduPrimitiveProcessorInterface/calculatedProcessorFvPatchFields.C
+++ b/src/finiteVolume/fields/fvPatchFields/constraint/calculatedProcessor/calculatedProcessorFvPatchFields.C
@@ -37,15 +37,31 @@ namespace Foam
 
 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
 
-defineNamedTemplateTypeNameAndDebug(calculatedProcessorFvPatchScalarField, 0);
-defineNamedTemplateTypeNameAndDebug(calculatedProcessorFvPatchVectorField, 0);
+defineNamedTemplateTypeNameAndDebug
+(
+    calculatedProcessorFvPatchScalarField,
+    0
+);
+defineNamedTemplateTypeNameAndDebug
+(
+    calculatedProcessorFvPatchVectorField,
+    0
+);
 defineNamedTemplateTypeNameAndDebug
 (
     calculatedProcessorFvPatchSphericalTensorField,
     0
 );
-defineNamedTemplateTypeNameAndDebug(calculatedProcessorFvPatchSymmTensorField, 0);
-defineNamedTemplateTypeNameAndDebug(calculatedProcessorFvPatchTensorField, 0);
+defineNamedTemplateTypeNameAndDebug
+(
+    calculatedProcessorFvPatchSymmTensorField,
+    0
+);
+defineNamedTemplateTypeNameAndDebug
+(
+    calculatedProcessorFvPatchTensorField,
+    0
+);
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
diff --git a/src/overset/lduPrimitiveProcessorInterface/calculatedProcessorFvPatchFields.H b/src/finiteVolume/fields/fvPatchFields/constraint/calculatedProcessor/calculatedProcessorFvPatchFields.H
similarity index 100%
rename from src/overset/lduPrimitiveProcessorInterface/calculatedProcessorFvPatchFields.H
rename to src/finiteVolume/fields/fvPatchFields/constraint/calculatedProcessor/calculatedProcessorFvPatchFields.H
diff --git a/src/overset/lduPrimitiveProcessorInterface/calculatedProcessorFvPatchFieldsFwd.H b/src/finiteVolume/fields/fvPatchFields/constraint/calculatedProcessor/calculatedProcessorFvPatchFieldsFwd.H
similarity index 100%
rename from src/overset/lduPrimitiveProcessorInterface/calculatedProcessorFvPatchFieldsFwd.H
rename to src/finiteVolume/fields/fvPatchFields/constraint/calculatedProcessor/calculatedProcessorFvPatchFieldsFwd.H
diff --git a/src/finiteVolume/fields/fvPatchFields/constraint/cyclic/cyclicFvPatchField.C b/src/finiteVolume/fields/fvPatchFields/constraint/cyclic/cyclicFvPatchField.C
index ca0e6216e891c15671aa624e67ea92ad721cfe4e..43b9af13bc0d3430ca5fe5a0da8b3d1d7f7b0678 100644
--- a/src/finiteVolume/fields/fvPatchFields/constraint/cyclic/cyclicFvPatchField.C
+++ b/src/finiteVolume/fields/fvPatchFields/constraint/cyclic/cyclicFvPatchField.C
@@ -26,8 +26,10 @@ License
 
 \*---------------------------------------------------------------------------*/
 
+#include "fvMatrix.H"
 #include "cyclicFvPatchField.H"
 #include "transformField.H"
+#include "volFields.H"
 
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
@@ -174,27 +176,36 @@ Foam::cyclicFvPatchField<Type>::neighbourPatchField() const
 }
 
 
+
 template<class Type>
 void Foam::cyclicFvPatchField<Type>::updateInterfaceMatrix
 (
     solveScalarField& result,
     const bool add,
+    const lduAddressing& lduAddr,
+    const label patchId,
     const solveScalarField& psiInternal,
     const scalarField& coeffs,
     const direction cmpt,
-    const Pstream::commsTypes
+    const Pstream::commsTypes commsType
 ) const
 {
     const labelUList& nbrFaceCells =
-        cyclicPatch().cyclicPatch().neighbPatch().faceCells();
+        lduAddr.patchAddr
+        (
+            this->cyclicPatch().neighbPatchID()
+        );
 
     solveScalarField pnf(psiInternal, nbrFaceCells);
 
     // Transform according to the transformation tensors
     transformCoupleField(pnf, cmpt);
 
+
+    const labelUList& faceCells = lduAddr.patchAddr(patchId);
+
     // Multiply the field by coefficients and add into the result
-    this->addToInternalField(result, !add, coeffs, pnf);
+    this->addToInternalField(result, !add, faceCells, coeffs, pnf);
 }
 
 
@@ -203,21 +214,28 @@ void Foam::cyclicFvPatchField<Type>::updateInterfaceMatrix
 (
     Field<Type>& result,
     const bool add,
+    const lduAddressing& lduAddr,
+    const label patchId,
     const Field<Type>& psiInternal,
     const scalarField& coeffs,
     const Pstream::commsTypes
 ) const
 {
-    const labelUList& nbrFaceCells =
-        cyclicPatch().cyclicPatch().neighbPatch().faceCells();
+    const labelList& nbrFaceCells =
+        lduAddr.patchAddr
+        (
+            this->cyclicPatch().neighbPatchID()
+        );
 
     Field<Type> pnf(psiInternal, nbrFaceCells);
 
     // Transform according to the transformation tensors
     transformCoupleField(pnf);
 
+    const labelUList& faceCells = lduAddr.patchAddr(patchId);
+
     // Multiply the field by coefficients and add into the result
-    this->addToInternalField(result, !add, coeffs, pnf);
+    this->addToInternalField(result, !add, faceCells, coeffs, pnf);
 }
 
 
@@ -228,4 +246,81 @@ void Foam::cyclicFvPatchField<Type>::write(Ostream& os) const
 }
 
 
+template<class Type>
+void Foam::cyclicFvPatchField<Type>::manipulateMatrix
+(
+    fvMatrix<Type>& matrix,
+    const label mat,
+    const direction cmpt
+)
+{
+    if (this->cyclicPatch().owner())
+    {
+        label index = this->patch().index();
+
+        const label globalPatchID =
+            matrix.lduMeshAssembly().patchLocalToGlobalMap()[mat][index];
+
+        const Field<scalar> intCoeffsCmpt
+        (
+            matrix.internalCoeffs()[globalPatchID].component(cmpt)
+        );
+
+        const Field<scalar> boundCoeffsCmpt
+        (
+            matrix.boundaryCoeffs()[globalPatchID].component(cmpt)
+        );
+
+        const labelUList& u = matrix.lduAddr().upperAddr();
+        const labelUList& l = matrix.lduAddr().lowerAddr();
+
+        const labelList& faceMap =
+            matrix.lduMeshAssembly().faceBoundMap()[mat][index];
+
+        forAll (faceMap, faceI)
+        {
+            label globalFaceI = faceMap[faceI];
+
+            const scalar boundCorr = -boundCoeffsCmpt[faceI];
+            const scalar intCorr = -intCoeffsCmpt[faceI];
+
+            matrix.upper()[globalFaceI] += boundCorr;
+            matrix.diag()[u[globalFaceI]] -= boundCorr;
+            matrix.diag()[l[globalFaceI]] -= intCorr;
+
+            if (matrix.asymmetric())
+            {
+                matrix.lower()[globalFaceI] += intCorr;
+            }
+        }
+
+        if (matrix.psi(mat).mesh().fluxRequired(this->internalField().name()))
+        {
+            matrix.internalCoeffs().set
+            (
+                globalPatchID, intCoeffsCmpt*pTraits<Type>::one
+            );
+            matrix.boundaryCoeffs().set
+            (
+                globalPatchID, boundCoeffsCmpt*pTraits<Type>::one
+            );
+
+            const label nbrPathID = this->cyclicPatch().neighbPatchID();
+
+            const label nbrGlobalPatchID =
+                matrix.lduMeshAssembly().patchLocalToGlobalMap()[mat][nbrPathID];
+
+            matrix.internalCoeffs().set
+            (
+                nbrGlobalPatchID, intCoeffsCmpt*pTraits<Type>::one
+
+            );
+            matrix.boundaryCoeffs().set
+            (
+                nbrGlobalPatchID, boundCoeffsCmpt*pTraits<Type>::one
+            );
+        }
+    }
+}
+
 // ************************************************************************* //
diff --git a/src/finiteVolume/fields/fvPatchFields/constraint/cyclic/cyclicFvPatchField.H b/src/finiteVolume/fields/fvPatchFields/constraint/cyclic/cyclicFvPatchField.H
index 1678a23251bc4104c7c0ef4a00e443ea27ff4f82..33abab3bc7fa2f08e0962aab7a37c9491561cfc4 100644
--- a/src/finiteVolume/fields/fvPatchFields/constraint/cyclic/cyclicFvPatchField.H
+++ b/src/finiteVolume/fields/fvPatchFields/constraint/cyclic/cyclicFvPatchField.H
@@ -93,6 +93,7 @@ class cyclicFvPatchField
 
 public:
 
+
     //- Runtime type information
     TypeName(cyclicFvPatch::typeName_());
 
@@ -183,6 +184,8 @@ public:
             (
                 solveScalarField& result,
                 const bool add,
+                const lduAddressing& lduAddr,
+                const label patchId,
                 const solveScalarField& psiInternal,
                 const scalarField& coeffs,
                 const direction cmpt,
@@ -194,12 +197,24 @@ public:
             (
                 Field<Type>& result,
                 const bool add,
+                const lduAddressing& lduAddr,
+                const label patchId,
                 const Field<Type>& psiInternal,
                 const scalarField& coeffs,
                 const Pstream::commsTypes commsType
             ) const;
 
 
+            //- Manipulate matrix
+            virtual void manipulateMatrix
+            (
+                fvMatrix<Type>& m,
+                const label iMatrix,
+                const direction cmp
+            );
+
+
+
         // Cyclic coupled interface functions
 
             //- Does the patch field perform the transformation
diff --git a/src/finiteVolume/fields/fvPatchFields/constraint/cyclicACMI/cyclicACMIFvPatchField.C b/src/finiteVolume/fields/fvPatchFields/constraint/cyclicACMI/cyclicACMIFvPatchField.C
index 96415c00e56adaaa1645d264230e02b901037a02..b34124799508f8d754da15855d23802c0ecba278 100644
--- a/src/finiteVolume/fields/fvPatchFields/constraint/cyclicACMI/cyclicACMIFvPatchField.C
+++ b/src/finiteVolume/fields/fvPatchFields/constraint/cyclicACMI/cyclicACMIFvPatchField.C
@@ -26,6 +26,7 @@ License
 
 \*---------------------------------------------------------------------------*/
 
+#include "fvMatrix.H"
 #include "cyclicACMIFvPatchField.H"
 #include "transformField.H"
 
@@ -160,7 +161,13 @@ Foam::tmp<Foam::Field<Type>>
 Foam::cyclicACMIFvPatchField<Type>::patchNeighbourField() const
 {
     const Field<Type>& iField = this->primitiveField();
-    const cyclicACMIPolyPatch& cpp = cyclicACMIPatch_.cyclicACMIPatch();
+    //const cyclicACMIPolyPatch& cpp = cyclicACMIPatch_.cyclicACMIPatch();
+
+    // By pass polyPatch to get nbrId. Instead use cyclicAMIFvPatch virtual
+    // neighbPatch()
+    const cyclicACMIFvPatch& neighbPatch = cyclicACMIPatch_.neighbPatch();
+    const labelUList& nbrFaceCells = neighbPatch.faceCells();
+
     tmp<Field<Type>> tpnf
     (
         cyclicACMIPatch_.interpolate
@@ -168,7 +175,8 @@ Foam::cyclicACMIFvPatchField<Type>::patchNeighbourField() const
             Field<Type>
             (
                 iField,
-                cpp.neighbPatch().faceCells()
+                nbrFaceCells
+                //cpp.neighbPatch().faceCells()
             )
         )
     );
@@ -209,6 +217,7 @@ Foam::cyclicACMIFvPatchField<Type>::nonOverlapPatchField() const
             this->primitiveField()
         );
 
+    // WIP: Needs to re-direct nonOverlapPatchID to new patchId for assembly?
     return fld.boundaryField()[cyclicACMIPatch_.nonOverlapPatchID()];
 }
 
@@ -218,17 +227,24 @@ void Foam::cyclicACMIFvPatchField<Type>::updateInterfaceMatrix
 (
     solveScalarField& result,
     const bool add,
+    const lduAddressing& lduAddr,
+    const label patchId,
     const solveScalarField& psiInternal,
     const scalarField& coeffs,
     const direction cmpt,
     const Pstream::commsTypes
 ) const
 {
-    const cyclicACMIPolyPatch& cpp = cyclicACMIPatch_.cyclicACMIPatch();
+    // note: only applying coupled contribution
 
-    // Note: only applying coupled contribution
+//     const labelUList& nbrFaceCellsCoupled =
+//         lduAddr.patchAddr
+//         (
+//             cyclicACMIPatch_.cyclicACMIPatch().neighbPatchID()
+//         );
 
-    const labelUList& nbrFaceCellsCoupled = cpp.neighbPatch().faceCells();
+    const labelUList& nbrFaceCellsCoupled =
+        lduAddr.patchAddr(cyclicACMIPatch_.neighbPatchID());
 
     solveScalarField pnf(psiInternal, nbrFaceCellsCoupled);
 
@@ -237,7 +253,9 @@ void Foam::cyclicACMIFvPatchField<Type>::updateInterfaceMatrix
 
     pnf = cyclicACMIPatch_.interpolate(pnf);
 
-    this->addToInternalField(result, !add, coeffs, pnf);
+    const labelUList& faceCells = lduAddr.patchAddr(patchId);
+
+    this->addToInternalField(result, !add, faceCells, coeffs, pnf);
 }
 
 
@@ -246,16 +264,17 @@ void Foam::cyclicACMIFvPatchField<Type>::updateInterfaceMatrix
 (
     Field<Type>& result,
     const bool add,
+    const lduAddressing& lduAddr,
+    const label patchId,
     const Field<Type>& psiInternal,
     const scalarField& coeffs,
     const Pstream::commsTypes
 ) const
 {
-    const cyclicACMIPolyPatch& cpp = cyclicACMIPatch_.cyclicACMIPatch();
+    // note: only applying coupled contribution
 
-    // Note: only applying coupled contribution
-
-    const labelUList& nbrFaceCellsCoupled = cpp.neighbPatch().faceCells();
+    const labelUList& nbrFaceCellsCoupled =
+        lduAddr.patchAddr(cyclicACMIPatch_.neighbPatchID());
 
     Field<Type> pnf(psiInternal, nbrFaceCellsCoupled);
 
@@ -264,7 +283,9 @@ void Foam::cyclicACMIFvPatchField<Type>::updateInterfaceMatrix
 
     pnf = cyclicACMIPatch_.interpolate(pnf);
 
-    this->addToInternalField(result, !add, coeffs, pnf);
+    const labelUList& faceCells = lduAddr.patchAddr(patchId);
+
+    this->addToInternalField(result, !add, faceCells, coeffs, pnf);
 }
 
 
@@ -284,6 +305,141 @@ void Foam::cyclicACMIFvPatchField<Type>::manipulateMatrix
 }
 
 
+template<class Type>
+void Foam::cyclicACMIFvPatchField<Type>::manipulateMatrix
+(
+    fvMatrix<Type>& matrix,
+    const label mat,
+    const direction cmpt
+)
+{
+    if (this->cyclicACMIPatch().owner())
+    {
+        label index = this->patch().index();
+
+        const label globalPatchID =
+            matrix.lduMeshAssembly().patchLocalToGlobalMap()[mat][index];
+
+        const Field<scalar> intCoeffsCmpt
+        (
+            matrix.internalCoeffs()[globalPatchID].component(cmpt)
+        );
+
+        const Field<scalar> boundCoeffsCmpt
+        (
+            matrix.boundaryCoeffs()[globalPatchID].component(cmpt)
+        );
+
+        tmp<Field<scalar>> tintCoeffs(coeffs(matrix, intCoeffsCmpt, mat));
+        tmp<Field<scalar>> tbndCoeffs(coeffs(matrix, boundCoeffsCmpt, mat));
+        const Field<scalar>& intCoeffs = tintCoeffs.ref();
+        const Field<scalar>& bndCoeffs = tbndCoeffs.ref();
+
+        const labelUList& u = matrix.lduAddr().upperAddr();
+        const labelUList& l = matrix.lduAddr().lowerAddr();
+
+        label subFaceI = 0;
+
+        const labelList& faceMap =
+            matrix.lduMeshAssembly().faceBoundMap()[mat][index];
+
+        forAll (faceMap, j)
+        {
+            label globalFaceI = faceMap[j];
+
+            const scalar boundCorr = -bndCoeffs[subFaceI];
+            const scalar intCorr = -intCoeffs[subFaceI];
+
+            matrix.upper()[globalFaceI] += boundCorr;
+            matrix.diag()[u[globalFaceI]] -= intCorr;
+            matrix.diag()[l[globalFaceI]] -= boundCorr;
+
+            if (matrix.asymmetric())
+            {
+                matrix.lower()[globalFaceI] += intCorr;
+            }
+            subFaceI++;
+        }
+
+        // Set internalCoeffs and boundaryCoeffs in the assembly matrix
+        // on clyclicAMI patches to be used in the individual matrix by
+        // matrix.flux()
+        if (matrix.psi(mat).mesh().fluxRequired(this->internalField().name()))
+        {
+            matrix.internalCoeffs().set
+            (
+                globalPatchID, intCoeffs*pTraits<Type>::one
+            );
+            matrix.boundaryCoeffs().set
+            (
+                globalPatchID, bndCoeffs*pTraits<Type>::one
+            );
+
+            const label nbrPathID =
+                cyclicACMIPatch_.cyclicACMIPatch().neighbPatchID();
+
+            const label nbrGlobalPatchID =
+                matrix.lduMeshAssembly().patchLocalToGlobalMap()
+                [mat][nbrPathID];
+
+            matrix.internalCoeffs().set
+            (
+                nbrGlobalPatchID, intCoeffs*pTraits<Type>::one
+            );
+            matrix.boundaryCoeffs().set
+            (
+                nbrGlobalPatchID, bndCoeffs*pTraits<Type>::one
+            );
+        }
+    }
+}
+
+
+template<class Type>
+Foam::tmp<Foam::Field<Foam::scalar>>
+Foam::cyclicACMIFvPatchField<Type>::coeffs
+(
+    fvMatrix<Type>& matrix,
+    const Field<scalar>& coeffs,
+    const label mat
+) const
+{
+    const label index(this->patch().index());
+
+    const label nSubFaces
+    (
+        matrix.lduMeshAssembly().cellBoundMap()[mat][index].size()
+    );
+
+    Field<scalar> mapCoeffs(nSubFaces, Zero);
+
+    const scalarListList& srcWeight =
+        cyclicACMIPatch_.cyclicACMIPatch().AMI().srcWeights();
+
+    const scalarField& mask = cyclicACMIPatch_.cyclicACMIPatch().mask();
+
+    const scalar tol = cyclicACMIPolyPatch::tolerance();
+    label subFaceI = 0;
+    forAll(mask, faceI)
+    {
+        const scalarList& w = srcWeight[faceI];
+        for(label i=0; i<w.size(); i++)
+        {
+            if (mask[faceI] > tol)
+            {
+                const label localFaceId =
+                    matrix.lduMeshAssembly().facePatchFaceMap()
+                    [mat][index][subFaceI];
+                mapCoeffs[subFaceI] = w[i]*coeffs[localFaceId];
+            }
+            subFaceI++;
+        }
+    }
+
+    return tmp<Field<scalar>>(new Field<scalar>(mapCoeffs));
+}
+
+
 template<class Type>
 void Foam::cyclicACMIFvPatchField<Type>::updateCoeffs()
 {
diff --git a/src/finiteVolume/fields/fvPatchFields/constraint/cyclicACMI/cyclicACMIFvPatchField.H b/src/finiteVolume/fields/fvPatchFields/constraint/cyclicACMI/cyclicACMIFvPatchField.H
index db093b3940174646b4663dd5a93f52491f220d18..da1097b06cb15841fb5884c8fcb73919a6c77339 100644
--- a/src/finiteVolume/fields/fvPatchFields/constraint/cyclicACMI/cyclicACMIFvPatchField.H
+++ b/src/finiteVolume/fields/fvPatchFields/constraint/cyclicACMI/cyclicACMIFvPatchField.H
@@ -89,6 +89,15 @@ class cyclicACMIFvPatchField
             const Field<Type2>&
         ) const;
 
+         //- Return new matrix coeffs
+        tmp<Field<scalar>> coeffs
+        (
+            fvMatrix<Type>& matrix,
+            const Field<scalar>&,
+            const label
+        ) const;
+
+
 
 public:
 
@@ -206,6 +215,8 @@ public:
             (
                 solveScalarField& result,
                 const bool add,
+                const lduAddressing& lduAddr,
+                const label patchId,
                 const solveScalarField& psiInternal,
                 const scalarField& coeffs,
                 const direction cmpt,
@@ -217,6 +228,8 @@ public:
             (
                 Field<Type>&,
                 const bool add,
+                const lduAddressing& lduAddr,
+                const label patchId,
                 const Field<Type>&,
                 const scalarField&,
                 const Pstream::commsTypes commsType
@@ -225,6 +238,14 @@ public:
             //- Manipulate matrix
             virtual void manipulateMatrix(fvMatrix<Type>& matrix);
 
+            //- Manipulate matrix
+            virtual void manipulateMatrix
+            (
+                fvMatrix<Type>& m,
+                const label iMatrix,
+                const direction cmpt
+            );
+
             //- Update the coefficients associated with the patch field
             virtual void updateCoeffs();
 
diff --git a/src/finiteVolume/fields/fvPatchFields/constraint/cyclicAMI/cyclicAMIFvPatchField.C b/src/finiteVolume/fields/fvPatchFields/constraint/cyclicAMI/cyclicAMIFvPatchField.C
index eb3053dd881e673645569cbb50a0407cca311a7e..95bccb0e3f91de85129efe95fadaf5bcddb001d6 100644
--- a/src/finiteVolume/fields/fvPatchFields/constraint/cyclicAMI/cyclicAMIFvPatchField.C
+++ b/src/finiteVolume/fields/fvPatchFields/constraint/cyclicAMI/cyclicAMIFvPatchField.C
@@ -26,6 +26,10 @@ License
 
 \*---------------------------------------------------------------------------*/
 
+#include "fvMatrix.H"
+#include "volFields.H"
+//#include "cylicFvPatchField.H"
+
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
 template<class Type>
@@ -142,15 +146,20 @@ Foam::tmp<Foam::Field<Type>>
 Foam::cyclicAMIFvPatchField<Type>::patchNeighbourField() const
 {
     const Field<Type>& iField = this->primitiveField();
-    const labelUList& nbrFaceCells =
-        cyclicAMIPatch_.cyclicAMIPatch().neighbPatch().faceCells();
+
+    // By pass polyPatch to get nbrId. Instead use cyclicAMIFvPatch virtual
+    // neighbPatch()
+    const cyclicAMIFvPatch& neighbPatch = cyclicAMIPatch_.neighbPatch();
+    const labelUList& nbrFaceCells = neighbPatch.faceCells();
 
     Field<Type> pnf(iField, nbrFaceCells);
 
     tmp<Field<Type>> tpnf;
     if (cyclicAMIPatch_.applyLowWeightCorrection())
     {
-        tpnf = cyclicAMIPatch_.interpolate(pnf, this->patchInternalField()());
+        Field<Type> pnfInternal(iField, cyclicAMIPatch_.faceCells());
+
+        tpnf = cyclicAMIPatch_.interpolate(pnf, pnfInternal);
     }
     else
     {
@@ -188,6 +197,8 @@ void Foam::cyclicAMIFvPatchField<Type>::updateInterfaceMatrix
 (
     solveScalarField& result,
     const bool add,
+    const lduAddressing& lduAddr,
+    const label patchId,
     const solveScalarField& psiInternal,
     const scalarField& coeffs,
     const direction cmpt,
@@ -195,7 +206,7 @@ void Foam::cyclicAMIFvPatchField<Type>::updateInterfaceMatrix
 ) const
 {
     const labelUList& nbrFaceCells =
-        cyclicAMIPatch_.cyclicAMIPatch().neighbPatch().faceCells();
+        lduAddr.patchAddr(cyclicAMIPatch_.neighbPatchID());
 
     solveScalarField pnf(psiInternal, nbrFaceCells);
 
@@ -212,8 +223,10 @@ void Foam::cyclicAMIFvPatchField<Type>::updateInterfaceMatrix
         pnf = cyclicAMIPatch_.interpolate(pnf);
     }
 
+    const labelUList& faceCells = lduAddr.patchAddr(patchId);
+
     // Multiply the field by coefficients and add into the result
-    this->addToInternalField(result, !add, coeffs, pnf);
+    this->addToInternalField(result, !add, faceCells, coeffs, pnf);
 }
 
 
@@ -222,13 +235,15 @@ void Foam::cyclicAMIFvPatchField<Type>::updateInterfaceMatrix
 (
     Field<Type>& result,
     const bool add,
+    const lduAddressing& lduAddr,
+    const label patchId,
     const Field<Type>& psiInternal,
     const scalarField& coeffs,
     const Pstream::commsTypes
 ) const
 {
     const labelUList& nbrFaceCells =
-        cyclicAMIPatch_.cyclicAMIPatch().neighbPatch().faceCells();
+        lduAddr.patchAddr(cyclicAMIPatch_.neighbPatchID());
 
     Field<Type> pnf(psiInternal, nbrFaceCells);
 
@@ -245,8 +260,178 @@ void Foam::cyclicAMIFvPatchField<Type>::updateInterfaceMatrix
         pnf = cyclicAMIPatch_.interpolate(pnf);
     }
 
+    const labelUList& faceCells = lduAddr.patchAddr(patchId);
+
     // Multiply the field by coefficients and add into the result
-    this->addToInternalField(result, !add, coeffs, pnf);
+    this->addToInternalField(result, !add, faceCells, coeffs, pnf);
+}
+
+
+template<class Type>
+void Foam::cyclicAMIFvPatchField<Type>::manipulateMatrix
+(
+    fvMatrix<Type>& matrix,
+    const label mat,
+    const direction cmpt
+)
+{
+
+    if (this->cyclicAMIPatch().owner())
+    {
+        label index = this->patch().index();
+
+        const label globalPatchID =
+            matrix.lduMeshAssembly().patchLocalToGlobalMap()[mat][index];
+
+        const Field<scalar> intCoeffsCmpt
+        (
+            matrix.internalCoeffs()[globalPatchID].component(cmpt)
+        );
+
+        const Field<scalar> boundCoeffsCmpt
+        (
+            matrix.boundaryCoeffs()[globalPatchID].component(cmpt)
+        );
+
+        tmp<Field<scalar>> tintCoeffs(coeffs(matrix, intCoeffsCmpt, mat));
+        tmp<Field<scalar>> tbndCoeffs(coeffs(matrix, boundCoeffsCmpt, mat));
+        const Field<scalar>& intCoeffs = tintCoeffs.ref();
+        const Field<scalar>& bndCoeffs = tbndCoeffs.ref();
+
+        const labelUList& u = matrix.lduAddr().upperAddr();
+        const labelUList& l = matrix.lduAddr().lowerAddr();
+
+        label subFaceI = 0;
+
+        const labelList& faceMap =
+            matrix.lduMeshAssembly().faceBoundMap()[mat][index];
+
+        forAll (faceMap, j)
+        {
+            label globalFaceI = faceMap[j];
+
+            const scalar boundCorr = -bndCoeffs[subFaceI];
+            const scalar intCorr = -intCoeffs[subFaceI];
+
+            matrix.upper()[globalFaceI] += boundCorr;
+            matrix.diag()[u[globalFaceI]] -= intCorr;
+            matrix.diag()[l[globalFaceI]] -= boundCorr;
+
+            if (matrix.asymmetric())
+            {
+                matrix.lower()[globalFaceI] += intCorr;
+            }
+            subFaceI++;
+        }
+
+        // Set internalCoeffs and boundaryCoeffs in the assembly matrix
+        // on clyclicAMI patches to be used in the individual matrix by
+        // matrix.flux()
+        if (matrix.psi(mat).mesh().fluxRequired(this->internalField().name()))
+        {
+            matrix.internalCoeffs().set
+            (
+                globalPatchID, intCoeffs*pTraits<Type>::one
+            );
+            matrix.boundaryCoeffs().set
+            (
+                globalPatchID, bndCoeffs*pTraits<Type>::one
+            );
+
+            const label nbrPathID =
+                cyclicAMIPatch_.cyclicAMIPatch().neighbPatchID();
+
+            const label nbrGlobalPatchID =
+                matrix.lduMeshAssembly().patchLocalToGlobalMap()
+                    [mat][nbrPathID];
+
+            matrix.internalCoeffs().set
+            (
+                nbrGlobalPatchID, intCoeffs*pTraits<Type>::one
+            );
+            matrix.boundaryCoeffs().set
+            (
+                nbrGlobalPatchID, bndCoeffs*pTraits<Type>::one
+            );
+        }
+    }
+}
+
+
+template<class Type>
+Foam::tmp<Foam::Field<Foam::scalar>>
+Foam::cyclicAMIFvPatchField<Type>::coeffs
+(
+    fvMatrix<Type>& matrix,
+    const Field<scalar>& coeffs,
+    const label mat
+) const
+{
+    const label index(this->patch().index());
+
+    const label nSubFaces
+    (
+        matrix.lduMeshAssembly().cellBoundMap()[mat][index].size()
+    );
+
+    Field<scalar> mapCoeffs(nSubFaces, Zero);
+
+    const scalarListList& srcWeight =
+        cyclicAMIPatch_.cyclicAMIPatch().AMI().srcWeights();
+
+    label subFaceI = 0;
+    forAll(*this, faceI)
+    {
+        const scalarList& w = srcWeight[faceI];
+        for(label i=0; i<w.size(); i++)
+        {
+            const label localFaceId =
+                matrix.lduMeshAssembly().facePatchFaceMap()[mat][index][subFaceI];
+            mapCoeffs[subFaceI] = w[i]*coeffs[localFaceId];
+            subFaceI++;
+        }
+    }
+
+    return tmp<Field<scalar>>(new Field<scalar>(mapCoeffs));
+}
+
+
+template<class Type>
+template<class Type2>
+void Foam::cyclicAMIFvPatchField<Type>::collectStencilData
+(
+    const refPtr<mapDistribute>& mapPtr,
+    const labelListList& stencil,
+    const Type2& data,
+    List<Type2>& expandedData
+)
+{
+    expandedData.setSize(stencil.size());
+    if (mapPtr.valid())
+    {
+        Type2 work(data);
+        mapPtr().distribute(work);
+
+        forAll(stencil, facei)
+        {
+            const labelList& slots = stencil[facei];
+            expandedData[facei].append
+            (
+                UIndirectList<typename Type2::value_type>(work, slots)
+            );
+        }
+    }
+    else
+    {
+        forAll(stencil, facei)
+        {
+            const labelList& slots = stencil[facei];
+            expandedData[facei].append
+            (
+                UIndirectList<typename Type2::value_type>(data, slots)
+            );
+        }
+    }
 }
 
 
@@ -259,3 +444,4 @@ void Foam::cyclicAMIFvPatchField<Type>::write(Ostream& os) const
 
 
 // ************************************************************************* //
+
diff --git a/src/finiteVolume/fields/fvPatchFields/constraint/cyclicAMI/cyclicAMIFvPatchField.H b/src/finiteVolume/fields/fvPatchFields/constraint/cyclicAMI/cyclicAMIFvPatchField.H
index b5bc5533e2af72db160ff78b50e48a204abe1e8d..08ddce2aa708745114c93509e1df677ddffb9f3a 100644
--- a/src/finiteVolume/fields/fvPatchFields/constraint/cyclicAMI/cyclicAMIFvPatchField.H
+++ b/src/finiteVolume/fields/fvPatchFields/constraint/cyclicAMI/cyclicAMIFvPatchField.H
@@ -60,6 +60,7 @@ SourceFiles
 #ifndef cyclicAMIFvPatchField_H
 #define cyclicAMIFvPatchField_H
 
+
 #include "coupledFvPatchField.H"
 #include "cyclicAMILduInterfaceField.H"
 #include "cyclicAMIFvPatch.H"
@@ -95,6 +96,25 @@ class cyclicAMIFvPatchField
         ) const;
 
 
+        //- Return new matrix coeffs
+        tmp<Field<scalar>> coeffs
+        (
+            fvMatrix<Type>& matrix,
+            const Field<scalar>&,
+            const label
+        ) const;
+
+
+        template<class Type2>
+        void collectStencilData
+        (
+            const refPtr<mapDistribute>& mapPtr,
+            const labelListList& stencil,
+            const Type2& data,
+            List<Type2>& expandedData
+        );
+
+
 public:
 
     //- Runtime type information
@@ -187,6 +207,8 @@ public:
             (
                 solveScalarField& result,
                 const bool add,
+                const lduAddressing& lduAddr,
+                const label patchId,
                 const solveScalarField& psiInternal,
                 const scalarField& coeffs,
                 const direction cmpt,
@@ -198,12 +220,23 @@ public:
             (
                 Field<Type>&,
                 const bool add,
+                const lduAddressing& lduAddr,
+                const label patchId,
                 const Field<Type>&,
                 const scalarField&,
                 const Pstream::commsTypes commsType
             ) const;
 
 
+            //- Manipulate matrix
+            virtual void manipulateMatrix
+            (
+                fvMatrix<Type>& m,
+                const label iMatrix,
+                const direction cmpt
+            );
+
+
         // Cyclic AMI coupled interface functions
 
             //- Does the patch field perform the transformation
diff --git a/src/finiteVolume/fields/fvPatchFields/constraint/jumpCyclic/jumpCyclicFvPatchField.C b/src/finiteVolume/fields/fvPatchFields/constraint/jumpCyclic/jumpCyclicFvPatchField.C
index 312829ed0d7e862ac4097a3ac82c67beec7edda8..2b5e3a364bb4bec03af58f155c68a0b28dce5395 100644
--- a/src/finiteVolume/fields/fvPatchFields/constraint/jumpCyclic/jumpCyclicFvPatchField.C
+++ b/src/finiteVolume/fields/fvPatchFields/constraint/jumpCyclic/jumpCyclicFvPatchField.C
@@ -101,8 +101,8 @@ Foam::jumpCyclicFvPatchField<Type>::patchNeighbourField() const
     const labelUList& nbrFaceCells =
         this->cyclicPatch().neighbFvPatch().faceCells();
 
-    tmp<Field<Type>> tpnf(new Field<Type>(this->size()));
-    Field<Type>& pnf = tpnf.ref();
+    auto tpnf = tmp<Field<Type>>::New(this->size());
+    auto& pnf = tpnf.ref();
 
     Field<Type> jf(this->jump());
     if (!this->cyclicPatch().owner())
@@ -137,6 +137,8 @@ void Foam::jumpCyclicFvPatchField<Type>::updateInterfaceMatrix
 (
     solveScalarField& result,
     const bool add,
+    const lduAddressing& lduAddr,
+    const label patchId,
     const solveScalarField& psiInternal,
     const scalarField& coeffs,
     const direction cmpt,
@@ -152,6 +154,8 @@ void Foam::jumpCyclicFvPatchField<Type>::updateInterfaceMatrix
 (
     Field<Type>& result,
     const bool add,
+    const lduAddressing& lduAddr,
+    const label patchId,
     const Field<Type>& psiInternal,
     const scalarField& coeffs,
     const Pstream::commsTypes
@@ -160,7 +164,10 @@ void Foam::jumpCyclicFvPatchField<Type>::updateInterfaceMatrix
     Field<Type> pnf(this->size());
 
     const labelUList& nbrFaceCells =
-        this->cyclicPatch().neighbFvPatch().faceCells();
+        lduAddr.patchAddr
+        (
+            this->cyclicPatch().neighbPatchID()
+        );
 
     // only apply jump to original field
     if (&psiInternal == &this->primitiveField())
@@ -188,8 +195,10 @@ void Foam::jumpCyclicFvPatchField<Type>::updateInterfaceMatrix
     // Transform according to the transformation tensors
     this->transformCoupleField(pnf);
 
+    const labelUList& faceCells = lduAddr.patchAddr(patchId);
+
     // Multiply the field by coefficients and add into the result
-    this->addToInternalField(result, !add, coeffs, pnf);
+    this->addToInternalField(result, !add, faceCells, coeffs, pnf);
 }
 
 
diff --git a/src/finiteVolume/fields/fvPatchFields/constraint/jumpCyclic/jumpCyclicFvPatchField.H b/src/finiteVolume/fields/fvPatchFields/constraint/jumpCyclic/jumpCyclicFvPatchField.H
index 0b0425b1cc6afd9f5c94bf3d347dbf8785bd620e..28c803b6591ea4e617502e79ced080de7f224544 100644
--- a/src/finiteVolume/fields/fvPatchFields/constraint/jumpCyclic/jumpCyclicFvPatchField.H
+++ b/src/finiteVolume/fields/fvPatchFields/constraint/jumpCyclic/jumpCyclicFvPatchField.H
@@ -133,6 +133,8 @@ public:
             (
                 solveScalarField& result,
                 const bool add,
+                const lduAddressing& lduAddr,
+                const label patchId,
                 const solveScalarField& psiInternal,
                 const scalarField& coeffs,
                 const direction cmpt,
@@ -144,6 +146,8 @@ public:
             (
                 Field<Type>&,
                 const bool add,
+                const lduAddressing& lduAddr,
+                const label patchId,
                 const Field<Type>&,
                 const scalarField&,
                 const Pstream::commsTypes commsType
@@ -156,6 +160,8 @@ void jumpCyclicFvPatchField<scalar>::updateInterfaceMatrix
 (
     solveScalarField& result,
     const bool add,
+    const lduAddressing& lduAddr,
+    const label patchId,
     const solveScalarField& psiInternal,
     const scalarField& coeffs,
     const direction cmpt,
@@ -168,6 +174,8 @@ void jumpCyclicFvPatchField<vector>::updateInterfaceMatrix
 (
     solveScalarField& result,
     const bool add,
+    const lduAddressing& lduAddr,
+    const label patchId,
     const solveScalarField& psiInternal,
     const scalarField& coeffs,
     const direction cmpt,
diff --git a/src/finiteVolume/fields/fvPatchFields/constraint/jumpCyclic/jumpCyclicFvPatchFields.C b/src/finiteVolume/fields/fvPatchFields/constraint/jumpCyclic/jumpCyclicFvPatchFields.C
index f940085a4d5d57c5f5dbc965fe01ca6f0a08bb3d..a0310e7b50a5342e62d72d076354b109a7e55fbd 100644
--- a/src/finiteVolume/fields/fvPatchFields/constraint/jumpCyclic/jumpCyclicFvPatchFields.C
+++ b/src/finiteVolume/fields/fvPatchFields/constraint/jumpCyclic/jumpCyclicFvPatchFields.C
@@ -44,6 +44,8 @@ void Foam::jumpCyclicFvPatchField<Foam::scalar>::updateInterfaceMatrix
 (
     solveScalarField& result,
     const bool add,
+    const lduAddressing& lduAddr,
+    const label patchId,
     const solveScalarField& psiInternal,
     const scalarField& coeffs,
     const direction cmpt,
@@ -53,7 +55,10 @@ void Foam::jumpCyclicFvPatchField<Foam::scalar>::updateInterfaceMatrix
     solveScalarField pnf(this->size());
 
     const labelUList& nbrFaceCells =
-        this->cyclicPatch().neighbFvPatch().faceCells();
+        lduAddr.patchAddr
+        (
+            this->cyclicPatch().neighbPatchID()
+        );
 
     // only apply jump to original field
     if
@@ -85,8 +90,10 @@ void Foam::jumpCyclicFvPatchField<Foam::scalar>::updateInterfaceMatrix
     // Transform according to the transformation tensors
     this->transformCoupleField(pnf, cmpt);
 
+    const labelUList& faceCells = lduAddr.patchAddr(patchId);
+
     // Multiply the field by coefficients and add into the result
-    this->addToInternalField(result, !add, coeffs, pnf);
+    this->addToInternalField(result, !add, faceCells, coeffs, pnf);
 }
 
 
@@ -95,6 +102,8 @@ void Foam::jumpCyclicFvPatchField<Foam::vector>::updateInterfaceMatrix
 (
     solveScalarField& result,
     const bool add,
+    const lduAddressing& lduAddr,
+    const label patchId,
     const solveScalarField& psiInternal,
     const scalarField& coeffs,
     const direction cmpt,
@@ -104,7 +113,10 @@ void Foam::jumpCyclicFvPatchField<Foam::vector>::updateInterfaceMatrix
     solveScalarField pnf(this->size());
 
     const labelUList& nbrFaceCells =
-        this->cyclicPatch().neighbFvPatch().faceCells();
+        lduAddr.patchAddr
+        (
+            this->cyclicPatch().neighbPatchID()
+        );
 
     const Field<vector>& iField = this->primitiveField();
 
@@ -140,8 +152,10 @@ void Foam::jumpCyclicFvPatchField<Foam::vector>::updateInterfaceMatrix
     // Transform according to the transformation tensors
     this->transformCoupleField(pnf, cmpt);
 
+    const labelUList& faceCells = lduAddr.patchAddr(patchId);
+
     // Multiply the field by coefficients and add into the result
-    this->addToInternalField(result, !add, coeffs, pnf);
+    this->addToInternalField(result, !add, faceCells, coeffs, pnf);
 }
 
 // ************************************************************************* //
diff --git a/src/finiteVolume/fields/fvPatchFields/constraint/jumpCyclicAMI/jumpCyclicAMIFvPatchField.C b/src/finiteVolume/fields/fvPatchFields/constraint/jumpCyclicAMI/jumpCyclicAMIFvPatchField.C
index beec9d54a283d7e118bab9195a37d4f0b5628b90..f96eaa1468c928fe9a6174133c43c3e5b6669170 100644
--- a/src/finiteVolume/fields/fvPatchFields/constraint/jumpCyclicAMI/jumpCyclicAMIFvPatchField.C
+++ b/src/finiteVolume/fields/fvPatchFields/constraint/jumpCyclicAMI/jumpCyclicAMIFvPatchField.C
@@ -138,6 +138,8 @@ void Foam::jumpCyclicAMIFvPatchField<Type>::updateInterfaceMatrix
 (
     solveScalarField& result,
     const bool add,
+    const lduAddressing& lduAddr,
+    const label patchId,
     const solveScalarField& psiInternal,
     const scalarField& coeffs,
     const direction cmpt,
@@ -153,13 +155,18 @@ void Foam::jumpCyclicAMIFvPatchField<Type>::updateInterfaceMatrix
 (
     Field<Type>& result,
     const bool add,
+    const lduAddressing& lduAddr,
+    const label patchId,
     const Field<Type>& psiInternal,
     const scalarField& coeffs,
     const Pstream::commsTypes
 ) const
 {
     const labelUList& nbrFaceCells =
-        this->cyclicAMIPatch().cyclicAMIPatch().neighbPatch().faceCells();
+        lduAddr.patchAddr
+        (
+            this->cyclicAMIPatch().neighbPatchID()
+        );
 
     Field<Type> pnf(psiInternal, nbrFaceCells);
 
@@ -193,8 +200,10 @@ void Foam::jumpCyclicAMIFvPatchField<Type>::updateInterfaceMatrix
     // Transform according to the transformation tensors
     this->transformCoupleField(pnf);
 
+    const labelUList& faceCells = lduAddr.patchAddr(patchId);
+
     // Multiply the field by coefficients and add into the result
-    this->addToInternalField(result, !add, coeffs, pnf);
+    this->addToInternalField(result, !add,faceCells, coeffs, pnf);
 }
 
 
diff --git a/src/finiteVolume/fields/fvPatchFields/constraint/jumpCyclicAMI/jumpCyclicAMIFvPatchField.H b/src/finiteVolume/fields/fvPatchFields/constraint/jumpCyclicAMI/jumpCyclicAMIFvPatchField.H
index 11f6e5c2a22d66e8a577bd3661c7139c57a6a141..81bc12133d9db69e5608e2f50c3b61ba552033b5 100644
--- a/src/finiteVolume/fields/fvPatchFields/constraint/jumpCyclicAMI/jumpCyclicAMIFvPatchField.H
+++ b/src/finiteVolume/fields/fvPatchFields/constraint/jumpCyclicAMI/jumpCyclicAMIFvPatchField.H
@@ -135,6 +135,8 @@ public:
             (
                 solveScalarField& result,
                 const bool add,
+                const lduAddressing& lduAddr,
+                const label patchId,
                 const solveScalarField& psiInternal,
                 const scalarField& coeffs,
                 const direction cmpt,
@@ -146,6 +148,8 @@ public:
             (
                 Field<Type>&,
                 const bool add,
+                const lduAddressing& lduAddr,
+                const label patchId,
                 const Field<Type>&,
                 const scalarField&,
                 const Pstream::commsTypes commsType
@@ -159,6 +163,8 @@ void jumpCyclicAMIFvPatchField<scalar>::updateInterfaceMatrix
 (
     solveScalarField& result,
     const bool add,
+    const lduAddressing& lduAddr,
+    const label patchId,
     const solveScalarField& psiInternal,
     const scalarField& coeffs,
     const direction cmpt,
diff --git a/src/finiteVolume/fields/fvPatchFields/constraint/jumpCyclicAMI/jumpCyclicAMIFvPatchFields.C b/src/finiteVolume/fields/fvPatchFields/constraint/jumpCyclicAMI/jumpCyclicAMIFvPatchFields.C
index cca426b92df00a7633334f60c6f14f12fc20d7f7..3fdac24f67b4662f7bfc49cb5fa63d980e0584b4 100644
--- a/src/finiteVolume/fields/fvPatchFields/constraint/jumpCyclicAMI/jumpCyclicAMIFvPatchFields.C
+++ b/src/finiteVolume/fields/fvPatchFields/constraint/jumpCyclicAMI/jumpCyclicAMIFvPatchFields.C
@@ -46,6 +46,8 @@ void Foam::jumpCyclicAMIFvPatchField<scalar>::updateInterfaceMatrix
 (
     solveScalarField& result,
     const bool add,
+    const lduAddressing& lduAddr,
+    const label patchId,
     const solveScalarField& psiInternal,
     const scalarField& coeffs,
     const direction cmpt,
@@ -53,7 +55,10 @@ void Foam::jumpCyclicAMIFvPatchField<scalar>::updateInterfaceMatrix
 ) const
 {
     const labelUList& nbrFaceCells =
-        this->cyclicAMIPatch().cyclicAMIPatch().neighbPatch().faceCells();
+        lduAddr.patchAddr
+        (
+            this->cyclicAMIPatch().neighbPatchID()
+        );
 
     solveScalarField pnf(psiInternal, nbrFaceCells);
 
@@ -83,8 +88,10 @@ void Foam::jumpCyclicAMIFvPatchField<scalar>::updateInterfaceMatrix
     // Transform according to the transformation tensors
     this->transformCoupleField(pnf, cmpt);
 
+    const labelUList& faceCells = lduAddr.patchAddr(patchId);
+
     // Multiply the field by coefficients and add into the result
-    this->addToInternalField(result, !add, coeffs, pnf);
+    this->addToInternalField(result, !add, faceCells, coeffs, pnf);
 }
 
 
diff --git a/src/finiteVolume/fields/fvPatchFields/constraint/processor/processorFvPatchField.C b/src/finiteVolume/fields/fvPatchFields/constraint/processor/processorFvPatchField.C
index 195dcff8a6cfa5ea2bf47194c89d038abee8a912..c87c52a8d9631e5b794f40452911792ff3d54878 100644
--- a/src/finiteVolume/fields/fvPatchFields/constraint/processor/processorFvPatchField.C
+++ b/src/finiteVolume/fields/fvPatchFields/constraint/processor/processorFvPatchField.C
@@ -313,13 +313,23 @@ void Foam::processorFvPatchField<Type>::initInterfaceMatrixUpdate
 (
     solveScalarField&,
     const bool add,
+    const lduAddressing& lduAddr,
+    const label patchId,
     const solveScalarField& psiInternal,
     const scalarField&,
     const direction,
     const Pstream::commsTypes commsType
 ) const
 {
-    this->patch().patchInternalField(psiInternal, scalarSendBuf_);
+    //this->patch().patchInternalField(psiInternal, scalarSendBuf_);
+
+    const labelUList& faceCells = lduAddr.patchAddr(patchId);
+
+    scalarSendBuf_.setSize(this->patch().size());
+    forAll(scalarSendBuf_, facei)
+    {
+        scalarSendBuf_[facei] = psiInternal[faceCells[facei]];
+    }
 
     if
     (
@@ -374,6 +384,8 @@ void Foam::processorFvPatchField<Type>::updateInterfaceMatrix
 (
     solveScalarField& result,
     const bool add,
+    const lduAddressing& lduAddr,
+    const label patchId,
     const solveScalarField&,
     const scalarField& coeffs,
     const direction cmpt,
@@ -385,6 +397,8 @@ void Foam::processorFvPatchField<Type>::updateInterfaceMatrix
         return;
     }
 
+    const labelUList& faceCells = lduAddr.patchAddr(patchId);
+
     if
     (
         commsType == Pstream::commsTypes::nonBlocking
@@ -412,7 +426,14 @@ void Foam::processorFvPatchField<Type>::updateInterfaceMatrix
         }
 
         // Multiply the field by coefficients and add into the result
-        this->addToInternalField(result, !add, coeffs, scalarReceiveBuf_);
+        this->addToInternalField
+        (
+            result,
+            !add,
+            faceCells,
+            coeffs,
+            scalarReceiveBuf_
+        );
     }
     else
     {
@@ -432,7 +453,7 @@ void Foam::processorFvPatchField<Type>::updateInterfaceMatrix
         }
 
         // Multiply the field by coefficients and add into the result
-        this->addToInternalField(result, !add, coeffs, pnf);
+        this->addToInternalField(result, !add, faceCells, coeffs, pnf);
     }
 
     const_cast<processorFvPatchField<Type>&>(*this).updatedMatrix() = true;
@@ -444,12 +465,21 @@ void Foam::processorFvPatchField<Type>::initInterfaceMatrixUpdate
 (
     Field<Type>&,
     const bool add,
+    const lduAddressing& lduAddr,
+    const label patchId,
     const Field<Type>& psiInternal,
     const scalarField&,
     const Pstream::commsTypes commsType
 ) const
 {
-    this->patch().patchInternalField(psiInternal, sendBuf_);
+    sendBuf_.setSize(this->patch().size());
+
+    const labelUList& faceCells = lduAddr.patchAddr(patchId);
+
+    forAll(sendBuf_, facei)
+    {
+        sendBuf_[facei] = psiInternal[faceCells[facei]];
+    }
 
     if
     (
@@ -504,6 +534,8 @@ void Foam::processorFvPatchField<Type>::updateInterfaceMatrix
 (
     Field<Type>& result,
     const bool add,
+    const lduAddressing& lduAddr,
+    const label patchId,
     const Field<Type>&,
     const scalarField& coeffs,
     const Pstream::commsTypes commsType
@@ -514,6 +546,8 @@ void Foam::processorFvPatchField<Type>::updateInterfaceMatrix
         return;
     }
 
+    const labelUList& faceCells = lduAddr.patchAddr(patchId);
+
     if
     (
         commsType == Pstream::commsTypes::nonBlocking
@@ -539,7 +573,7 @@ void Foam::processorFvPatchField<Type>::updateInterfaceMatrix
         transformCoupleField(receiveBuf_);
 
         // Multiply the field by coefficients and add into the result
-        this->addToInternalField(result, !add, coeffs, receiveBuf_);
+        this->addToInternalField(result, !add, faceCells, coeffs, receiveBuf_);
     }
     else
     {
@@ -552,7 +586,7 @@ void Foam::processorFvPatchField<Type>::updateInterfaceMatrix
         transformCoupleField(pnf);
 
         // Multiply the field by coefficients and add into the result
-        this->addToInternalField(result, !add, coeffs, pnf);
+        this->addToInternalField(result, !add, faceCells, coeffs, pnf);
     }
 
     const_cast<processorFvPatchField<Type>&>(*this).updatedMatrix() = true;
diff --git a/src/finiteVolume/fields/fvPatchFields/constraint/processor/processorFvPatchField.H b/src/finiteVolume/fields/fvPatchFields/constraint/processor/processorFvPatchField.H
index 1fddc08487a3e9f4ad860360b905c985b8423cbd..cb710100014e0120faf82b2c9cba0d18c66c2a09 100644
--- a/src/finiteVolume/fields/fvPatchFields/constraint/processor/processorFvPatchField.H
+++ b/src/finiteVolume/fields/fvPatchFields/constraint/processor/processorFvPatchField.H
@@ -214,6 +214,8 @@ public:
             (
                 solveScalarField& result,
                 const bool add,
+                const lduAddressing& lduAddr,
+                const label patchId,
                 const solveScalarField& psiInternal,
                 const scalarField& coeffs,
                 const direction cmpt,
@@ -225,6 +227,8 @@ public:
             (
                 solveScalarField& result,
                 const bool add,
+                const lduAddressing& lduAddr,
+                const label patchId,
                 const solveScalarField& psiInternal,
                 const scalarField& coeffs,
                 const direction cmpt,
@@ -236,6 +240,8 @@ public:
             (
                 Field<Type>& result,
                 const bool add,
+                const lduAddressing& lduAddr,
+                const label patchId,
                 const Field<Type>& psiInternal,
                 const scalarField& coeffs,
                 const Pstream::commsTypes commsType
@@ -246,10 +252,13 @@ public:
             (
                 Field<Type>& result,
                 const bool add,
+                const lduAddressing& lduAddr,
+                const label patchId,
                 const Field<Type>& psiInternal,
                 const scalarField& coeffs,
                 const Pstream::commsTypes commsType
             ) const;
+            
 
 
         //- Processor coupled interface functions
diff --git a/src/finiteVolume/fields/fvPatchFields/derived/mappedField/mappedMixedFieldFvPatchField/mappedMixedFieldFvPatchFields.C b/src/finiteVolume/fields/fvPatchFields/derived/mappedField/mappedMixedFieldFvPatchField/mappedMixedFieldFvPatchFields.C
index e2ff66464acf28be5fbfb794239447cbf68ab1f2..6eed3da77bc1c5ca2510d3963df3da1237e1cb38 100644
--- a/src/finiteVolume/fields/fvPatchFields/derived/mappedField/mappedMixedFieldFvPatchField/mappedMixedFieldFvPatchFields.C
+++ b/src/finiteVolume/fields/fvPatchFields/derived/mappedField/mappedMixedFieldFvPatchField/mappedMixedFieldFvPatchFields.C
@@ -2,8 +2,10 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2019 OpenCFD Ltd.
+    \\  /    A nd           | www.openfoam.com
      \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2019 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
diff --git a/src/finiteVolume/fields/fvPatchFields/derived/mappedField/mappedMixedFieldFvPatchField/mappedMixedFieldFvPatchFields.H b/src/finiteVolume/fields/fvPatchFields/derived/mappedField/mappedMixedFieldFvPatchField/mappedMixedFieldFvPatchFields.H
index 78d5da421114416de71cf29b3ed6b6dc53bcadd6..d50ea5fdd1beec335ac32c16b2261a6587a41db2 100644
--- a/src/finiteVolume/fields/fvPatchFields/derived/mappedField/mappedMixedFieldFvPatchField/mappedMixedFieldFvPatchFields.H
+++ b/src/finiteVolume/fields/fvPatchFields/derived/mappedField/mappedMixedFieldFvPatchField/mappedMixedFieldFvPatchFields.H
@@ -2,8 +2,10 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2019 OpenCFD Ltd.
+    \\  /    A nd           | www.openfoam.com
      \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2019 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
diff --git a/src/finiteVolume/fields/fvPatchFields/derived/mappedMixed/mappedMixedFvPatchFields.C b/src/finiteVolume/fields/fvPatchFields/derived/mappedMixed/mappedMixedFvPatchFields.C
index 609f37bf4d58fbcf4cd3bfeafde49ff4480ce5c1..e7b8d4c915be45911e38ccb6ada992427a9a5175 100644
--- a/src/finiteVolume/fields/fvPatchFields/derived/mappedMixed/mappedMixedFvPatchFields.C
+++ b/src/finiteVolume/fields/fvPatchFields/derived/mappedMixed/mappedMixedFvPatchFields.C
@@ -2,8 +2,10 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2020 OpenCFD Ltd.
+    \\  /    A nd           | www.openfoam.com
      \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2020 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
diff --git a/src/finiteVolume/fields/fvPatchFields/derived/mappedMixed/mappedMixedFvPatchFields.H b/src/finiteVolume/fields/fvPatchFields/derived/mappedMixed/mappedMixedFvPatchFields.H
index 2f7de22809c0f9d9ce7188073d2683e7656aa6d3..66febbb2ef6107c8702a09b07179cee44323ae4b 100644
--- a/src/finiteVolume/fields/fvPatchFields/derived/mappedMixed/mappedMixedFvPatchFields.H
+++ b/src/finiteVolume/fields/fvPatchFields/derived/mappedMixed/mappedMixedFvPatchFields.H
@@ -2,8 +2,10 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2019 OpenCFD Ltd.
+    \\  /    A nd           | www.openfoam.com
      \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2019 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
diff --git a/src/finiteVolume/fields/fvPatchFields/fvPatchField/fvPatchField.C b/src/finiteVolume/fields/fvPatchFields/fvPatchField/fvPatchField.C
index d967a8ad9cc2e920176b60beb619763091a8a96c..ba1ab519c3c3742e3b3aadf5df3956674ae8f1b3 100644
--- a/src/finiteVolume/fields/fvPatchFields/fvPatchField/fvPatchField.C
+++ b/src/finiteVolume/fields/fvPatchFields/fvPatchField/fvPatchField.C
@@ -46,7 +46,8 @@ Foam::fvPatchField<Type>::fvPatchField
     internalField_(iF),
     updated_(false),
     manipulatedMatrix_(false),
-    patchType_(word::null)
+    patchType_(word::null),
+    useImplicit_(false)
 {}
 
 
@@ -63,7 +64,8 @@ Foam::fvPatchField<Type>::fvPatchField
     internalField_(iF),
     updated_(false),
     manipulatedMatrix_(false),
-    patchType_(word::null)
+    patchType_(word::null),
+    useImplicit_(false)
 {}
 
 
@@ -80,7 +82,8 @@ Foam::fvPatchField<Type>::fvPatchField
     internalField_(iF),
     updated_(false),
     manipulatedMatrix_(false),
-    patchType_(patchType)
+    patchType_(patchType),
+    useImplicit_(false)
 {}
 
 
@@ -97,7 +100,8 @@ Foam::fvPatchField<Type>::fvPatchField
     internalField_(iF),
     updated_(false),
     manipulatedMatrix_(false),
-    patchType_(word::null)
+    patchType_(word::null),
+    useImplicit_(false)
 {}
 
 
@@ -115,7 +119,8 @@ Foam::fvPatchField<Type>::fvPatchField
     internalField_(iF),
     updated_(false),
     manipulatedMatrix_(false),
-    patchType_(dict.getOrDefault<word>("patchType", word::null))
+    patchType_(dict.getOrDefault<word>("patchType", word::null)),
+    useImplicit_(dict.getOrDefault<bool>("useImplicit", false))
 {
     if (valueRequired)
     {
@@ -150,7 +155,8 @@ Foam::fvPatchField<Type>::fvPatchField
     internalField_(iF),
     updated_(false),
     manipulatedMatrix_(false),
-    patchType_(ptf.patchType_)
+    patchType_(ptf.patchType_),
+    useImplicit_(ptf.useImplicit_)
 {
     // For unmapped faces set to internal field value (zero-gradient)
     if (notNull(iF) && mapper.hasUnmapped())
@@ -172,7 +178,8 @@ Foam::fvPatchField<Type>::fvPatchField
     internalField_(ptf.internalField_),
     updated_(false),
     manipulatedMatrix_(false),
-    patchType_(ptf.patchType_)
+    patchType_(ptf.patchType_),
+    useImplicit_(ptf.useImplicit_)
 {}
 
 
@@ -188,7 +195,8 @@ Foam::fvPatchField<Type>::fvPatchField
     internalField_(iF),
     updated_(false),
     manipulatedMatrix_(false),
-    patchType_(ptf.patchType_)
+    patchType_(ptf.patchType_),
+    useImplicit_(ptf.useImplicit_)
 {}
 
 
@@ -360,10 +368,23 @@ void Foam::fvPatchField<Type>::manipulateMatrix
 }
 
 
+template<class Type>
+void Foam::fvPatchField<Type>::manipulateMatrix
+(
+    fvMatrix<Type>& matrix,
+    const label iMatrix,
+    const direction cmp
+)
+{
+    manipulatedMatrix_ = true;
+}
+
+
 template<class Type>
 void Foam::fvPatchField<Type>::write(Ostream& os) const
 {
     os.writeEntry("type", type());
+    os.writeEntryIfDifferent<bool>("useImplicit", false, useImplicit_);
 
     if (patchType_.size())
     {
@@ -585,6 +606,6 @@ Foam::Ostream& Foam::operator<<(Ostream& os, const fvPatchField<Type>& ptf)
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
-    #include "fvPatchFieldNew.C"
+#include "fvPatchFieldNew.C"
 
 // ************************************************************************* //
diff --git a/src/finiteVolume/fields/fvPatchFields/fvPatchField/fvPatchField.H b/src/finiteVolume/fields/fvPatchFields/fvPatchField/fvPatchField.H
index 9e8ee684417e33930454687a03defcb1110d8445..0532940ca5f7863a96b324152a3a7c1ad278fd3f 100644
--- a/src/finiteVolume/fields/fvPatchFields/fvPatchField/fvPatchField.H
+++ b/src/finiteVolume/fields/fvPatchFields/fvPatchField/fvPatchField.H
@@ -57,24 +57,17 @@ SourceFiles
 namespace Foam
 {
 
-// Forward declaration of classes
+// Forward Declarations
 
 class objectRegistry;
 class dictionary;
 class fvPatchFieldMapper;
 class volMesh;
 
+template<class Type> class fvPatchField;
+template<class Type> class calculatedFvPatchField;
+template<class Type> class fvMatrix;
 
-// Forward declaration of friend functions and operators
-
-template<class Type>
-class fvPatchField;
-
-template<class Type>
-class calculatedFvPatchField;
-
-template<class Type>
-class fvMatrix;
 
 template<class Type>
 Ostream& operator<<(Ostream&, const fvPatchField<Type>&);
@@ -110,6 +103,9 @@ class fvPatchField
         //  patch type as 'patchType'
         word patchType_;
 
+        //- Use implicit formulation
+        bool useImplicit_;
+
 
 public:
 
@@ -306,7 +302,22 @@ public:
     virtual ~fvPatchField<Type>() = default;
 
 
-    // Member functions
+    // Member Functions
+
+        // Implicit Functions
+
+            //- Use implicit formulation for coupled patches only
+            bool useImplicit() const
+            {
+                return useImplicit_;
+            }
+
+            //- Non-const access to useImplicit
+            bool& useImplicit()
+            {
+                return useImplicit_;
+            }
+
 
         // Attributes
 
@@ -382,7 +393,6 @@ public:
                 return manipulatedMatrix_;
             }
 
-
         // Mapping functions
 
             //- Map (and resize as needed) from self given a mapping object
@@ -527,6 +537,14 @@ public:
                 const scalarField& weights
             );
 
+            //- Manipulate fvMatrix
+            virtual void manipulateMatrix
+            (
+                fvMatrix<Type>& matrix,
+                const label iMatrix,
+                const direction cmp
+            );
+
 
         // I-O
 
diff --git a/src/finiteVolume/fvMatrices/fvMatrix/fvMatrix.C b/src/finiteVolume/fvMatrices/fvMatrix/fvMatrix.C
index 8b06e2812658373a5721c52c4bf820a2319fef23..6ad6ee6abcfaccc1f6677776604741d99154968a 100644
--- a/src/finiteVolume/fvMatrices/fvMatrix/fvMatrix.C
+++ b/src/finiteVolume/fvMatrices/fvMatrix/fvMatrix.C
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2017 OpenFOAM Foundation
-    Copyright (C) 2016-2020 OpenCFD Ltd.
+    Copyright (C) 2016-2021 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -35,6 +35,12 @@ License
 #include "UniformList.H"
 #include "demandDrivenData.H"
 
+#include "cyclicFvPatchField.H"
+#include "cyclicAMIFvPatchField.H"
+#include "cyclicACMIFvPatchField.H"
+
+#include "processorLduInterfaceField.H"
+
 // * * * * * * * * * * * * Protected Member Functions  * * * * * * * * * * * //
 
 template<class Type>
@@ -120,14 +126,24 @@ void Foam::fvMatrix<Type>::addBoundaryDiag
     const direction solveCmpt
 ) const
 {
-    forAll(internalCoeffs_, patchi)
+    for (label fieldi = 0; fieldi < nMatrices(); fieldi++)
     {
-        addToInternalField
-        (
-            lduAddr().patchAddr(patchi),
-            internalCoeffs_[patchi].component(solveCmpt),
-            diag
-        );
+        const auto& bpsi = this->psi(fieldi).boundaryField();
+
+        forAll(bpsi, ptfi)
+        {
+            const label patchi = globalPatchID(fieldi, ptfi);
+
+            if (patchi != -1)
+            {
+                addToInternalField
+                (
+                    lduAddr().patchAddr(patchi),
+                    internalCoeffs_[patchi].component(solveCmpt),
+                    diag
+                );
+            }
+        }
     }
 }
 
@@ -135,14 +151,23 @@ void Foam::fvMatrix<Type>::addBoundaryDiag
 template<class Type>
 void Foam::fvMatrix<Type>::addCmptAvBoundaryDiag(scalarField& diag) const
 {
-    forAll(internalCoeffs_, patchi)
+    for (label fieldi = 0; fieldi < nMatrices(); fieldi++)
     {
-        addToInternalField
-        (
-            lduAddr().patchAddr(patchi),
-            cmptAv(internalCoeffs_[patchi]),
-            diag
-        );
+        const auto& bpsi = this->psi(fieldi).boundaryField();
+
+        forAll(bpsi, ptfi)
+        {
+            const label patchi = globalPatchID(fieldi, ptfi);
+            if (patchi != -1)
+            {
+                addToInternalField
+                (
+                    lduAddr().patchAddr(patchi),
+                    cmptAv(internalCoeffs_[patchi]),
+                    diag
+                );
+            }
+        }
     }
 }
 
@@ -154,25 +179,42 @@ void Foam::fvMatrix<Type>::addBoundarySource
     const bool couples
 ) const
 {
-    forAll(psi_.boundaryField(), patchi)
+    for (label fieldi = 0; fieldi < nMatrices(); fieldi++)
     {
-        const fvPatchField<Type>& ptf = psi_.boundaryField()[patchi];
-        const Field<Type>& pbc = boundaryCoeffs_[patchi];
+        const auto& bpsi = this->psi(fieldi).boundaryField();
 
-        if (!ptf.coupled())
-        {
-            addToInternalField(lduAddr().patchAddr(patchi), pbc, source);
-        }
-        else if (couples)
+        forAll(bpsi, ptfi)
         {
-            const tmp<Field<Type>> tpnf = ptf.patchNeighbourField();
-            const Field<Type>& pnf = tpnf();
+            const fvPatchField<Type>& ptf = bpsi[ptfi];
 
-            const labelUList& addr = lduAddr().patchAddr(patchi);
+            const label patchi = globalPatchID(fieldi, ptfi);
 
-            forAll(addr, facei)
+            if (patchi != -1)
             {
-                source[addr[facei]] += cmptMultiply(pbc[facei], pnf[facei]);
+                const Field<Type>& pbc = boundaryCoeffs_[patchi];
+
+                if (!ptf.coupled())
+                {
+                    addToInternalField
+                    (
+                        lduAddr().patchAddr(patchi),
+                        pbc,
+                        source
+                    );
+                }
+                else if (couples)
+                {
+                    const tmp<Field<Type>> tpnf = ptf.patchNeighbourField();
+                    const Field<Type>& pnf = tpnf();
+
+                    const labelUList& addr = lduAddr().patchAddr(patchi);
+
+                    forAll(addr, facei)
+                    {
+                        source[addr[facei]] +=
+                            cmptMultiply(pbc[facei], pnf[facei]);
+                    }
+                }
             }
         }
     }
@@ -261,8 +303,31 @@ void Foam::fvMatrix<Type>::setValuesFromList
 }
 
 
+template<class Type>
+Foam::label Foam::fvMatrix<Type>::checkImplicit(const label fieldI)
+{
+    const auto& bpsi = this->psi(fieldI).boundaryField();
+
+    label id = -1;
+    forAll (bpsi, patchI)
+    {
+        if (bpsi[patchI].useImplicit())
+        {
+            id += (label(2) << patchI);
+        }
+    }
+    if (id > 0)
+    {
+        lduAssemblyName_ = word("lduAssembly") + name(id);
+        useImplicit_ = true;
+    }
+    return id;
+}
+
+
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
+
 template<class Type>
 Foam::fvMatrix<Type>::fvMatrix
 (
@@ -272,6 +337,9 @@ Foam::fvMatrix<Type>::fvMatrix
 :
     lduMatrix(psi.mesh()),
     psi_(psi),
+    useImplicit_(false),
+    lduAssemblyName_(word::null),
+    nMatrix_(0),
     dimensions_(ds),
     source_(psi.size(), Zero),
     internalCoeffs_(psi.mesh().boundary().size()),
@@ -281,7 +349,8 @@ Foam::fvMatrix<Type>::fvMatrix
     DebugInFunction
         << "Constructing fvMatrix<Type> for field " << psi_.name() << endl;
 
-    // Initialise coupling coefficients
+    checkImplicit();
+
     forAll(psi.mesh().boundary(), patchi)
     {
         internalCoeffs_.set
@@ -305,11 +374,8 @@ Foam::fvMatrix<Type>::fvMatrix
         );
     }
 
-    // Update the boundary coefficients of psi without changing its event No.
-    auto& psiRef =
-        const_cast<GeometricField<Type, fvPatchField, volMesh>&>(psi_);
-
-    const label currentStatePsi = psiRef.eventNo();
+    auto& psiRef = this->psi(0);
+    label currentStatePsi = psiRef.eventNo();
     psiRef.boundaryFieldRef().updateCoeffs();
     psiRef.eventNo() = currentStatePsi;
 }
@@ -321,6 +387,9 @@ Foam::fvMatrix<Type>::fvMatrix(const fvMatrix<Type>& fvm)
     refCount(),
     lduMatrix(fvm),
     psi_(fvm.psi_),
+    useImplicit_(fvm.useImplicit_),
+    lduAssemblyName_(fvm.lduAssemblyName_),
+    nMatrix_(fvm.nMatrix_),
     dimensions_(fvm.dimensions_),
     source_(fvm.source_),
     internalCoeffs_(fvm.internalCoeffs_),
@@ -350,6 +419,9 @@ Foam::fvMatrix<Type>::fvMatrix(const tmp<fvMatrix<Type>>& tfvm)
         tfvm.isTmp()
     ),
     psi_(tfvm().psi_),
+    useImplicit_(tfvm().useImplicit_),
+    lduAssemblyName_(tfvm().lduAssemblyName_),
+    nMatrix_(tfvm().nMatrix_),
     dimensions_(tfvm().dimensions_),
     source_
     (
@@ -401,15 +473,21 @@ Foam::fvMatrix<Type>::fvMatrix
 :
     lduMatrix(psi.mesh()),
     psi_(psi),
+    useImplicit_(false),
+    lduAssemblyName_(word::null),
+    nMatrix_(0),
     dimensions_(is),
     source_(is),
     internalCoeffs_(psi.mesh().boundary().size()),
     boundaryCoeffs_(psi.mesh().boundary().size()),
     faceFluxCorrectionPtr_(nullptr)
 {
+
     DebugInFunction
         << "Constructing fvMatrix<Type> for field " << psi_.name() << endl;
 
+    checkImplicit();
+
     // Initialise coupling coefficients
     forAll(psi.mesh().boundary(), patchi)
     {
@@ -455,11 +533,519 @@ Foam::fvMatrix<Type>::~fvMatrix()
         << "Destroying fvMatrix<Type> for field " << psi_.name() << endl;
 
     deleteDemandDrivenData(faceFluxCorrectionPtr_);
+    subMatrices_.clear();
 }
 
 
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
+template<class Type>
+void Foam::fvMatrix<Type>::setInterfaces
+(
+    lduInterfaceFieldPtrsList& interfaces,
+    PtrDynList<lduInterfaceField>& newInterfaces
+)
+{
+    interfaces.setSize(internalCoeffs_.size());
+    for (label fieldi = 0; fieldi < nMatrices(); fieldi++)
+    {
+        const auto& bpsi = this->psi(fieldi).boundaryField();
+        lduInterfaceFieldPtrsList fieldInterfaces(bpsi.scalarInterfaces());
+
+        forAll (fieldInterfaces, patchi)
+        {
+            label globalPatchID = lduMeshPtr()->patchMap()[fieldi][patchi];
+
+            if (globalPatchID != -1)
+            {
+                if (fieldInterfaces.set(patchi))
+                {
+                    if (isA<cyclicLduInterfaceField>(bpsi[patchi]))
+                    {
+                        newInterfaces.append
+                        (
+                            new cyclicFvPatchField<Type>
+                            (
+                                refCast<const fvPatch>
+                                (
+                                    lduMeshPtr()->interfaces()[globalPatchID]
+                                ),
+                                bpsi[patchi].internalField()
+                            )
+                        );
+                        interfaces.set(globalPatchID, &newInterfaces.last());
+
+                    }
+                    else if (isA<cyclicAMILduInterfaceField>(bpsi[patchi]))
+                    {
+                        newInterfaces.append
+                        (
+                            new cyclicAMIFvPatchField<Type>
+                            (
+                                refCast<const fvPatch>
+                                (
+                                    lduMeshPtr()->interfaces()[globalPatchID]
+                                ),
+                                bpsi[patchi].internalField()
+                            )
+                        );
+                        interfaces.set(globalPatchID, &newInterfaces.last());
+                    }
+                    else if (isA<cyclicACMILduInterfaceField>(bpsi[patchi]))
+                    {
+                        newInterfaces.append
+                        (
+                            new cyclicACMIFvPatchField<Type>
+                            (
+                                refCast<const fvPatch>
+                                (
+                                    lduMeshPtr()->interfaces()[globalPatchID]
+                                ),
+                                bpsi[patchi].internalField()
+                            )
+                        );
+                        interfaces.set(globalPatchID, &newInterfaces.last());
+                    }
+                    else
+                    {
+                        interfaces.set(globalPatchID, &fieldInterfaces[patchi]);
+                    }
+                }
+            }
+        }
+    }
+}
+
+
+template<class Type>
+void Foam::fvMatrix<Type>::mapContributions
+(
+    label fieldi,
+    const FieldField<Field, Type>& fluxContrib,
+    FieldField<Field, Type>& contrib,
+    bool internal
+) const
+{
+    const lduPrimitiveMeshAssembly* ptr = lduMeshPtr();
+
+    const labelList& patchMap = ptr->patchMap()[fieldi];
+
+    forAll(contrib, patchi)
+    {
+        const label globalPtchId = patchMap[patchi];
+
+        if (globalPtchId != -1)
+        {
+            // Cache contrib before overwriting
+            const Field<Type> saveContrib(fluxContrib[globalPtchId]);
+            contrib[patchi].setSize(psi_.boundaryField()[patchi].size()),
+            contrib[patchi] = pTraits<Type>::zero;
+
+            if (internal)
+            {
+                contrib[patchi] =
+                    cmptMultiply
+                    (
+                        saveContrib,
+                        psi_.boundaryField()[patchi].patchInternalField()
+                    );
+            }
+            else
+            {
+                if (this->psi(fieldi).boundaryField()[patchi].coupled())
+                {
+                    contrib[patchi] =
+                        cmptMultiply
+                        (
+                            saveContrib,
+                            psi_.boundaryField()[patchi].patchNeighbourField()
+                        );
+                }
+            }
+        }
+        else if (globalPtchId == -1)
+        {
+            const polyPatch& pp =
+                this->psi(fieldi).mesh().boundaryMesh()[patchi];
+
+            if (pp.masterImplicit())
+            {
+                label virtualPatch =
+                    ptr->patchLocalToGlobalMap()[fieldi][patchi];
+
+                const label nbrPatchId = pp.neighbPolyPatchID();
+
+                // Copy contrib before overwriting
+                const Field<Type> saveContrib(fluxContrib[virtualPatch]);
+
+                Field<Type>& coeffs = contrib[patchi];
+                Field<Type>& nbrCoeffs = contrib[nbrPatchId];
+
+                coeffs.setSize(psi_.boundaryField()[patchi].size());
+                nbrCoeffs.setSize(psi_.boundaryField()[nbrPatchId].size());
+
+                coeffs = pTraits<Type>::zero;
+                nbrCoeffs = pTraits<Type>::zero;
+
+                // nrb cells
+                const labelList& nbrCellIds =
+                    ptr->cellBoundMap()[fieldi][patchi];
+
+                const labelList& cellIds =
+                    ptr->cellBoundMap()[fieldi][nbrPatchId];
+
+                const GeometricField<Type, fvPatchField, volMesh>& psi =
+                    this->psi(fieldi);
+
+                forAll(saveContrib, subFaceI)
+                {
+                    const label faceId =
+                        ptr->facePatchFaceMap()[fieldi][patchi][subFaceI];
+                    const label nbrFaceId =
+                        ptr->facePatchFaceMap()[fieldi][nbrPatchId][subFaceI];
+
+                    const label nbrCellId = nbrCellIds[subFaceI];
+                    const label cellId = cellIds[subFaceI];
+
+                    if (internal)
+                    {
+                        coeffs[faceId] +=
+                            cmptMultiply(saveContrib[subFaceI], psi[cellId]);
+
+                        nbrCoeffs[nbrFaceId] +=
+                            cmptMultiply(saveContrib[subFaceI], psi[nbrCellId]);
+                    }
+                    else //boundary
+                    {
+                        coeffs[faceId] +=
+                            cmptMultiply(saveContrib[subFaceI], psi[nbrCellId]);
+
+                        nbrCoeffs[nbrFaceId] +=
+                            cmptMultiply(saveContrib[subFaceI], psi[cellId]);
+                    }
+                }
+            }
+        }
+    }
+}
+
+
+template<class Type>
+void Foam::fvMatrix<Type>::setBounAndInterCoeffs()
+{
+    // If it is a multi-fvMatrix needs correct internalCoeffs and
+    // boundaryCoeffs size
+    if (nMatrix_ > 0)
+    {
+        label interfaceI(0);
+        for (label fieldi = 0; fieldi < nMatrices(); fieldi++)
+        {
+            const auto& psi = this->psi(fieldi);
+
+            forAll(psi.mesh().boundary(), patchi)
+            {
+                interfaceI++;
+            }
+        }
+        internalCoeffs_.setSize(interfaceI);
+        boundaryCoeffs_.setSize(interfaceI);
+
+        interfaceI = 0;
+        for (label fieldi = 0; fieldi < nMatrices(); fieldi++)
+        {
+            const auto& psi = this->psi(fieldi);
+
+            forAll(psi.mesh().boundary(), patchi)
+            {
+                internalCoeffs_.set
+                (
+                    interfaceI,
+                    new Field<Type>
+                    (
+                        psi.mesh().boundary()[patchi].size(),
+                        Zero
+                    )
+                );
+
+                boundaryCoeffs_.set
+                (
+                    interfaceI,
+                    new Field<Type>
+                    (
+                        psi.mesh().boundary()[patchi].size(),
+                        Zero
+                    )
+                );
+                interfaceI++;
+            }
+        }
+    }
+
+    for (label i=0; i < nMatrices(); ++i)
+    {
+        const auto& bpsi = this->psi(i).boundaryField();
+
+        // Cache to-be implicit internal/boundary
+        FieldField<Field, Type> boundary(bpsi.size());
+        FieldField<Field, Type> internal(bpsi.size());
+
+        label implicit = 0;
+        forAll(bpsi, patchI)
+        {
+            label globalPatchId = lduMeshPtr()->patchMap()[i][patchI];
+            if (globalPatchId == -1)
+            {
+                boundary.set
+                (
+                    implicit,
+                    matrix(i).boundaryCoeffs()[patchI].clone()
+                );
+                internal.set
+                (
+                    implicit,
+                    matrix(i).internalCoeffs()[patchI].clone()
+                );
+                implicit++;
+            }
+        }
+
+        // Update non-implicit patches (re-order)
+        forAll(bpsi, patchI)
+        {
+            label globalPatchId = lduMeshPtr()->patchMap()[i][patchI];
+            if (globalPatchId != -1)
+            {
+                if (matrix(i).internalCoeffs().set(patchI))
+                {
+                    internalCoeffs_.set
+                    (
+                        globalPatchId,
+                        matrix(i).internalCoeffs()[patchI].clone()
+                    );
+                }
+
+                if (matrix(i).boundaryCoeffs().set(patchI))
+                {
+                    boundaryCoeffs_.set
+                    (
+                        globalPatchId,
+                        matrix(i).boundaryCoeffs()[patchI].clone()
+                    );
+                }
+            }
+        }
+
+        // Store implicit patches at the end of the list
+        implicit = 0;
+        forAll(bpsi, patchI)
+        {
+            label globalPatchId = lduMeshPtr()->patchMap()[i][patchI];
+            if (globalPatchId == -1)
+            {
+                const label implicitPatchId =
+                     lduMeshPtr()->patchLocalToGlobalMap()[i][patchI];
+
+                internalCoeffs_.set
+                (
+                    implicitPatchId, internal[implicit].clone()
+                );
+                boundaryCoeffs_.set
+                (
+                    implicitPatchId, boundary[implicit].clone()
+                );
+
+                implicit++;
+            }
+        }
+    }
+
+//    forAll(internalCoeffs_, patchI)
+//    {
+//         DebugVar(patchI)
+//         DebugVar(internalCoeffs_[patchI])
+//         DebugVar(boundaryCoeffs_[patchI])
+//    }
+}
+
+
+template<class Type>
+void Foam::fvMatrix<Type>::manipulateMatrix(direction cmp)
+{
+    for (label i=0; i < nMatrices(); ++i)
+    {
+        forAll(psi(i).boundaryField(), patchI)
+        {
+            label globalPatchId = lduMeshPtr()->patchMap()[i][patchI];
+
+            if (globalPatchId == -1)
+            {
+                psi(i).boundaryFieldRef()[patchI].manipulateMatrix
+                (
+                    *this,
+                    i,
+                    cmp
+                );
+            }
+        }
+    }
+}
+
+
+template<class Type>
+void Foam::fvMatrix<Type>::transferFvMatrixCoeffs()
+{
+    const labelListList& faceMap = lduMeshPtr()->faceMap();
+    const labelList& cellMap = lduMeshPtr()->cellOffsets();
+
+    label newFaces = lduMeshPtr()->lduAddr().upperAddr().size();
+    label newCells = lduMeshPtr()->lduAddr().size();
+
+    scalarField lowerAssemb(newFaces, Zero);
+    scalarField upperAssemb(newFaces, Zero);
+    scalarField diagAssemb(newCells, Zero);
+    Field<Type> sourceAssemb(newCells, Zero);
+
+    bool asymmetricAssemby = false;
+    for (label i=0; i < nMatrices(); ++i)
+    {
+        if (matrix(i).asymmetric())
+        {
+            asymmetricAssemby = true;
+        }
+    }
+    // Move append contents into intermediate list
+    for (label i=0; i < nMatrices(); ++i)
+    {
+        if (asymmetricAssemby)
+        {
+            const scalarField lowerSub(matrix(i).lower());
+            forAll(lowerSub, facei)
+            {
+                lowerAssemb[faceMap[i][facei]] = lowerSub[facei];
+            }
+        }
+
+        const scalarField upperSub(matrix(i).upper());
+        const scalarField diagSub(matrix(i).diag());
+        const Field<Type> sourceSub(matrix(i).source());
+
+        forAll(upperSub, facei)
+        {
+            upperAssemb[faceMap[i][facei]] = upperSub[facei];
+        }
+
+        forAll(diagSub, celli)
+        {
+            const label globalCelli = cellMap[i] + celli;
+            diagAssemb[globalCelli] = diagSub[celli];
+            sourceAssemb[globalCelli] = sourceSub[celli];
+        }
+    }
+
+    if (asymmetricAssemby)
+    {
+        lower().setSize(newFaces, Zero);
+        lower() = lowerAssemb;
+    }
+    upper().setSize(newFaces, Zero);
+    upper() = upperAssemb;
+
+    diag().setSize(newCells, Zero);
+    diag() = diagAssemb;
+
+    source().setSize(newCells, Zero);
+    source() = sourceAssemb;
+}
+
+
+template<class Type>
+Foam::lduPrimitiveMeshAssembly* Foam::fvMatrix<Type>::lduMeshPtr()
+{
+    const lduPrimitiveMeshAssembly* lduAssemMeshPtr =
+        psi_.mesh().thisDb().objectRegistry::template findObject
+        <
+            lduPrimitiveMeshAssembly
+        > (lduAssemblyName_);
+
+    return const_cast<lduPrimitiveMeshAssembly*>(lduAssemMeshPtr);
+}
+
+
+template<class Type>
+const Foam::lduPrimitiveMeshAssembly* Foam::fvMatrix<Type>::lduMeshPtr() const
+{
+    return
+    (
+        psi_.mesh().thisDb().objectRegistry::template cfindObject
+        <
+            lduPrimitiveMeshAssembly
+        > (lduAssemblyName_)
+    );
+}
+
+
+template<class Type>
+void Foam::fvMatrix<Type>::createOrUpdateLduPrimitiveAssembly()
+{
+    lduPrimitiveMeshAssembly* ptr = lduMeshPtr();
+
+    IOobject io
+    (
+        lduAssemblyName_,
+        psi_.mesh().time().timeName(),
+        psi_.mesh(),
+        IOobject::NO_READ,
+        IOobject::NO_WRITE
+    );
+
+    UPtrList<lduMesh> uMeshPtr(nMatrices());
+
+    UPtrList<GeometricField<Type, fvPatchField, volMesh>>
+        uFieldPtr(nMatrices());
+
+    for (label fieldi = 0; fieldi < nMatrices(); fieldi++)
+    {
+        const fvMesh& meshi = this->psi(fieldi).mesh();
+        uMeshPtr.set
+        (
+            fieldi,
+            &const_cast<fvMesh&>(meshi)
+        );
+        uFieldPtr.set(fieldi, &this->psi(fieldi));
+    }
+
+    if (!ptr)
+    {
+        lduPrimitiveMeshAssembly* lduAssemMeshPtr =
+            new lduPrimitiveMeshAssembly(io, uMeshPtr);
+
+        lduAssemMeshPtr->store();
+        lduAssemMeshPtr->update(uFieldPtr);
+
+        Info
+            << "Creating lduPrimitiveAssembly: " << lduAssemblyName_ << endl;
+    }
+    else if
+    (
+        psi_.mesh().changing() && !psi_.mesh().upToDatePoints(*ptr)
+    )
+    {
+        // Clear losortPtr_, ownerStartPtr_, losortStartPtr_
+        ptr->lduAddr().clearOut();
+        ptr->update(uFieldPtr);
+        psi_.mesh().setUpToDatePoints(*ptr);
+
+        Info
+            << "Updating lduPrimitiveAssembly: " << lduAssemblyName_ << endl;
+    }
+    else
+    {
+        Info
+            << "Using lduPrimitiveAssembly: " << lduAssemblyName_ << endl;
+    }
+}
+
+
 template<class Type>
 void Foam::fvMatrix<Type>::setValues
 (
@@ -555,6 +1141,36 @@ void Foam::fvMatrix<Type>::setReferences
 }
 
 
+template<class Type>
+void Foam::fvMatrix<Type>::addFvMatrix(fvMatrix& matrix)
+{
+    subMatrices_.append(matrix.clone());
+    ++nMatrix_;
+
+    if (dimensions_ != matrix.dimensions())
+    {
+        FatalErrorInFunction
+            << "incompatible dimensions for matrix addition "
+            << endl << "    "
+            << "[" << dimensions_  << " ] "
+            << " [" << matrix.dimensions() << " ]"
+            << abort(FatalError);
+    }
+
+    for (label fieldi = 0; fieldi < nMatrices(); fieldi++)
+    {
+        label id = checkImplicit(fieldi);
+        if (id > 0)
+        {
+            break;
+        }
+    }
+
+    internalCoeffs_.setSize(0);
+    boundaryCoeffs_.setSize(0);
+}
+
+
 template<class Type>
 void Foam::fvMatrix<Type>::relax(const scalar alpha)
 {
@@ -903,6 +1519,7 @@ Foam::tmp<Foam::volScalarField> Foam::fvMatrix<Type>::H1() const
 }
 
 
+
 template<class Type>
 Foam::tmp<Foam::GeometricField<Type, Foam::fvsPatchField, Foam::surfaceMesh>>
 Foam::fvMatrix<Type>::
@@ -917,6 +1534,14 @@ flux() const
             << abort(FatalError);
     }
 
+    if (nMatrices() > 1)
+    {
+        FatalErrorInFunction
+            << "Flux requested but " << psi_.name()
+            << " can't handle multiple fvMatrix."
+            << abort(FatalError);
+    }
+
     // construct GeometricField<Type, fvsPatchField, surfaceMesh>
     tmp<GeometricField<Type, fvsPatchField, surfaceMesh>> tfieldFlux
     (
@@ -950,30 +1575,49 @@ flux() const
 
     FieldField<Field, Type> InternalContrib = internalCoeffs_;
 
-    forAll(InternalContrib, patchi)
+    label fieldi = 0;
+    if (!useImplicit_)
     {
-        InternalContrib[patchi] =
-            cmptMultiply
-            (
-                InternalContrib[patchi],
-                psi_.boundaryField()[patchi].patchInternalField()
-            );
+        forAll(InternalContrib, patchi)
+        {
+            InternalContrib[patchi] =
+                cmptMultiply
+                (
+                    InternalContrib[patchi],
+                    psi_.boundaryField()[patchi].patchInternalField()
+                );
+        }
+    }
+    else
+    {
+        FieldField<Field, Type> fluxInternalContrib(internalCoeffs_);
+
+        mapContributions(fieldi, fluxInternalContrib, InternalContrib, true);
     }
 
     FieldField<Field, Type> NeighbourContrib = boundaryCoeffs_;
 
-    forAll(NeighbourContrib, patchi)
+    if (!useImplicit_)
     {
-        if (psi_.boundaryField()[patchi].coupled())
+        forAll(NeighbourContrib, patchi)
         {
-            NeighbourContrib[patchi] =
-                cmptMultiply
-                (
-                    NeighbourContrib[patchi],
-                    psi_.boundaryField()[patchi].patchNeighbourField()
-                );
+            if (psi_.boundaryField()[patchi].coupled())
+            {
+                NeighbourContrib[patchi] =
+                    cmptMultiply
+                    (
+                        NeighbourContrib[patchi],
+                        psi_.boundaryField()[patchi].patchNeighbourField()
+                    );
+            }
         }
     }
+    else
+    {
+        FieldField<Field, Type> fluxBoundaryContrib(boundaryCoeffs_);
+
+        mapContributions(fieldi, fluxBoundaryContrib, NeighbourContrib, false);
+    }
 
     typename GeometricField<Type, fvsPatchField, surfaceMesh>::
         Boundary& ffbf = fieldFlux.boundaryFieldRef();
@@ -981,6 +1625,7 @@ flux() const
     forAll(ffbf, patchi)
     {
         ffbf[patchi] = InternalContrib[patchi] - NeighbourContrib[patchi];
+        //DebugVar(gSum(ffbf[patchi]))
     }
 
     if (faceFluxCorrectionPtr_)
@@ -1039,6 +1684,9 @@ void Foam::fvMatrix<Type>::operator=(const fvMatrix<Type>& fvmv)
             new GeometricField<Type, fvsPatchField, surfaceMesh>
         (*fvmv.faceFluxCorrectionPtr_);
     }
+
+    useImplicit_ = fvmv.useImplicit_;
+    lduAssemblyName_ = fvmv.lduAssemblyName_;
 }
 
 
@@ -1076,6 +1724,10 @@ void Foam::fvMatrix<Type>::operator+=(const fvMatrix<Type>& fvmv)
     internalCoeffs_ += fvmv.internalCoeffs_;
     boundaryCoeffs_ += fvmv.boundaryCoeffs_;
 
+    useImplicit_ = fvmv.useImplicit_;
+    lduAssemblyName_ = fvmv.lduAssemblyName_;
+    nMatrix_ = fvmv.nMatrix_;
+
     if (faceFluxCorrectionPtr_ && fvmv.faceFluxCorrectionPtr_)
     {
         *faceFluxCorrectionPtr_ += *fvmv.faceFluxCorrectionPtr_;
@@ -1110,6 +1762,10 @@ void Foam::fvMatrix<Type>::operator-=(const fvMatrix<Type>& fvmv)
     internalCoeffs_ -= fvmv.internalCoeffs_;
     boundaryCoeffs_ -= fvmv.boundaryCoeffs_;
 
+    useImplicit_ = fvmv.useImplicit_;
+    lduAssemblyName_ = fvmv.lduAssemblyName_;
+    nMatrix_ = fvmv.nMatrix_;
+
     if (faceFluxCorrectionPtr_ && fvmv.faceFluxCorrectionPtr_)
     {
         *faceFluxCorrectionPtr_ -= *fvmv.faceFluxCorrectionPtr_;
diff --git a/src/finiteVolume/fvMatrices/fvMatrix/fvMatrix.H b/src/finiteVolume/fvMatrices/fvMatrix/fvMatrix.H
index c7813d8adfcb9bc66ab6b84390de489167f5fb09..a98074244a3b1b631e7eea5cabc6d8eb8dc35420 100644
--- a/src/finiteVolume/fvMatrices/fvMatrix/fvMatrix.H
+++ b/src/finiteVolume/fvMatrices/fvMatrix/fvMatrix.H
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2017 OpenFOAM Foundation
-    Copyright (C) 2016-2020 OpenCFD Ltd.
+    Copyright (C) 2016-2021 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -51,6 +51,8 @@ SourceFiles
 #include "dimensionedTypes.H"
 #include "zero.H"
 #include "className.H"
+#include "lduPrimitiveMeshAssembly.H"
+#include "lduMesh.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
@@ -108,6 +110,7 @@ tmp<GeometricField<Type, fvPatchField, volMesh>> operator&
 );
 
 
+
 /*---------------------------------------------------------------------------*\
                            Class fvMatrix Declaration
 \*---------------------------------------------------------------------------*/
@@ -124,6 +127,18 @@ class fvMatrix
         //  Converted into a non-const reference at the point of solution.
         const GeometricField<Type, fvPatchField, volMesh>& psi_;
 
+        //- Originating fvMatrices when assembling matrices. Empty if not used.
+        PtrList<fvMatrix<Type>> subMatrices_;
+
+        //- Is the fvMatrix using implicit formulation
+        bool useImplicit_;
+
+        //- Name of the lduAssembly
+        word lduAssemblyName_;
+
+        //- Number of fvMatrices added to this
+        label nMatrix_;
+
         //- Dimension set
         dimensionSet dimensions_;
 
@@ -148,6 +163,7 @@ protected:
     //- Declare friendship with the fvSolver class
     friend class fvSolver;
 
+
     // Protected Member Functions
 
         //- Add patch contribution to internal field
@@ -185,6 +201,12 @@ protected:
         ) const;
 
 
+        // Implicit helper functions
+
+            //- Name the implicit assembly addressing
+            label checkImplicit(const label fieldI = 0);
+
+
         // Matrix completion functionality
 
             void addBoundaryDiag
@@ -285,10 +307,121 @@ public:
 
         // Access
 
-            const GeometricField<Type, fvPatchField, volMesh>& psi() const
-            {
-                return psi_;
-            }
+            // Coupling
+
+                label nMatrices() const
+                {
+                    return (nMatrix_ == 0 ? 1 : nMatrix_);
+                }
+
+                const fvMatrix<Type>& matrix(const label i) const
+                {
+                    return (nMatrix_ == 0 ? *this : subMatrices_[i]);
+                }
+
+                fvMatrix<Type>& matrix(const label i)
+                {
+                    return (nMatrix_ == 0 ? *this : subMatrices_[i]);
+                }
+
+                label globalPatchID
+                (
+                    const label fieldi,
+                    const label patchi
+                ) const
+                {
+                    if (!lduMeshPtr())
+                    {
+                        return patchi;
+                    }
+                    else
+                    {
+                        return lduMeshPtr()->patchMap()[fieldi][patchi];
+                    }
+                }
+
+                //- Transfer lower, upper, diag and source to this fvMatrix
+                void transferFvMatrixCoeffs();
+
+                //- Create or update ldu assembly
+                void createOrUpdateLduPrimitiveAssembly();
+
+                //- Access to lduPrimitiveMeshAssembly
+                lduPrimitiveMeshAssembly* lduMeshPtr();
+
+                //- Const Access to lduPrimitiveMeshAssembly
+                const lduPrimitiveMeshAssembly* lduMeshPtr() const;
+
+                //- Manipulate matrix
+                void manipulateMatrix(direction cmp);
+
+                //- Manipulate boundary/internal coeffs for coupling
+                void setBounAndInterCoeffs();
+
+                //- Set interfaces
+                void setInterfaces
+                (
+                    lduInterfaceFieldPtrsList&,
+                    PtrDynList<lduInterfaceField>& newInterfaces
+                );
+
+                //- Add internal and boundary contribution to local patches
+                void mapContributions
+                (
+                    label fieldi,
+                    const FieldField<Field, Type>& fluxContrib,
+                    FieldField<Field, Type>& contrib,
+                    bool internal
+                ) const;
+
+                //- Return optional lduAdressing
+                const lduPrimitiveMeshAssembly& lduMeshAssembly()
+                {
+                    return *lduMeshPtr();
+                }
+
+                //- Return psi
+                const GeometricField<Type, fvPatchField, volMesh>& psi
+                (
+                    const label i = 0
+                ) const
+                {
+                    return
+                    (
+                        (i == 0 && nMatrix_ == 0) ? psi_ : matrix(i).psi()
+                    );
+                }
+
+
+                GeometricField<Type, fvPatchField, volMesh>& psi
+                (
+                    const label i = 0
+                )
+                {
+                    return
+                    (
+                        (i == 0 && nMatrix_ == 0)
+                      ? const_cast
+                        <
+                            GeometricField<Type, fvPatchField, volMesh>&
+                        >(psi_)
+                      : const_cast
+                        <
+                            GeometricField<Type, fvPatchField, volMesh>&
+                        >
+                        (
+                            matrix(i).psi()
+                        )
+                    );
+                }
+
+                //- Clear multiple fvMatrices
+                void clear()
+                {
+                    subMatrices_.clear();
+                    nMatrix_ = 0;
+                }
+
 
             const dimensionSet& dimensions() const
             {
@@ -333,7 +466,6 @@ public:
                 return boundaryCoeffs_;
             }
 
-
             //- Declare return type of the faceFluxCorrectionPtr() function
             typedef GeometricField<Type, fvsPatchField, surfaceMesh>
                 *surfaceTypeFieldPtr;
@@ -405,6 +537,9 @@ public:
                 const scalar value
             );
 
+            //- Add fvMatrix
+            void addFvMatrix(fvMatrix<Type>& matrix);
+
             //- Relax matrix (for steady-state solution).
             //  alpha = 1 : diagonally equal
             //  alpha < 1 : diagonally dominant
diff --git a/src/finiteVolume/fvMatrices/fvMatrix/fvMatrixSolve.C b/src/finiteVolume/fvMatrices/fvMatrix/fvMatrixSolve.C
index dcc77cfd3c81c6629e5707d6e8d5eaaa2c3e0766..07c552b52deb58a857065cc2f6d4e0b771a679d8 100644
--- a/src/finiteVolume/fvMatrices/fvMatrix/fvMatrixSolve.C
+++ b/src/finiteVolume/fvMatrices/fvMatrix/fvMatrixSolve.C
@@ -116,6 +116,12 @@ Foam::SolverPerformance<Type> Foam::fvMatrix<Type>::solveSegregated
     const dictionary& solverControls
 )
 {
+    if (useImplicit_)
+    {
+        FatalErrorInFunction
+            << "Implicit option is not allowed for type: " << Type::typeName
+            << exit(FatalError);
+    }
     if (debug)
     {
         Info.masterStream(this->mesh().comm())
diff --git a/src/finiteVolume/fvMatrices/fvScalarMatrix/fvScalarMatrix.C b/src/finiteVolume/fvMatrices/fvScalarMatrix/fvScalarMatrix.C
index e5b1e88aa4c2c20ec1c010fc09703a851a2a6df8..99f4baf92c28b045c4ea24424eeb5b245b3aa39b 100644
--- a/src/finiteVolume/fvMatrices/fvScalarMatrix/fvScalarMatrix.C
+++ b/src/finiteVolume/fvMatrices/fvScalarMatrix/fvScalarMatrix.C
@@ -30,6 +30,9 @@ License
 #include "extrapolatedCalculatedFvPatchFields.H"
 #include "profiling.H"
 #include "PrecisionAdaptor.H"
+#include "jumpCyclicFvPatchField.H"
+#include "cyclicPolyPatch.H"
+#include "cyclicAMIPolyPatch.H"
 
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
@@ -82,6 +85,10 @@ Foam::fvMatrix<Foam::scalar>::solver
     scalarField saveDiag(diag());
     addBoundaryDiag(diag(), 0);
 
+    lduInterfaceFieldPtrsList interfaces =
+        psi_.boundaryField().scalarInterfaces();
+
+
     autoPtr<fvMatrix<scalar>::fvSolver> solverPtr
     (
         new fvMatrix<scalar>::fvSolver
@@ -93,7 +100,7 @@ Foam::fvMatrix<Foam::scalar>::solver
                 *this,
                 boundaryCoeffs_,
                 internalCoeffs_,
-                psi_.boundaryField().scalarInterfaces(),
+                interfaces,
                 solverControls
             )
         )
@@ -160,8 +167,29 @@ Foam::solverPerformance Foam::fvMatrix<Foam::scalar>::solveSegregated
             << endl;
     }
 
-    GeometricField<scalar, fvPatchField, volMesh>& psi =
-       const_cast<GeometricField<scalar, fvPatchField, volMesh>&>(psi_);
+    scalarField saveLower;
+    scalarField saveUpper;
+
+    if (useImplicit_)
+    {
+        createOrUpdateLduPrimitiveAssembly();
+
+        if (psi_.mesh().fluxRequired(psi_.name()))
+        {
+            // Save lower/upper for flux calculation
+            if (asymmetric())
+            {
+                saveLower = lower();
+            }
+            saveUpper = upper();
+        }
+
+        setLduMesh(*lduMeshPtr());
+        transferFvMatrixCoeffs();
+        setBounAndInterCoeffs();
+        direction cmpt = 0;
+        manipulateMatrix(cmpt);
+    }
 
     scalarField saveDiag(diag());
     addBoundaryDiag(diag(), 0);
@@ -169,16 +197,72 @@ Foam::solverPerformance Foam::fvMatrix<Foam::scalar>::solveSegregated
     scalarField totalSource(source_);
     addBoundarySource(totalSource, false);
 
+    lduInterfaceFieldPtrsList interfaces;
+    PtrDynList<lduInterfaceField> newInterfaces;
+    if (!useImplicit_)
+    {
+        interfaces = this->psi(0).boundaryField().scalarInterfaces();
+    }
+    else
+    {
+        setInterfaces(interfaces, newInterfaces);
+    }
+
+    tmp<scalarField> tpsi;
+    if (!useImplicit_)
+    {
+        GeometricField<scalar, fvPatchField, volMesh>& psi =
+           const_cast<GeometricField<scalar, fvPatchField, volMesh>&>(psi_);
+
+        tpsi = tmp<scalarField>(psi.primitiveFieldRef());
+    }
+    else
+    {
+        tpsi = tmp<scalarField>::New(lduAddr().size(), Zero);
+        scalarField& psi = tpsi.ref();
+
+        for (label fieldi = 0; fieldi < nMatrices(); fieldi++)
+        {
+            const label cellOffset = lduMeshPtr()->cellOffsets()[fieldi];
+            const auto& psiInternal = this->psi(fieldi).primitiveField();
+
+            forAll(psiInternal, localCellI)
+            {
+                psi[cellOffset + localCellI] = psiInternal[localCellI];
+            }
+        }
+    }
+    scalarField& psi = tpsi.constCast();
+
     // Solver call
     solverPerformance solverPerf = lduMatrix::solver::New
     (
-        psi.name(),
+        this->psi(0).name(),
         *this,
         boundaryCoeffs_,
         internalCoeffs_,
-        psi_.boundaryField().scalarInterfaces(),
+        interfaces,
         solverControls
-    )->solve(psi.primitiveFieldRef(), totalSource);
+    )->solve(psi, totalSource);
+
+    if (useImplicit_)
+    {
+        for (label fieldi = 0; fieldi < nMatrices(); fieldi++)
+        {
+            auto& psiInternal =
+                const_cast<GeometricField<scalar, fvPatchField, volMesh>&>
+                (
+                    this->psi(fieldi)
+                ).primitiveFieldRef();
+
+            const label cellOffset = lduMeshPtr()->cellOffsets()[fieldi];
+
+            forAll(psiInternal, localCellI)
+            {
+                psiInternal[localCellI] = psi[localCellI + cellOffset];
+            }
+        }
+    }
 
     if (solverPerformance::debug)
     {
@@ -187,9 +271,35 @@ Foam::solverPerformance Foam::fvMatrix<Foam::scalar>::solveSegregated
 
     diag() = saveDiag;
 
-    psi.correctBoundaryConditions();
+    if (useImplicit_)
+    {
+        if (psi_.mesh().fluxRequired(psi_.name()))
+        {
+            // Restore lower/upper
+            if (asymmetric())
+            {
+                lower().setSize(saveLower.size());
+                lower() = saveLower;
+            }
+
+            upper().setSize(saveUpper.size());
+            upper() = saveUpper;
+        }
+        // Set the original lduMesh
+        setLduMesh(psi_.mesh());
+    }
 
-    psi.mesh().setSolverPerformance(psi.name(), solverPerf);
+    for (label fieldi = 0; fieldi < nMatrices(); fieldi++)
+    {
+        auto& localPsi =
+            const_cast<GeometricField<scalar, fvPatchField, volMesh>&>
+            (
+                this->psi(fieldi)
+            );
+
+        localPsi.correctBoundaryConditions();
+        localPsi.mesh().setSolverPerformance(localPsi.name(), solverPerf);
+    }
 
     return solverPerf;
 }
diff --git a/src/finiteVolume/fvMatrices/fvScalarMatrix/fvScalarMatrix.H b/src/finiteVolume/fvMatrices/fvScalarMatrix/fvScalarMatrix.H
index c2c469517b0133a1936e877fd41a11171fd774bf..82545cec64cbdc0f4dcde4ade33293b9914c055b 100644
--- a/src/finiteVolume/fvMatrices/fvScalarMatrix/fvScalarMatrix.H
+++ b/src/finiteVolume/fvMatrices/fvScalarMatrix/fvScalarMatrix.H
@@ -59,22 +59,13 @@ void fvMatrix<scalar>::setComponentReference
 );
 
 template<>
-autoPtr<fvMatrix<scalar>::fvSolver> fvMatrix<scalar>::solver
-(
-    const dictionary&
-);
+autoPtr<fvMatrix<scalar>::fvSolver> fvMatrix<scalar>::solver(const dictionary&);
 
 template<>
-solverPerformance fvMatrix<scalar>::fvSolver::solve
-(
-    const dictionary&
-);
+solverPerformance fvMatrix<scalar>::fvSolver::solve(const dictionary&);
 
 template<>
-solverPerformance fvMatrix<scalar>::solveSegregated
-(
-    const dictionary&
-);
+solverPerformance fvMatrix<scalar>::solveSegregated(const dictionary&);
 
 template<>
 tmp<scalarField> fvMatrix<scalar>::residual() const;
diff --git a/src/finiteVolume/fvMesh/fvMesh.C b/src/finiteVolume/fvMesh/fvMesh.C
index 8d4bee062ea7cef8c29dc7d42486b20626679062..283fa43a38ae66a38e0d776645a7cf8e9985952a 100644
--- a/src/finiteVolume/fvMesh/fvMesh.C
+++ b/src/finiteVolume/fvMesh/fvMesh.C
@@ -697,12 +697,20 @@ const Foam::lduAddressing& Foam::fvMesh::lduAddr() const
             << nFaces() << endl;
 
         lduPtr_ = new fvMeshLduAddressing(*this);
+
+        return *lduPtr_;
     }
 
     return *lduPtr_;
 }
 
 
+Foam::lduInterfacePtrsList Foam::fvMesh::interfaces() const
+{
+    return boundary().interfaces();
+}
+
+
 void Foam::fvMesh::mapFields(const mapPolyMesh& meshMap)
 {
     DebugInFunction
diff --git a/src/finiteVolume/fvMesh/fvMesh.H b/src/finiteVolume/fvMesh/fvMesh.H
index da3748cfe2ad9c5cae88a2b91a5dc53b5cb6d6b9..0c547157d618fc01001ecc987de6492760bbccb1 100644
--- a/src/finiteVolume/fvMesh/fvMesh.H
+++ b/src/finiteVolume/fvMesh/fvMesh.H
@@ -67,6 +67,8 @@ SourceFiles
 #include "className.H"
 #include "SolverPerformance.H"
 
+
+
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
 namespace Foam
@@ -309,10 +311,7 @@ public:
 
             //- Return a list of pointers for each patch
             //  with only those pointing to interfaces being set
-            virtual lduInterfacePtrsList interfaces() const
-            {
-                return boundary().interfaces();
-            }
+            virtual lduInterfacePtrsList interfaces() const;
 
             //- Return communicator used for parallel communication
             virtual label comm() const
diff --git a/src/finiteVolume/fvMesh/fvPatches/basic/coupled/coupledFvPatch.H b/src/finiteVolume/fvMesh/fvPatches/basic/coupled/coupledFvPatch.H
index b7a8cab7b2aa0df76917822d62441e3c77e55422..f334ab2f2ab57f9bd632b5bd76a8bf8a0a8011bb 100644
--- a/src/finiteVolume/fvMesh/fvPatches/basic/coupled/coupledFvPatch.H
+++ b/src/finiteVolume/fvMesh/fvPatches/basic/coupled/coupledFvPatch.H
@@ -124,12 +124,21 @@ public:
         // Interface transfer functions
 
             //- Return the values of the given internal data adjacent to
-            //  the interface as a field
+            //- the interface as a field
             virtual tmp<labelField> interfaceInternalField
             (
                 const labelUList& internalData
             ) const = 0;
 
+
+            //- Return the values of the given internal data adjacent to
+            //- the interface as a field using a mapping faceCell
+            virtual tmp<labelField> interfaceInternalField
+            (
+                const labelUList& internalData,
+                const labelUList& faceCell
+            ) const = 0;
+
             //- Inherit initInternalFieldTransfer from lduInterface
             using lduInterface::initInternalFieldTransfer;
 
@@ -141,6 +150,15 @@ public:
             ) const
             {}
 
+            //- Initialise neighbour field transfer using faceCells map
+            virtual void initInternalFieldTransfer
+            (
+                const Pstream::commsTypes commsType,
+                labelUList& iF,
+                const labelUList& faceCell
+            ) const
+            {}
+
             //- Return neighbour field
             virtual tmp<labelField> internalFieldTransfer
             (
diff --git a/src/finiteVolume/fvMesh/fvPatches/constraint/cyclic/cyclicFvPatch.C b/src/finiteVolume/fvMesh/fvPatches/constraint/cyclic/cyclicFvPatch.C
index b22a27fdec6d5ec0a15ce9ec12415bdafb21cab8..7a04296170c0dcfd444db3127aca30c483d440eb 100644
--- a/src/finiteVolume/fvMesh/fvPatches/constraint/cyclic/cyclicFvPatch.C
+++ b/src/finiteVolume/fvMesh/fvPatches/constraint/cyclic/cyclicFvPatch.C
@@ -6,6 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2016 OpenFOAM Foundation
+    Copyright (C) 2019 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -101,6 +102,16 @@ Foam::tmp<Foam::labelField> Foam::cyclicFvPatch::interfaceInternalField
 }
 
 
+Foam::tmp<Foam::labelField> Foam::cyclicFvPatch::interfaceInternalField
+(
+    const labelUList& internalData,
+    const labelUList& faceCells
+) const
+{
+    return patchInternalField(internalData, faceCells);
+}
+
+
 Foam::tmp<Foam::labelField> Foam::cyclicFvPatch::internalFieldTransfer
 (
     const Pstream::commsTypes commsType,
diff --git a/src/finiteVolume/fvMesh/fvPatches/constraint/cyclic/cyclicFvPatch.H b/src/finiteVolume/fvMesh/fvPatches/constraint/cyclic/cyclicFvPatch.H
index c21104ca7fe4007b0d9ebdc9eb7fbda1fe019529..0d272294ed064baec4b54e99b08440108d76906a 100644
--- a/src/finiteVolume/fvMesh/fvPatches/constraint/cyclic/cyclicFvPatch.H
+++ b/src/finiteVolume/fvMesh/fvPatches/constraint/cyclic/cyclicFvPatch.H
@@ -6,6 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011 OpenFOAM Foundation
+    Copyright (C) 2019 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -87,6 +88,7 @@ public:
 
     // Member functions
 
+
         // Access
 
             //- Return local reference cast into the cyclic patch
@@ -149,18 +151,29 @@ public:
         // Interface transfer functions
 
             //- Return the values of the given internal data adjacent to
-            //  the interface as a field
+            //- the interface as a field
             virtual tmp<labelField> interfaceInternalField
             (
                 const labelUList& internalData
             ) const;
 
+
+            //- Return the values of the given internal data adjacent to
+            //- the interface as a field using a mapping faceCell
+            virtual tmp<labelField> interfaceInternalField
+            (
+                const labelUList& internalData,
+                const labelUList& faceCell
+            ) const;
+
+
             //- Return neighbour field
             virtual tmp<labelField> internalFieldTransfer
             (
                 const Pstream::commsTypes commsType,
                 const labelUList& internalData
             ) const;
+
 };
 
 
diff --git a/src/finiteVolume/fvMesh/fvPatches/constraint/cyclicACMI/cyclicACMIFvPatch.C b/src/finiteVolume/fvMesh/fvPatches/constraint/cyclicACMI/cyclicACMIFvPatch.C
index 46b57e156bc1d385a1bd5bd2ee05ea7890db5144..966cdb26a3fd2a78fbbd4bd449caa65552cb82f6 100644
--- a/src/finiteVolume/fvMesh/fvPatches/constraint/cyclicACMI/cyclicACMIFvPatch.C
+++ b/src/finiteVolume/fvMesh/fvPatches/constraint/cyclicACMI/cyclicACMIFvPatch.C
@@ -168,6 +168,68 @@ Foam::cyclicACMIFvPatch::cyclicACMIFvPatch
 
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
+// void Foam::cyclicACMIFvPatch::newInternalProcFaces
+// (
+//     label& newFaces,
+//     label& newProcFaces
+// ) const
+// {
+//     const List<labelList>& addSourceFaces =
+//         cyclicACMIPolyPatch_.AMI().srcAddress();
+//
+//     const scalarField& fMask = cyclicACMIPolyPatch_.srcMask();
+//
+//     // Add new faces as many weights for AMI
+//     forAll (addSourceFaces, faceI)
+//     {
+//         if (fMask[faceI] > cyclicACMIPolyPatch_.tolerance_)
+//         {
+//             const labelList& nbrFaceIs = addSourceFaces[faceI];
+//
+//             forAll (nbrFaceIs, j)
+//             {
+//                 label nbrFaceI = nbrFaceIs[j];
+//
+//                 if (nbrFaceI < neighbPatch().size())
+//                 {
+//                     // local faces
+//                     newFaces++;
+//                 }
+//                 else
+//                 {
+//                     // Proc faces
+//                     newProcFaces++;
+//                 }
+//             }
+//         }
+//     }
+// }
+
+
+// Foam::refPtr<Foam::labelListList>
+// Foam::cyclicACMIFvPatch::mapCollocatedFaces() const
+// {
+//     const scalarField& fMask = cyclicACMIPolyPatch_.srcMask();
+//     const labelListList& srcFaces = cyclicACMIPolyPatch_.AMI().srcAddress();
+//     labelListList dOverFaces;
+//
+//     dOverFaces.setSize(srcFaces.size());
+//     forAll (dOverFaces, faceI)
+//     {
+//         if (fMask[faceI] > cyclicACMIPolyPatch_.tolerance_)
+//         {
+//             dOverFaces[faceI].setSize(srcFaces[faceI].size());
+//
+//             forAll (dOverFaces[faceI], subFaceI)
+//             {
+//                 dOverFaces[faceI][subFaceI] = srcFaces[faceI][subFaceI];
+//             }
+//         }
+//     }
+//     return refPtr<labelListList>(new labelListList(dOverFaces));
+// }
+
+
 bool Foam::cyclicACMIFvPatch::coupled() const
 {
     return Pstream::parRun() || (this->size() && neighbFvPatch().size());
@@ -227,6 +289,16 @@ Foam::tmp<Foam::labelField> Foam::cyclicACMIFvPatch::interfaceInternalField
 }
 
 
+Foam::tmp<Foam::labelField> Foam::cyclicACMIFvPatch::interfaceInternalField
+(
+    const labelUList& internalData,
+    const labelUList& faceCells
+) const
+{
+    return patchInternalField(internalData, faceCells);
+}
+
+
 Foam::tmp<Foam::labelField> Foam::cyclicACMIFvPatch::internalFieldTransfer
 (
     const Pstream::commsTypes commsType,
@@ -344,5 +416,4 @@ void Foam::cyclicACMIFvPatch::movePoints()
     }
 }
 
-
 // ************************************************************************* //
diff --git a/src/finiteVolume/fvMesh/fvPatches/constraint/cyclicACMI/cyclicACMIFvPatch.H b/src/finiteVolume/fvMesh/fvPatches/constraint/cyclicACMI/cyclicACMIFvPatch.H
index 687fcc0201bbf59a5102a81732f5ec909471823b..16ca0b4586d394c8ec537f14a4fb8c34aa47ee2d 100644
--- a/src/finiteVolume/fvMesh/fvPatches/constraint/cyclicACMI/cyclicACMIFvPatch.H
+++ b/src/finiteVolume/fvMesh/fvPatches/constraint/cyclicACMI/cyclicACMIFvPatch.H
@@ -97,6 +97,15 @@ public:
 
     // Member functions
 
+//         // Implicit treatment functions
+//
+//             //- Return number of new internal sub-faces and new proc faces
+//             virtual void newInternalProcFaces(label&, label&) const;
+//
+//             //- Return collocated faces
+//             virtual refPtr<labelListList> mapCollocatedFaces() const;
+
+
         // Access
 
             //- Return local reference cast into the cyclic patch
@@ -169,9 +178,9 @@ public:
                 );
             }
 
-            //- Return true if this patch is coupled. This is equivalent
-            //- to the coupledPolyPatch::coupled() if parallel running or
-            //- both sides present, false otherwise
+            //- Return true if this patch is coupled.
+            //  This is equivalent to coupledPolyPatch::coupled()
+            //  if parallel running or both sides present, false otherwise
             virtual bool coupled() const;
 
             //- Return delta (P to N) vectors across coupled patch
@@ -214,12 +223,21 @@ public:
                 const labelUList& internalData
             ) const;
 
+            //- Return the values of the given internal data adjacent to
+            //- the interface as a field using a mapping faceCell
+            virtual tmp<labelField> interfaceInternalField
+            (
+                const labelUList& internalData,
+                const labelUList& faceCells
+            ) const;
+
             //- Return neighbour field
             virtual tmp<labelField> internalFieldTransfer
             (
                 const Pstream::commsTypes commsType,
                 const labelUList& internalData
             ) const;
+
 };
 
 
diff --git a/src/finiteVolume/fvMesh/fvPatches/constraint/cyclicAMI/cyclicAMIFvPatch.C b/src/finiteVolume/fvMesh/fvPatches/constraint/cyclicAMI/cyclicAMIFvPatch.C
index 92c8ec63b2dae07bab985dadd74a015d18631950..86d45f1637ca2efbc0508f412776d42a6f71ddf7 100644
--- a/src/finiteVolume/fvMesh/fvPatches/constraint/cyclicAMI/cyclicAMIFvPatch.C
+++ b/src/finiteVolume/fvMesh/fvPatches/constraint/cyclicAMI/cyclicAMIFvPatch.C
@@ -51,6 +51,38 @@ namespace Foam
 
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
+// void Foam::cyclicAMIFvPatch::newInternalProcFaces
+// (
+//     label& newFaces,
+//     label& newProcFaces
+// ) const
+// {
+//     const labelListList& addSourceFaces = AMI().srcAddress();
+//
+//     // Add new faces as many weights for AMI
+//     forAll (addSourceFaces, faceI)
+//     {
+//         const labelList& nbrFaceIs = addSourceFaces[faceI];
+//
+//         forAll (nbrFaceIs, j)
+//         {
+//             label nbrFaceI = nbrFaceIs[j];
+//
+//             if (nbrFaceI < neighbPatch().size())
+//             {
+//                 // local faces
+//                 newFaces++;
+//             }
+//             else
+//             {
+//                 // Proc faces
+//                 newProcFaces++;
+//             }
+//         }
+//     }
+// }
+
+
 bool Foam::cyclicAMIFvPatch::coupled() const
 {
     return
@@ -190,6 +222,16 @@ Foam::tmp<Foam::labelField> Foam::cyclicAMIFvPatch::interfaceInternalField
 }
 
 
+Foam::tmp<Foam::labelField> Foam::cyclicAMIFvPatch::interfaceInternalField
+(
+    const labelUList& internalData,
+    const labelUList& faceCells
+) const
+{
+    return patchInternalField(internalData, faceCells);
+}
+
+
 Foam::tmp<Foam::labelField> Foam::cyclicAMIFvPatch::internalFieldTransfer
 (
     const Pstream::commsTypes commsType,
@@ -270,5 +312,4 @@ void Foam::cyclicAMIFvPatch::movePoints()
     }
 }
 
-
 // ************************************************************************* //
diff --git a/src/finiteVolume/fvMesh/fvPatches/constraint/cyclicAMI/cyclicAMIFvPatch.H b/src/finiteVolume/fvMesh/fvPatches/constraint/cyclicAMI/cyclicAMIFvPatch.H
index 1c3b46ab574592ac1a30dd22373de263d1532422..2a26e21658f9c1afa3bf54a1cb491b552dd6bc1c 100644
--- a/src/finiteVolume/fvMesh/fvPatches/constraint/cyclicAMI/cyclicAMIFvPatch.H
+++ b/src/finiteVolume/fvMesh/fvPatches/constraint/cyclicAMI/cyclicAMIFvPatch.H
@@ -6,6 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2016 OpenFOAM Foundation
+    Copyright (C) 2019 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -102,6 +103,41 @@ public:
 
         // Access
 
+//             // Implicit treatment functions
+//
+//                 //- Return number of new internal of this polyPatch faces
+//                 virtual void newInternalProcFaces(label&, label&) const;
+//
+//                 //- Return nbrCells
+//                 virtual const labelUList& nbrCells() const
+//                 {
+//                     return cyclicAMIPolyPatch_.neighbPatch().faceCells();
+//                 }
+//
+//                 //- Return nbr patch ID
+//                 virtual label neighbPolyPatchID() const
+//                 {
+//                     return neighbPatchID();
+//                 }
+//
+//                 //- Return collocated faces map
+//                 virtual refPtr<labelListList> mapCollocatedFaces() const
+//                 {
+//                     const labelListList& sourceFaces =
+//                         cyclicAMIPolyPatch_.AMI().srcAddress();
+//                     return refPtr<labelListList>
+//                     (
+//                         new labelListList(sourceFaces)
+//                     );
+//                 }
+//
+//                 //- Return implicit master
+//                 virtual bool masterImplicit() const
+//                 {
+//                     return owner();
+//                 }
+
+
             //- Return local reference cast into the cyclic patch
             const cyclicAMIPolyPatch& cyclicAMIPatch() const
             {
@@ -167,6 +203,7 @@ public:
                 );
             }
 
+
             //- Return true if this patch is coupled. This is equivalent
             //- to the coupledPolyPatch::coupled() if parallel running or
             //- both sides present, false otherwise
@@ -205,12 +242,23 @@ public:
                 const labelUList& internalData
             ) const;
 
+
+            //- Return the values of the given internal data adjacent to
+            //- the interface as a field using a mapping faceCell
+            virtual tmp<labelField> interfaceInternalField
+            (
+                const labelUList& internalData,
+                const labelUList& faceCells
+            ) const;
+
+
             //- Return neighbour field
             virtual tmp<labelField> internalFieldTransfer
             (
                 const Pstream::commsTypes commsType,
                 const labelUList& internalData
             ) const;
+
 };
 
 
diff --git a/src/finiteVolume/fvMesh/fvPatches/constraint/processor/processorFvPatch.C b/src/finiteVolume/fvMesh/fvPatches/constraint/processor/processorFvPatch.C
index ac2da30fd870a7faa8d1f10cd3f0cdfbd3d0546a..dbf04fa225e77d7592271171dd358092e5a1cd46 100644
--- a/src/finiteVolume/fvMesh/fvPatches/constraint/processor/processorFvPatch.C
+++ b/src/finiteVolume/fvMesh/fvPatches/constraint/processor/processorFvPatch.C
@@ -6,6 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2014 OpenFOAM Foundation
+    Copyright (C) 2019 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -110,6 +111,16 @@ Foam::tmp<Foam::labelField> Foam::processorFvPatch::interfaceInternalField
 }
 
 
+Foam::tmp<Foam::labelField> Foam::processorFvPatch::interfaceInternalField
+(
+    const labelUList& internalData,
+    const labelUList& faceCells
+) const
+{
+    return patchInternalField(internalData, faceCells);
+}
+
+
 void Foam::processorFvPatch::initInternalFieldTransfer
 (
     const Pstream::commsTypes commsType,
@@ -120,6 +131,17 @@ void Foam::processorFvPatch::initInternalFieldTransfer
 }
 
 
+void Foam::processorFvPatch::initInternalFieldTransfer
+(
+    const Pstream::commsTypes commsType,
+    const labelUList& iF,
+    const labelUList& faceCells
+) const
+{
+    send(commsType, interfaceInternalField(iF, faceCells)());
+}
+
+
 Foam::tmp<Foam::labelField> Foam::processorFvPatch::internalFieldTransfer
 (
     const Pstream::commsTypes commsType,
diff --git a/src/finiteVolume/fvMesh/fvPatches/constraint/processor/processorFvPatch.H b/src/finiteVolume/fvMesh/fvPatches/constraint/processor/processorFvPatch.H
index d985505d338773fd5557fc8b8c7f5e7a7771db3d..03934add2b8f4c752325d3383056101ec5744838 100644
--- a/src/finiteVolume/fvMesh/fvPatches/constraint/processor/processorFvPatch.H
+++ b/src/finiteVolume/fvMesh/fvPatches/constraint/processor/processorFvPatch.H
@@ -6,6 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2015 OpenFOAM Foundation
+    Copyright (C) 2019 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -113,14 +114,7 @@ public:
         //- Return true if running parallel
         virtual bool coupled() const
         {
-            if (Pstream::parRun())
-            {
-                return true;
-            }
-            else
-            {
-                return false;
-            }
+            return Pstream::parRun();
         }
 
         const processorPolyPatch& procPolyPatch() const
@@ -153,12 +147,20 @@ public:
         // Interface transfer functions
 
             //- Return the values of the given internal data adjacent to
-            //  the interface as a field
+            //- the interface as a field
             virtual tmp<labelField> interfaceInternalField
             (
                 const labelUList& internalData
             ) const;
 
+            //- Return the values of the given internal data adjacent to
+            //- the interface as a field using a mapping faceCell
+            virtual tmp<labelField> interfaceInternalField
+            (
+                const labelUList& internalData,
+                const labelUList& faceCells
+            ) const;
+
             //- Inherit initInternalFieldTransfer from coupledFvPatch
             using coupledFvPatch::initInternalFieldTransfer;
 
@@ -169,12 +171,21 @@ public:
                 const labelUList& internalData
             ) const;
 
+            //- Initialise neighbour field transfer using faceCells map
+            virtual void initInternalFieldTransfer
+            (
+                const Pstream::commsTypes commsType,
+                const labelUList& iF,
+                const labelUList& faceCells
+            ) const;
+
             //- Return neighbour field
             virtual tmp<labelField> internalFieldTransfer
             (
                 const Pstream::commsTypes commsType,
                 const labelUList& internalData
             ) const;
+
 };
 
 
diff --git a/src/finiteVolume/fvMesh/fvPatches/fvPatch/fvPatch.H b/src/finiteVolume/fvMesh/fvPatches/fvPatch/fvPatch.H
index 92870d06b17aba590efd0e6abd0afee065c3aec3..7ef94de2ab9893789f82c4606bccfb14fbe7f458 100644
--- a/src/finiteVolume/fvMesh/fvPatches/fvPatch/fvPatch.H
+++ b/src/finiteVolume/fvMesh/fvPatches/fvPatch/fvPatch.H
@@ -257,6 +257,15 @@ public:
             template<class Type>
             tmp<Field<Type>> patchInternalField(const UList<Type>&) const;
 
+            //- Return given internal field next to patch as patch field
+            //- using faceCells mapping
+            template<class Type>
+            tmp<Field<Type>> patchInternalField
+            (
+                const UList<Type>&,
+                const labelUList& faceCells
+            ) const;
+
             //- Return given internal field next to patch as patch field
             template<class Type>
             void patchInternalField(const UList<Type>&, Field<Type>&) const;
diff --git a/src/finiteVolume/fvMesh/fvPatches/fvPatch/fvPatchTemplates.C b/src/finiteVolume/fvMesh/fvPatches/fvPatch/fvPatchTemplates.C
index 713c7cff55fa43d1825c3de3a215f5aa40e03072..634d6c5b9c8fac7befa8db14370dfd079c029b8d 100644
--- a/src/finiteVolume/fvMesh/fvPatches/fvPatch/fvPatchTemplates.C
+++ b/src/finiteVolume/fvMesh/fvPatches/fvPatch/fvPatchTemplates.C
@@ -6,6 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2016 OpenFOAM Foundation
+    Copyright (C) 2019 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -35,10 +36,19 @@ Foam::tmp<Foam::Field<Type>> Foam::fvPatch::patchInternalField
     const UList<Type>& f
 ) const
 {
-    tmp<Field<Type>> tpif(new Field<Type>(size()));
-    Field<Type>& pif = tpif.ref();
+    return patchInternalField(f, this->faceCells());
+}
 
-    const labelUList& faceCells = this->faceCells();
+
+template<class Type>
+Foam::tmp<Foam::Field<Type>> Foam::fvPatch::patchInternalField
+(
+    const UList<Type>& f,
+    const labelUList& faceCells
+) const
+{
+    auto tpif = tmp<Field<Type>>::New(size());
+    auto& pif = tpif.ref();
 
     forAll(pif, facei)
     {
@@ -56,7 +66,7 @@ void Foam::fvPatch::patchInternalField
     Field<Type>& pif
 ) const
 {
-    pif.setSize(size());
+    pif.resize(size());
 
     const labelUList& faceCells = this->faceCells();
 
diff --git a/src/finiteVolume/lduPrimitiveMeshAssembly/AssemblyFvPatch.H b/src/finiteVolume/lduPrimitiveMeshAssembly/AssemblyFvPatch.H
new file mode 100644
index 0000000000000000000000000000000000000000..a8ab612c274baa17cae02c84f781278aef6f29da
--- /dev/null
+++ b/src/finiteVolume/lduPrimitiveMeshAssembly/AssemblyFvPatch.H
@@ -0,0 +1,176 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2021 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+Class
+    Foam::AssemblyFvPatch
+
+Description
+    An assembly of lduMatrix that is specific inter-region coupling
+    through mapped patches.
+
+SourceFiles
+    AssemblyFvPatch.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef AssemblyFvPatch_H
+#define AssemblyFvPatch_H
+
+
+#include "cyclicFvPatch.H"
+#include "cyclicAMIFvPatch.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+/*---------------------------------------------------------------------------*\
+                    Class AssemblyFvPatch Declaration
+\*---------------------------------------------------------------------------*/
+
+template<class CyclicType>
+class AssemblyFvPatch
+:
+    public CyclicType
+{
+protected:
+
+    // Protected Data
+
+        //- Nbr faceCell
+        const labelList& nrbFaceCells_;
+
+        //- Local faceCells
+        const labelList& faceCells_;
+
+        //- Nbr patch ID
+        label nbrPatchID_;
+
+        //- Non-overlap patch ID
+        label nonOverlapPatchID_;
+
+
+public:
+
+    //- Runtime type information
+    TypeName(CyclicType::typeName_());
+
+
+    // Constructors
+
+        //- Construct from components
+        AssemblyFvPatch
+        (
+            const polyPatch& patch,
+            const fvBoundaryMesh& bm,
+            const labelList& nrbFaceCells,
+            const labelList& faceCells,
+            const label nbrPatchID,
+            const label nonOverPatchID = -1
+        )
+        :
+            CyclicType(patch, bm),
+            nrbFaceCells_(nrbFaceCells),
+            faceCells_(faceCells),
+            nbrPatchID_(nbrPatchID),
+            nonOverlapPatchID_(nonOverPatchID)
+        {}
+
+
+    //- Destructor
+    virtual ~AssemblyFvPatch() = default;
+
+
+    // Member Functions
+
+        //- Return neighbour field
+        virtual tmp<labelField> internalFieldTransfer
+        (
+            const Pstream::commsTypes commsType,
+            const labelUList& internalData
+        ) const
+        {
+            auto tpif = tmp<labelField>::New(nrbFaceCells_.size());
+            auto& pif = tpif.ref();
+
+            forAll(pif, facei)
+            {
+                pif[facei] = internalData[nrbFaceCells_[facei]];
+            }
+
+            return tpif;
+        }
+
+        //- Return neighbour
+        virtual label neighbPatchID() const
+        {
+            return nbrPatchID_;
+        }
+
+        //- Return non-overlap patch ID for ACMI
+        virtual label nonOverlapPatchID() const
+        {
+            return nonOverlapPatchID_;
+        }
+
+        //- Return non-overlapping fvPatch for ACMI
+        virtual const fvPatch& nonOverlapPatch() const
+        {
+            return this->boundaryMesh()[nonOverlapPatchID_];
+        }
+
+        //- Return nbr patch
+        virtual const CyclicType& neighbPatch() const
+        {
+            return refCast<const CyclicType>
+            (
+                this->boundaryMesh()[nbrPatchID_]
+            );
+        }
+
+        //- Return faceCells
+        virtual const labelUList& faceCells() const
+        {
+            return faceCells_;
+        }
+};
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#define makeAssemblyFvPatch(Type)                                             \
+                                                                              \
+    defineNamedTemplateTypeNameAndDebug(AssemblyFvPatch<Type>, 0);            \
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/finiteVolume/lduPrimitiveMeshAssembly/AssemblyFvPatches.C b/src/finiteVolume/lduPrimitiveMeshAssembly/AssemblyFvPatches.C
new file mode 100644
index 0000000000000000000000000000000000000000..78a3f27ce504d7404c669ee31f633dc6e8572e4a
--- /dev/null
+++ b/src/finiteVolume/lduPrimitiveMeshAssembly/AssemblyFvPatches.C
@@ -0,0 +1,56 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2021 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+Class
+    Foam::AssemblyPvPatch
+
+Description
+    An assembly of lduMatrix that is specific inter-region coupling
+    through mapped patches.
+
+SourceFiles
+    AssemblyPvPatch.C
+
+\*---------------------------------------------------------------------------*/
+
+#include "AssemblyFvPatch.H"
+
+#include "cyclicFvPatch.H"
+#include "cyclicAMIFvPatch.H"
+#include "cyclicACMIFvPatch.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+makeAssemblyFvPatch(cyclicFvPatch);
+makeAssemblyFvPatch(cyclicAMIFvPatch);
+makeAssemblyFvPatch(cyclicACMIFvPatch);
+
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+
diff --git a/src/finiteVolume/lduPrimitiveMeshAssembly/assemblyFaceAreaPairGAMGAgglomeration/assemblyFaceAreaPairGAMGAgglomeration.C b/src/finiteVolume/lduPrimitiveMeshAssembly/assemblyFaceAreaPairGAMGAgglomeration/assemblyFaceAreaPairGAMGAgglomeration.C
new file mode 100644
index 0000000000000000000000000000000000000000..1cbca2c9a4e3607e5975335cc86c0b3440867b6a
--- /dev/null
+++ b/src/finiteVolume/lduPrimitiveMeshAssembly/assemblyFaceAreaPairGAMGAgglomeration/assemblyFaceAreaPairGAMGAgglomeration.C
@@ -0,0 +1,244 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2018-2019 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+\*---------------------------------------------------------------------------*/
+
+#include "assemblyFaceAreaPairGAMGAgglomeration.H"
+#include "lduMatrix.H"
+#include "addToRunTimeSelectionTable.H"
+#include "lduPrimitiveMeshAssembly.H"
+#include "surfaceFields.H"
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+namespace Foam
+{
+    defineTypeNameAndDebug(assemblyFaceAreaPairGAMGAgglomeration, 0);
+
+    addToRunTimeSelectionTable
+    (
+        GAMGAgglomeration,
+        assemblyFaceAreaPairGAMGAgglomeration,
+        lduMatrix
+    );
+
+    addToRunTimeSelectionTable
+    (
+        GAMGAgglomeration,
+        assemblyFaceAreaPairGAMGAgglomeration,
+        geometry
+    );
+}
+
+
+// * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * * * //
+
+Foam::assemblyFaceAreaPairGAMGAgglomeration::
+~assemblyFaceAreaPairGAMGAgglomeration()
+{}
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::assemblyFaceAreaPairGAMGAgglomeration::
+assemblyFaceAreaPairGAMGAgglomeration
+(
+    const lduMatrix& matrix,
+    const dictionary& controlDict
+)
+:
+    pairGAMGAgglomeration(matrix.mesh(), controlDict)
+{
+    const lduMesh& ldumesh = matrix.mesh();
+
+    if (isA<lduPrimitiveMeshAssembly>(ldumesh))
+    {
+        const lduPrimitiveMeshAssembly& mesh =
+            refCast<const lduPrimitiveMeshAssembly>(ldumesh);
+
+        vectorField faceAreas(mesh.lduAddr().upperAddr().size(), Zero);
+
+        const labelListList& faceMap = mesh.faceMap();
+
+        for (label i=0; i < mesh.meshes().size(); ++i)
+        {
+            const fvMesh& m = refCast<const fvMesh>(mesh.meshes()[i]);
+            const labelList& subFaceMap = faceMap[i];
+            const vectorField& areas = m.Sf().internalField();
+
+            forAll(subFaceMap, facei)
+            {
+                faceAreas[subFaceMap[facei]] = areas[facei];
+            }
+
+            const polyBoundaryMesh& patches = m.boundaryMesh();
+
+            // Fill faceAreas for new faces
+            forAll(patches, patchI)
+            {
+                const polyPatch& pp = patches[patchI];
+                label globalPatchID = mesh.patchMap()[i][patchI];
+
+                if (globalPatchID == -1)
+                {
+                    if (pp.masterImplicit())
+                    {
+                        const vectorField& sf = m.boundary()[patchI].Sf();
+
+                        if (isA<cyclicAMIPolyPatch>(pp))
+                        {
+                            const cyclicAMIPolyPatch& mpp =
+                                    refCast<const cyclicAMIPolyPatch>(pp);
+
+                            const scalarListList& srcWeight =
+                                mpp.AMI().srcWeights();
+
+                            label subFaceI = 0;
+                            forAll(pp.faceCells(), faceI)
+                            {
+                                const scalarList& w = srcWeight[faceI];
+
+                                for(label j=0; j<w.size(); j++)
+                                {
+                                    const label globalFaceI =
+                                        mesh.faceBoundMap()[i][patchI][subFaceI];
+
+                                    if (globalFaceI != -1)
+                                    {
+                                        faceAreas[globalFaceI] = w[j]*sf[faceI];
+                                    }
+                                    subFaceI++;
+                                }
+                            }
+                        }
+                        else if (isA<cyclicACMIPolyPatch>(pp))
+                        {
+                            const cyclicACMIPolyPatch& mpp =
+                                refCast<const cyclicACMIPolyPatch>(pp);
+
+                            const scalarListList& srcWeight =
+                                mpp.AMI().srcWeights();
+
+                            const scalarField& mask = mpp.mask();
+                            const scalar tol = mpp.tolerance();
+                            label subFaceI = 0;
+                            forAll(mask, faceI)
+                            {
+                                const scalarList& w = srcWeight[faceI];
+
+                                for(label j=0; j<w.size(); j++)
+                                {
+                                    if (mask[faceI] > tol)
+                                    {
+                                        const label globalFaceI =
+                                            mesh.faceBoundMap()[i]
+                                            [patchI][subFaceI];
+
+                                        faceAreas[globalFaceI] = w[j]*sf[faceI];
+                                    }
+                                    subFaceI++;
+                                }
+                            }
+                        }
+                        else
+                        {
+                            forAll(pp.faceCells(), faceI)
+                            {
+                                const label globalFaceI =
+                                    mesh.faceBoundMap()[i][patchI][faceI];
+
+                                if (globalFaceI != -1)
+                                {
+                                    faceAreas[globalFaceI] = sf[faceI];
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        agglomerate
+        (
+            mesh,
+            mag
+            (
+                cmptMultiply
+                (
+                    faceAreas/sqrt(mag(faceAreas)),
+                    vector(1, 1.01, 1.02)
+                )
+            )
+        );
+    }
+    else
+    {
+        // Revert to faceAreaPairGAMGAgglomeration
+        const fvMesh& fvmesh = refCast<const fvMesh>(matrix.mesh());
+
+        agglomerate
+        (
+            matrix.mesh(),
+            mag
+            (
+                cmptMultiply
+                (
+                    fvmesh.Sf().primitiveField()
+                   /sqrt(fvmesh.magSf().primitiveField()),
+                    vector(1, 1.01, 1.02)
+                    //vector::one
+                )
+            )
+        );
+    }
+}
+
+
+Foam::assemblyFaceAreaPairGAMGAgglomeration::
+assemblyFaceAreaPairGAMGAgglomeration
+(
+    const lduMatrix& matrix,
+    const scalarField& cellVolumes,
+    const vectorField& faceAreas,
+    const dictionary& controlDict
+)
+:
+    pairGAMGAgglomeration(matrix.mesh(), controlDict)
+{
+    agglomerate
+    (
+        matrix.mesh(),
+        mag
+        (
+            cmptMultiply
+            (
+                faceAreas/sqrt(mag(faceAreas)),
+                vector(1, 1.01, 1.02)
+            )
+        )
+    );
+}
+
+
+// ************************************************************************* //
diff --git a/src/finiteVolume/lduPrimitiveMeshAssembly/assemblyFaceAreaPairGAMGAgglomeration/assemblyFaceAreaPairGAMGAgglomeration.H b/src/finiteVolume/lduPrimitiveMeshAssembly/assemblyFaceAreaPairGAMGAgglomeration/assemblyFaceAreaPairGAMGAgglomeration.H
new file mode 100644
index 0000000000000000000000000000000000000000..3792fb75fc8571a4eb3aa4b3a0b83e8a17b215a8
--- /dev/null
+++ b/src/finiteVolume/lduPrimitiveMeshAssembly/assemblyFaceAreaPairGAMGAgglomeration/assemblyFaceAreaPairGAMGAgglomeration.H
@@ -0,0 +1,93 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2019 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+Class
+    Foam::assemblyFaceAreaPairGAMGAgglomeration
+
+Description
+    Agglomerate using the pair algorithm.
+
+SourceFiles
+    assemblyFaceAreaPairGAMGAgglomeration.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef assemblyFaceAreaPairGAMGAgglomeration_H
+#define assemblyFaceAreaPairGAMGAgglomeration_H
+
+#include "pairGAMGAgglomeration.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+/*---------------------------------------------------------------------------*\
+            Class assemblyFaceAreaPairGAMGAgglomeration Declaration
+\*---------------------------------------------------------------------------*/
+
+class assemblyFaceAreaPairGAMGAgglomeration
+:
+    public pairGAMGAgglomeration
+{
+public:
+
+    //- Runtime type information
+    TypeName("assembledFaceAreaPair");
+
+
+    //- Destructor
+    ~assemblyFaceAreaPairGAMGAgglomeration();
+
+
+    // Constructors
+
+        //- Construct given mesh and controls
+        assemblyFaceAreaPairGAMGAgglomeration
+        (
+            const lduMatrix& matrix,
+            const dictionary& controlDict
+        );
+
+        //- Construct given mesh and controls
+        assemblyFaceAreaPairGAMGAgglomeration
+        (
+            const lduMatrix& matrix,
+            const scalarField& cellVolumes,
+            const vectorField& faceAreas,
+            const dictionary& controlDict
+        );
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/finiteVolume/lduPrimitiveMeshAssembly/lduPrimitiveMeshAssembly.C b/src/finiteVolume/lduPrimitiveMeshAssembly/lduPrimitiveMeshAssembly.C
new file mode 100644
index 0000000000000000000000000000000000000000..22d9955a7003765da7639024500cdf486b83484e
--- /dev/null
+++ b/src/finiteVolume/lduPrimitiveMeshAssembly/lduPrimitiveMeshAssembly.C
@@ -0,0 +1,159 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2019 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+\*---------------------------------------------------------------------------*/
+
+#include "lduPrimitiveMeshAssembly.H"
+#include "mappedPatchBase.H"
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+namespace Foam
+{
+    defineTypeNameAndDebug(lduPrimitiveMeshAssembly, 0);
+}
+
+
+// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
+
+Foam::label Foam::lduPrimitiveMeshAssembly::totalSize
+(
+    const UPtrList<lduMesh>& meshes
+)
+{
+    label tot = 0;
+
+    forAll(meshes, meshi)
+    {
+        tot += meshes[meshi].lduAddr().size();
+    }
+
+    return tot;
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::lduPrimitiveMeshAssembly::lduPrimitiveMeshAssembly
+(
+    const IOobject& io,
+    const UPtrList<lduMesh>& meshes
+)
+:
+    regIOobject(io),
+    lduPrimitiveMesh(totalSize(meshes)),
+    meshes_(meshes)
+{
+    forAll(meshes, meshi)
+    {
+        if (meshes[meshi].comm() != comm())
+        {
+            WarningInFunction
+                << "Communicator " << meshes[meshi].comm()
+                << " at index " << meshi
+                << " differs between meshes " << nl;
+        }
+    }
+
+    updateMaps(meshes);
+}
+
+
+Foam::lduPrimitiveMeshAssembly::lduPrimitiveMeshAssembly
+(
+    const IOobject& io,
+    const lduMesh& mesh
+)
+:
+    regIOobject(io),
+    lduPrimitiveMesh(mesh.lduAddr().size()),
+    meshes_(1)
+{
+    meshes_.set(0, const_cast<lduMesh*>(&mesh));
+    updateMaps(meshes_);
+}
+
+// * * * * * * * * * * * * * Public Member Functions  * * * * * * * * * * * //
+
+
+void Foam::lduPrimitiveMeshAssembly::updateMaps
+(
+    const UPtrList<lduMesh>& meshes
+)
+{
+    const label nMeshes = meshes.size();
+    patchMap_.setSize(nMeshes);
+    patchLocalToGlobalMap_.setSize(nMeshes);
+    faceMap_.setSize(nMeshes);
+    faceBoundMap_.setSize(nMeshes);
+    cellBoundMap_.setSize(nMeshes);
+
+    facePatchFaceMap_.setSize(nMeshes);
+
+    // Determine cellOffset and faceOffset
+    cellOffsets_.setSize(1+nMeshes);
+    cellOffsets_[0] = 0;
+    for (label meshi=0; meshi < nMeshes; ++meshi)
+    {
+        cellOffsets_[meshi+1] =
+            cellOffsets_[meshi] + meshes[meshi].lduAddr().size();
+    }
+
+    for (label i=0; i < nMeshes; ++i)
+    {
+        patchMap_[i].setSize(meshes_[i].interfaces().size(), -1);
+        patchLocalToGlobalMap_[i].setSize(patchMap_[i].size(), -1);
+
+        faceBoundMap_[i].setSize(patchMap_[i].size());
+        cellBoundMap_[i].setSize(patchMap_[i].size());
+        facePatchFaceMap_[i].setSize(patchMap_[i].size());
+    }
+}
+
+
+Foam::label Foam::lduPrimitiveMeshAssembly::findNbrMeshId
+(
+    const polyPatch& pp,
+    const label iMesh
+) const
+{
+    if (pp.neighbRegionID() != "none")
+    {
+        forAll(meshes_, meshi)
+        {
+            if (meshes_[meshi].thisDb().name() == pp.neighbRegionID())
+            {
+                return meshi;
+            }
+        }
+    }
+    else
+    {
+        return iMesh;
+    }
+    return -1;
+}
+
+// ************************************************************************* //
diff --git a/src/finiteVolume/lduPrimitiveMeshAssembly/lduPrimitiveMeshAssembly.H b/src/finiteVolume/lduPrimitiveMeshAssembly/lduPrimitiveMeshAssembly.H
new file mode 100644
index 0000000000000000000000000000000000000000..5a1edb355413f63167f1d0b22200f59b6f033665
--- /dev/null
+++ b/src/finiteVolume/lduPrimitiveMeshAssembly/lduPrimitiveMeshAssembly.H
@@ -0,0 +1,243 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2019 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+Class
+    Foam::lduPrimitiveMeshAssembly
+
+Description
+    An assembly of lduMatrix that is specific inter-region coupling
+    through mapped patches.
+
+SourceFiles
+    lduPrimitiveMeshAssembly.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef lduPrimitiveMeshAssembly_H
+#define lduPrimitiveMeshAssembly_H
+
+#include "fvMesh.H"
+#include "lduPrimitiveMesh.H"
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+/*---------------------------------------------------------------------------*\
+                  Class lduPrimitiveMeshAssembly Declaration
+\*---------------------------------------------------------------------------*/
+class lduPrimitiveMeshAssembly
+:
+    public regIOobject,
+    public lduPrimitiveMesh
+{
+    // Private Data
+
+        //- UPtrList for fvMesh
+        UPtrList<lduMesh> meshes_;
+
+        //- Overwrite patchAddr from lduPrimitiveMesh for assembly ldu address
+        List<labelList> patchAddr_;
+
+        //- Map from original to asembled (-1 for non-existing)
+        labelListList patchMap_;
+
+        //- Map from original to asembled plus extra virtual patch Ids
+        labelListList patchLocalToGlobalMap_;
+
+        //- Map internal faces from local to global
+        labelListList faceMap_;
+
+        //- Map patch local sub-face to global new internal face
+        labelListListList faceBoundMap_;
+
+        //- Map patch local sub-face to nbrCellId
+        labelListListList cellBoundMap_;
+
+        //- Map patch local sub-face to local patch face
+        labelListListList facePatchFaceMap_;
+
+        //- Offset cells
+        labelList cellOffsets_;
+
+
+    // Private Member Functions
+
+        //- Get size of all meshes
+        static label totalSize(const UPtrList<lduMesh>&);
+
+        //- No copy construct
+        lduPrimitiveMeshAssembly(const lduPrimitiveMeshAssembly&) = delete;
+
+        //- No copy assignment
+        void operator=(const lduPrimitiveMeshAssembly&) = delete;
+
+
+public:
+
+
+    // Static Data
+
+        // Declare name of the class and its debug switch
+        TypeName("lduPrimitiveMeshAssembly");
+
+
+    // Constructors
+
+        //- Construct from UPtrList of lduMesh
+        lduPrimitiveMeshAssembly
+        (
+            const IOobject& io,
+            const UPtrList<lduMesh>& meshes
+        );
+
+        //- Construct from one mesh
+        lduPrimitiveMeshAssembly
+        (
+            const IOobject& io,
+            const lduMesh&
+        );
+
+
+    //- Destructor
+    virtual ~lduPrimitiveMeshAssembly() = default;
+
+
+    // Public Member Functions
+
+        //- Update mappings
+        template<class Type>
+        void update
+        (
+            UPtrList<GeometricField<Type, fvPatchField, volMesh>>& psis
+        );
+
+        //- Size maps
+        void updateMaps(const UPtrList<lduMesh>&);
+
+        //- Find nrb mesh Id for mapped patches
+        label findNbrMeshId(const polyPatch& pp,const label iMesh) const;
+
+
+    // Access
+
+        //- Return the object registry
+        virtual const objectRegistry& thisDb() const
+        {
+            return meshes_[0].thisDb();
+        }
+
+        //- Return true if thisDb() is a valid DB
+        virtual bool hasDb() const
+        {
+            return true;
+        }
+
+        //- Return patch addressing
+        virtual const labelUList& patchAddr(const label patchNo) const
+        {
+            return patchAddr_[patchNo];
+        }
+
+        //- Return patchMap
+        const labelListList& patchMap() const
+        {
+            return patchMap_;
+        }
+
+        //- Return patchLocalToGlobalMap
+        const labelListList& patchLocalToGlobalMap() const
+        {
+            return patchLocalToGlobalMap_;
+        }
+
+        //- Return boundary face map
+        const labelListListList& faceBoundMap() const
+        {
+            return faceBoundMap_;
+        }
+
+        //- Return patch local sub-face to nbrCellId map
+        const labelListListList& cellBoundMap() const
+        {
+            return cellBoundMap_;
+        }
+
+        //- Return patch local sub-face to local patch face map
+        const labelListListList& facePatchFaceMap() const
+        {
+            return facePatchFaceMap_;
+        }
+
+        //- Return cellOffsets
+        const labelList& cellOffsets() const
+        {
+            return cellOffsets_;
+        }
+
+        //- Return faceMap
+        const labelListList& faceMap() const
+        {
+            return faceMap_;
+        }
+
+        //- Return patchAddr
+        const List<labelList>& patchAddr() const
+        {
+            return patchAddr_;
+        }
+
+        //- Return fvMeshes
+        const UPtrList<lduMesh>& meshes() const
+        {
+            return meshes_;
+        }
+
+        //- Write Data
+        virtual bool writeData(Ostream&) const
+        {
+            NotImplemented;
+            return false;
+        }
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#ifdef NoRepository
+    #include "lduPrimitiveMeshAssemblyTemplates.C"
+#endif
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/finiteVolume/lduPrimitiveMeshAssembly/lduPrimitiveMeshAssemblyTemplates.C b/src/finiteVolume/lduPrimitiveMeshAssembly/lduPrimitiveMeshAssemblyTemplates.C
new file mode 100644
index 0000000000000000000000000000000000000000..91c389e85f8d45db92ccde51f2b74a2fd4f2a298
--- /dev/null
+++ b/src/finiteVolume/lduPrimitiveMeshAssembly/lduPrimitiveMeshAssemblyTemplates.C
@@ -0,0 +1,492 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2019 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+\*---------------------------------------------------------------------------*/
+
+#include "lduPrimitiveMeshAssembly.H"
+
+#include "cyclicFvPatch.H"
+#include "cyclicAMIFvPatch.H"
+#include "cyclicACMIFvPatch.H"
+
+#include "lduPrimitiveProcessorInterface.H"
+#include "AssemblyFvPatch.H"
+
+// * * * * * * * * * * * * * Public Member Functions  * * * * * * * * * * * //
+
+template<class Type>
+void Foam::lduPrimitiveMeshAssembly::update
+(
+    UPtrList<GeometricField<Type, fvPatchField, volMesh>>& psis
+)
+{
+    label newFaces(0);
+    label newFacesProc(0);
+    label newPatches(0);
+
+    const label nMeshes(meshes_.size());
+
+    for (label i=0; i < nMeshes; ++i)
+    {
+        forAll(meshes_[i].interfaces(), patchI)
+        {
+            const polyPatch& pp = psis[i].mesh().boundaryMesh()[patchI];
+            const fvPatchField<Type>& fvp = psis[i].boundaryField()[patchI];
+
+            if (fvp.useImplicit())
+            {
+                if (pp.masterImplicit())
+                {
+                    label newFacesPatch(0);
+                    label newFacesProcPatch(0);
+
+                    pp.newInternalProcFaces(newFacesPatch, newFacesProcPatch);
+
+                    newFaces += newFacesPatch;
+                    newFacesProc += newFacesProcPatch;
+
+                    if (newFacesProc > 0)
+                    {
+                        FatalErrorInFunction
+                            << "The number of faces on either side of the "
+                            << "coupled patch " << patchI << " are not "
+                            << "the same. "
+                            << "This might be due to the decomposition used. "
+                            << "Please use decomposition preserving implicit "
+                            << "patches on a single processor."
+                            << exit(FatalError);
+                    }
+
+                    cellBoundMap_[i][patchI].setSize(newFacesPatch, -1);
+                    facePatchFaceMap_[i][patchI].setSize(newFacesPatch, -1);
+                    faceBoundMap_[i][patchI].setSize(newFacesPatch, -1);
+
+                    const label nbrId = pp.neighbPolyPatchID();
+                    const label meshNrbId = findNbrMeshId(pp, i);
+
+                    cellBoundMap_[meshNrbId][nbrId].setSize
+                    (
+                        newFacesPatch,
+                        -1
+                    );
+                    facePatchFaceMap_[meshNrbId][nbrId].setSize
+                    (
+                        newFacesPatch,
+                        -1
+                    );
+                    faceBoundMap_[meshNrbId][nbrId].setSize
+                    (
+                        newFacesPatch,
+                        -1
+                    );
+                }
+            }
+            else
+            {
+                patchMap_[i][patchI] = newPatches;
+                patchLocalToGlobalMap_[i][patchI] = newPatches;
+                newPatches++;
+            }
+        }
+    }
+
+    label virtualPatches = newPatches;
+
+    // patchLocalToGlobalMap: map from original to asembled + extra Ids
+
+    for (label i=0; i < nMeshes; ++i)
+    {
+        forAll(meshes_[i].interfaces(), patchI)
+        {
+            if (patchLocalToGlobalMap_[i][patchI] == -1)
+            {
+                patchLocalToGlobalMap_[i][patchI] = virtualPatches++;
+            }
+        }
+    }
+
+    DebugInfo << patchMap_ << endl;
+    DebugInfo << patchLocalToGlobalMap_ << endl;
+
+    label oldFaces(0);
+    // Add the internal faces for each mesh
+    for (label i=0; i < nMeshes; ++i)
+    {
+        newFaces += meshes_[i].lduAddr().upperAddr().size();
+        oldFaces += meshes_[i].lduAddr().upperAddr().size();
+    }
+
+    if (debug)
+    {
+        Info<< " old total faces : " << oldFaces
+            << " new total faces (internal) : " << newFaces
+            << " new faces (remote) : " << newFacesProc
+            << " new Faces : " << newFaces - oldFaces << endl;
+
+        Info<< " new patches : " << newPatches << endl;
+
+        Info<< "Local to Global patch Map  : "
+            << patchLocalToGlobalMap_ << endl;
+    }
+
+    // This gives the global cellId given the local patchId for interfaces
+    patchAddr_.setSize(newPatches);
+
+    for (label i=0; i < nMeshes; ++i)
+    {
+        const lduInterfacePtrsList interfacesLst = meshes_[i].interfaces();
+
+        forAll(interfacesLst, patchI)
+        {
+            label globalPatchId = patchMap_[i][patchI];
+
+            if (globalPatchId != -1)
+            {
+                const labelUList& faceCells =
+                    meshes_[i].lduAddr().patchAddr(patchI);
+
+                // Fill local patchAddr for standard patches
+                if (!faceCells.empty())
+                {
+                    patchAddr_[globalPatchId].setSize(faceCells.size(), -1);
+
+                    for (label celli = 0; celli < faceCells.size(); ++celli)
+                    {
+                        patchAddr_[globalPatchId][celli] =
+                            cellOffsets_[i] + faceCells[celli];
+                    }
+                }
+            }
+        }
+    }
+
+    // Interfaces
+    interfaces().setSize(newPatches);
+    // Primitive interfaces
+    primitiveInterfaces().setSize(newPatches);
+
+    // The interfaces are conserved (cyclics, proc, etc)
+    for (label i=0; i < nMeshes; ++i)
+    {
+        const lduInterfacePtrsList interfacesLst = meshes_[i].interfaces();
+
+        forAll(interfacesLst, patchI)
+        {
+            label globalPatchId = patchMap_[i][patchI];
+            if (globalPatchId != -1)
+            {
+                if (interfacesLst.set(patchI))
+                {
+                    const polyPatch& pp =
+                        psis[i].mesh().boundaryMesh()[patchI];
+
+                    const fvBoundaryMesh& bm = psis[i].mesh().boundary();
+
+                    if (isA<cyclicLduInterface>(interfacesLst[patchI]))
+                    {
+                        label nbrId = refCast
+                            <const cyclicLduInterface>
+                            (
+                                interfacesLst[patchI]
+                            ).neighbPatchID();
+
+                        label globalNbr = patchMap()[i][nbrId];
+
+                        primitiveInterfaces().set
+                        (
+                            globalPatchId,
+                            new AssemblyFvPatch<cyclicFvPatch>
+                            (
+                                pp,
+                                bm,
+                                patchAddr_[globalNbr],
+                                patchAddr_[globalPatchId],
+                                globalNbr
+                            )
+                        );
+
+                        interfaces().set
+                        (
+                            globalPatchId,
+                            &primitiveInterfaces()[globalPatchId]
+                        );
+                    }
+                    else if
+                    (
+                        isA<cyclicAMILduInterface>(interfacesLst[patchI])
+                    )
+                    {
+                        label nbrId =
+                            refCast
+                            <
+                                const cyclicAMIPolyPatch
+                            >(pp).neighbPatchID();
+
+                        label globalNbr = patchMap()[i][nbrId];
+
+                        primitiveInterfaces().set
+                        (
+                            globalPatchId,
+                            new AssemblyFvPatch<cyclicAMIFvPatch>
+                            (
+                                pp,
+                                bm,
+                                patchAddr_[globalNbr],
+                                patchAddr_[globalPatchId],
+                                globalNbr
+                            )
+                        );
+                        interfaces().set
+                        (
+                            globalPatchId,
+                            &primitiveInterfaces()[globalPatchId]
+                        );
+                    }
+                    else if
+                    (
+                        isA<cyclicACMILduInterface>(interfacesLst[patchI])
+                    )
+                    {
+                        label nbrId =
+                            refCast
+                            <
+                                const cyclicACMIPolyPatch
+                            >(pp).neighbPatchID();
+
+                        label globalNbr = patchMap()[i][nbrId];
+
+                        label nonOverlId =
+                            refCast
+                            <
+                                const cyclicACMIPolyPatch
+                            >(pp).nonOverlapPatchID();
+
+                        label globalnonOverlId = patchMap()[i][nonOverlId];
+
+                        primitiveInterfaces().set
+                        (
+                            globalPatchId,
+                            new AssemblyFvPatch<cyclicACMIFvPatch>
+                            (
+                                pp,
+                                bm,
+                                patchAddr_[globalNbr],
+                                patchAddr_[globalPatchId],
+                                globalNbr,
+                                globalnonOverlId
+                            )
+                        );
+                        interfaces().set
+                        (
+                            globalPatchId,
+                            &primitiveInterfaces()[globalPatchId]
+                        );
+                    }
+                    else
+                    {
+                        primitiveInterfaces().set
+                        (
+                            globalPatchId,
+                            nullptr
+                        );
+                        interfaces().set
+                        (
+                            globalPatchId,
+                            interfacesLst(patchI)
+                        );
+                    }
+                }
+            }
+        }
+    }
+
+    // Create new lower/upper addressing
+    lowerAddr().setSize(newFaces, -1);
+    upperAddr().setSize(newFaces, -1);
+
+    label startIndex = 0;
+
+    for (label i=0; i < nMeshes; ++i)
+    {
+        faceMap_[i].setSize(meshes_[i].lduAddr().lowerAddr().size(), -1);
+
+        const label nFaces = meshes_[i].lduAddr().upperAddr().size();
+
+        // Add individual addresses
+        SubList<label>(lowerAddr(), nFaces, startIndex) =
+            meshes_[i].lduAddr().lowerAddr();
+
+        SubList<label>(upperAddr(), nFaces, startIndex) =
+            meshes_[i].lduAddr().upperAddr();
+
+        // Offset cellsIDs to global cell addressing
+        label localFacei = 0;
+
+        for (label facei=startIndex; facei < startIndex + nFaces; ++facei)
+        {
+            lowerAddr()[facei] += cellOffsets_[i];
+            upperAddr()[facei] += cellOffsets_[i];
+
+            faceMap_[i][localFacei++] = facei;
+        }
+
+        startIndex += nFaces;
+    }
+    // Add new lower/upper adressing for new internal faces corresponding
+    // to patch faces that has a correspondent on the slave patch
+    // (i.e map, AMI,etc)
+    // Don't include faces that are in different proc
+
+    label nFaces = startIndex;
+
+    for (label i=0; i < nMeshes; ++i)
+    {
+        const lduInterfacePtrsList interfacesLst = meshes_[i].interfaces();
+
+        forAll(interfacesLst, patchI)
+        {
+            const polyPatch& pp = psis[i].mesh().boundaryMesh()[patchI];
+
+            const fvPatchField<Type>& fvp = psis[i].boundaryField()[patchI];
+
+            if (fvp.useImplicit())
+            {
+                label meshNrbId = this->findNbrMeshId(pp, i);
+
+                if (pp.masterImplicit())
+                {
+                    const labelUList& nbrFaceCells = pp.nbrCells();
+                    const label nbrPatchId = pp.neighbPolyPatchID();
+                    refPtr<labelListList> tlocalFaceToFace =
+                        pp.mapCollocatedFaces();
+
+                    const labelListList& localFaceToFace = tlocalFaceToFace();
+
+                    // Compact target map
+                    // key() = local face in proci
+                    // *iter = compactId
+
+                    label subFaceI(0);
+                    forAll(pp.faceCells(), faceI)
+                    {
+                        const label cellI =
+                            pp.faceCells()[faceI] + cellOffsets_[i];
+
+                        const labelList& facesIds = localFaceToFace[faceI];
+
+                        forAll(facesIds, j)
+                        {
+                            label nbrFaceId = facesIds[j];
+
+                            // local faces
+                            const label nbrCellI =
+                                nbrFaceCells[nbrFaceId]
+                              + cellOffsets_[meshNrbId];
+
+                            lowerAddr()[nFaces] = min(cellI, nbrCellI);
+                            upperAddr()[nFaces] = max(cellI, nbrCellI);
+
+                            cellBoundMap_[i][patchI][subFaceI] = nbrCellI;
+                            cellBoundMap_[meshNrbId][nbrPatchId][subFaceI] =
+                                cellI;
+
+                            facePatchFaceMap_[i][patchI][subFaceI] = faceI;
+                            facePatchFaceMap_[meshNrbId][nbrPatchId][subFaceI]
+                                = nbrFaceId;
+
+                            faceBoundMap_[i][patchI][subFaceI] = nFaces;
+                            faceBoundMap_[meshNrbId][nbrPatchId][subFaceI] =
+                                nFaces;
+
+                            ++subFaceI;
+                            ++nFaces;
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    if (newFaces != nFaces)
+    {
+       FatalErrorInFunction
+            << "Incorrrect total number of faces in the assembled lduMatrix: "
+            << newFaces << " != " << nFaces << nl
+            << exit(FatalError);
+    }
+
+    // Sort upper-tri order
+    {
+        labelList oldToNew
+        (
+            upperTriOrder
+            (
+                lduAddr().size(),
+                lowerAddr(),
+                upperAddr()
+            )
+        );
+        inplaceReorder(oldToNew, lowerAddr());
+        inplaceReorder(oldToNew, upperAddr());
+
+        for (labelList& faceMap : faceMap_)
+        {
+            for (label& facei : faceMap)
+            {
+                facei = oldToNew[facei];
+            }
+        }
+
+        for (labelListList& bMap : faceBoundMap_)
+        {
+            for (labelList& faceMap : bMap)
+            {
+                for (label& facei : faceMap)
+                {
+                    if (facei != -1)
+                    {
+                        facei = oldToNew[facei];
+                    }
+                }
+            }
+        }
+    }
+
+    if (debug & 2)
+    {
+        DebugVar(faceBoundMap_);
+        DebugVar(cellBoundMap_);
+        DebugVar(lowerAddr());
+        DebugVar(upperAddr());
+        DebugVar(patchAddr_);
+        DebugVar(cellOffsets_);
+        DebugVar(faceMap_);
+        (checkUpperTriangular(lduAddr().size(), lowerAddr(), upperAddr()));
+        DebugVar(lduAddr().size())
+    }
+}
+
+
+// ************************************************************************* //
diff --git a/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolation.H b/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolation.H
index f691d6ace3c9bb430352ee0ac0f5237702a36e96..1bdf85457f778b28199f2991c38dcdfc1c031249 100644
--- a/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolation.H
+++ b/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolation.H
@@ -137,6 +137,7 @@ protected:
             autoPtr<mapDistribute> srcMapPtr_;
 
 
+
         // Target patch
 
             //- Target face areas
diff --git a/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolationI.H b/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolationI.H
index 1effda038534ba3eda4b9915dfbfcea305874db6..3471bc2eefeaaa93a30e790dd74d329376533422 100644
--- a/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolationI.H
+++ b/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolationI.H
@@ -233,5 +233,4 @@ inline const Foam::mapDistribute& Foam::AMIInterpolation::tgtMap() const
     return *tgtMapPtr_;
 }
 
-
 // ************************************************************************* //
diff --git a/src/meshTools/AMIInterpolation/GAMG/interfaceFields/cyclicACMIGAMGInterfaceField/cyclicACMIGAMGInterfaceField.C b/src/meshTools/AMIInterpolation/GAMG/interfaceFields/cyclicACMIGAMGInterfaceField/cyclicACMIGAMGInterfaceField.C
index 582a785a0d670c130f49a9b55759ea4b4ee90801..6f9ff748de42f02822e006347f8ba844b761e503 100644
--- a/src/meshTools/AMIInterpolation/GAMG/interfaceFields/cyclicACMIGAMGInterfaceField/cyclicACMIGAMGInterfaceField.C
+++ b/src/meshTools/AMIInterpolation/GAMG/interfaceFields/cyclicACMIGAMGInterfaceField/cyclicACMIGAMGInterfaceField.C
@@ -97,6 +97,8 @@ void Foam::cyclicACMIGAMGInterfaceField::updateInterfaceMatrix
 (
     solveScalarField& result,
     const bool add,
+    const lduAddressing& lduAddr,
+    const label patchId,
     const solveScalarField& psiInternal,
     const scalarField& coeffs,
     const direction cmpt,
@@ -104,10 +106,13 @@ void Foam::cyclicACMIGAMGInterfaceField::updateInterfaceMatrix
 ) const
 {
     // Get neighbouring field
-    solveScalarField pnf
-    (
-        cyclicACMIInterface_.neighbPatch().interfaceInternalField(psiInternal)
-    );
+    const labelList& nbrFaceCells =
+        lduAddr.patchAddr
+        (
+            cyclicACMIInterface_.neighbPatchID()
+        );
+
+    solveScalarField pnf(psiInternal, nbrFaceCells);
 
     // Transform according to the transformation tensors
     transformCoupleField(pnf, cmpt);
@@ -121,7 +126,9 @@ void Foam::cyclicACMIGAMGInterfaceField::updateInterfaceMatrix
         pnf = cyclicACMIInterface_.neighbPatch().AMI().interpolateToTarget(pnf);
     }
 
-    this->addToInternalField(result, !add, coeffs, 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 66968e583e3edf5af4012f64e993ececd2f97ded..21f09689e63f13d8dce9f6efc53170ef9e84fbec 100644
--- a/src/meshTools/AMIInterpolation/GAMG/interfaceFields/cyclicACMIGAMGInterfaceField/cyclicACMIGAMGInterfaceField.H
+++ b/src/meshTools/AMIInterpolation/GAMG/interfaceFields/cyclicACMIGAMGInterfaceField/cyclicACMIGAMGInterfaceField.H
@@ -127,6 +127,8 @@ public:
             (
                 solveScalarField& result,
                 const bool add,
+                const lduAddressing& lduAddr,
+                const label patchId,
                 const solveScalarField& psiInternal,
                 const scalarField& coeffs,
                 const direction cmpt,
diff --git a/src/meshTools/AMIInterpolation/GAMG/interfaceFields/cyclicAMIGAMGInterfaceField/cyclicAMIGAMGInterfaceField.C b/src/meshTools/AMIInterpolation/GAMG/interfaceFields/cyclicAMIGAMGInterfaceField/cyclicAMIGAMGInterfaceField.C
index 7994f63c766e51b9244fb2d2ed8971a78a55f00a..6b3d0e1913d283d9a54d6d2f8a2796734e002e46 100644
--- a/src/meshTools/AMIInterpolation/GAMG/interfaceFields/cyclicAMIGAMGInterfaceField/cyclicAMIGAMGInterfaceField.C
+++ b/src/meshTools/AMIInterpolation/GAMG/interfaceFields/cyclicAMIGAMGInterfaceField/cyclicAMIGAMGInterfaceField.C
@@ -97,6 +97,8 @@ void Foam::cyclicAMIGAMGInterfaceField::updateInterfaceMatrix
 (
     solveScalarField& result,
     const bool add,
+    const lduAddressing& lduAddr,
+    const label patchId,
     const solveScalarField& psiInternal,
     const scalarField& coeffs,
     const direction cmpt,
@@ -104,10 +106,14 @@ void Foam::cyclicAMIGAMGInterfaceField::updateInterfaceMatrix
 ) const
 {
     // Get neighbouring field
-    solveScalarField pnf
-    (
-        cyclicAMIInterface_.neighbPatch().interfaceInternalField(psiInternal)
-    );
+
+    const labelList& nbrFaceCells =
+        lduAddr.patchAddr
+        (
+            cyclicAMIInterface_.neighbPatchID()
+        );
+
+    solveScalarField pnf(psiInternal, nbrFaceCells);
 
     // Transform according to the transformation tensors
     transformCoupleField(pnf, cmpt);
@@ -121,7 +127,9 @@ void Foam::cyclicAMIGAMGInterfaceField::updateInterfaceMatrix
         pnf = cyclicAMIInterface_.neighbPatch().AMI().interpolateToTarget(pnf);
     }
 
-    this->addToInternalField(result, !add, coeffs, pnf);
+    const labelUList& faceCells = lduAddr.patchAddr(patchId);
+
+    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 10ed09314bc8ca7fbeba5fad32a9e8d988308c86..880d4bde2877fa544af8acace511e220fe14f90f 100644
--- a/src/meshTools/AMIInterpolation/GAMG/interfaceFields/cyclicAMIGAMGInterfaceField/cyclicAMIGAMGInterfaceField.H
+++ b/src/meshTools/AMIInterpolation/GAMG/interfaceFields/cyclicAMIGAMGInterfaceField/cyclicAMIGAMGInterfaceField.H
@@ -126,6 +126,8 @@ public:
             (
                 solveScalarField& result,
                 const bool add,
+                const lduAddressing& lduAddr,
+                const label patchId,
                 const solveScalarField& psiInternal,
                 const scalarField& coeffs,
                 const direction cmpt,
diff --git a/src/meshTools/AMIInterpolation/GAMG/interfaces/cyclicACMIGAMGInterface/cyclicACMIGAMGInterface.C b/src/meshTools/AMIInterpolation/GAMG/interfaces/cyclicACMIGAMGInterface/cyclicACMIGAMGInterface.C
index f31bb4876682c7dfb9625af60786b7e0a6e64c41..b1bbe31be590f4a664636b72b6ab4c35b7eb6d6d 100644
--- a/src/meshTools/AMIInterpolation/GAMG/interfaces/cyclicACMIGAMGInterface/cyclicACMIGAMGInterface.C
+++ b/src/meshTools/AMIInterpolation/GAMG/interfaces/cyclicACMIGAMGInterface/cyclicACMIGAMGInterface.C
@@ -168,7 +168,7 @@ Foam::cyclicACMIGAMGInterface::~cyclicACMIGAMGInterface()
 Foam::tmp<Foam::labelField>
 Foam::cyclicACMIGAMGInterface::internalFieldTransfer
 (
-    const Pstream::commsTypes,
+    const Pstream::commsTypes commsType,
     const labelUList& iF
 ) const
 {
@@ -176,7 +176,7 @@ Foam::cyclicACMIGAMGInterface::internalFieldTransfer
         dynamic_cast<const cyclicACMIGAMGInterface&>(neighbPatch());
     const labelUList& nbrFaceCells = nbr.faceCells();
 
-    tmp<labelField> tpnf(new labelField(nbrFaceCells.size()));
+    auto tpnf = tmp<labelField>::New(nbrFaceCells.size());
     labelField& pnf = tpnf.ref();
 
     forAll(pnf, facei)
diff --git a/src/meshTools/AMIInterpolation/GAMG/interfaces/cyclicAMIGAMGInterface/cyclicAMIGAMGInterface.C b/src/meshTools/AMIInterpolation/GAMG/interfaces/cyclicAMIGAMGInterface/cyclicAMIGAMGInterface.C
index 716ca9208bcaf5a192dc7593dfa5ec0b0c01d0cc..54194af015dc5ab96e50893e264a0d2f5d2d57bd 100644
--- a/src/meshTools/AMIInterpolation/GAMG/interfaces/cyclicAMIGAMGInterface/cyclicAMIGAMGInterface.C
+++ b/src/meshTools/AMIInterpolation/GAMG/interfaces/cyclicAMIGAMGInterface/cyclicAMIGAMGInterface.C
@@ -167,7 +167,7 @@ Foam::cyclicAMIGAMGInterface::~cyclicAMIGAMGInterface()
 
 Foam::tmp<Foam::labelField> Foam::cyclicAMIGAMGInterface::internalFieldTransfer
 (
-    const Pstream::commsTypes,
+    const Pstream::commsTypes commsType,
     const labelUList& iF
 ) const
 {
@@ -186,5 +186,4 @@ Foam::tmp<Foam::labelField> Foam::cyclicAMIGAMGInterface::internalFieldTransfer
     return tpnf;
 }
 
-
 // ************************************************************************* //
diff --git a/src/meshTools/AMIInterpolation/patches/cyclicACMI/cyclicACMIPolyPatch/cyclicACMIPolyPatch.C b/src/meshTools/AMIInterpolation/patches/cyclicACMI/cyclicACMIPolyPatch/cyclicACMIPolyPatch.C
index b7c63b027146c2c619d426640910f32a36c12429..4d4f1c61f6080c411af3c0ccab8bfe81979daf63 100644
--- a/src/meshTools/AMIInterpolation/patches/cyclicACMI/cyclicACMIPolyPatch/cyclicACMIPolyPatch.C
+++ b/src/meshTools/AMIInterpolation/patches/cyclicACMI/cyclicACMIPolyPatch/cyclicACMIPolyPatch.C
@@ -740,6 +740,65 @@ Foam::cyclicACMIPolyPatch::cyclicACMIPolyPatch
 
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
+void Foam::cyclicACMIPolyPatch::newInternalProcFaces
+(
+    label& newFaces,
+    label& newProcFaces
+) const
+{
+    const List<labelList>& addSourceFaces = AMI().srcAddress();
+    const scalarField& fMask = srcMask();
+
+    // Add new faces as many weights for AMI
+    forAll (addSourceFaces, faceI)
+    {
+        if (fMask[faceI] > tolerance_)
+        {
+            const labelList& nbrFaceIs = addSourceFaces[faceI];
+
+            forAll (nbrFaceIs, j)
+            {
+                label nbrFaceI = nbrFaceIs[j];
+
+                if (nbrFaceI < neighbPatch().size())
+                {
+                    // local faces
+                    newFaces++;
+                }
+                else
+                {
+                    // Proc faces
+                    newProcFaces++;
+                }
+            }
+        }
+    }
+}
+
+
+Foam::refPtr<Foam::labelListList> Foam::cyclicACMIPolyPatch::mapCollocatedFaces() const
+{
+    const scalarField& fMask = srcMask();
+    const labelListList& srcFaces = AMI().srcAddress();
+    labelListList dOverFaces;
+
+    dOverFaces.setSize(srcFaces.size());
+    forAll (dOverFaces, faceI)
+    {
+        if (fMask[faceI] > tolerance_)
+        {
+            dOverFaces[faceI].setSize(srcFaces[faceI].size());
+
+            forAll (dOverFaces[faceI], subFaceI)
+            {
+                dOverFaces[faceI][subFaceI] = srcFaces[faceI][subFaceI];
+            }
+        }
+    }
+    return refPtr<labelListList>(new labelListList(dOverFaces));
+}
+
+
 const Foam::cyclicACMIPolyPatch& Foam::cyclicACMIPolyPatch::neighbPatch() const
 {
     const polyPatch& pp = this->boundaryMesh()[neighbPatchID()];
diff --git a/src/meshTools/AMIInterpolation/patches/cyclicACMI/cyclicACMIPolyPatch/cyclicACMIPolyPatch.H b/src/meshTools/AMIInterpolation/patches/cyclicACMI/cyclicACMIPolyPatch/cyclicACMIPolyPatch.H
index a12b5ddeaa3e91bb77afc3ec822bdc33bba50739..5ed8b3e603e609191c6e714cf7e76c240b4c1c47 100644
--- a/src/meshTools/AMIInterpolation/patches/cyclicACMI/cyclicACMIPolyPatch/cyclicACMIPolyPatch.H
+++ b/src/meshTools/AMIInterpolation/patches/cyclicACMI/cyclicACMIPolyPatch/cyclicACMIPolyPatch.H
@@ -302,6 +302,15 @@ public:
 
     // Member Functions
 
+        // Implicit treatment functions
+
+            //- Return number of new internal sub-faces and new proc faces
+            virtual void newInternalProcFaces(label&, label&) const;
+
+            //- Return collocated faces
+            virtual refPtr<labelListList> mapCollocatedFaces() const;
+
+
         // Access
 
             //- Return a reference to the neighbour patch
diff --git a/src/meshTools/AMIInterpolation/patches/cyclicAMI/cyclicAMIPolyPatch/cyclicAMIPolyPatch.C b/src/meshTools/AMIInterpolation/patches/cyclicAMI/cyclicAMIPolyPatch/cyclicAMIPolyPatch.C
index 80ae52d33db8e24300f93054d010531df8021b5a..3ce1c4232c20ee25d23051d2281c614207d22c79 100644
--- a/src/meshTools/AMIInterpolation/patches/cyclicAMI/cyclicAMIPolyPatch/cyclicAMIPolyPatch.C
+++ b/src/meshTools/AMIInterpolation/patches/cyclicAMI/cyclicAMIPolyPatch/cyclicAMIPolyPatch.C
@@ -806,9 +806,40 @@ Foam::cyclicAMIPolyPatch::cyclicAMIPolyPatch
     faceCentres0_()
 {}
 
-
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
+void Foam::cyclicAMIPolyPatch::newInternalProcFaces
+(
+    label& newFaces,
+    label& newProcFaces
+) const
+{
+    const labelListList& addSourceFaces = AMI().srcAddress();
+
+    // Add new faces as many weights for AMI
+    forAll (addSourceFaces, faceI)
+    {
+        const labelList& nbrFaceIs = addSourceFaces[faceI];
+
+        forAll (nbrFaceIs, j)
+        {
+            label nbrFaceI = nbrFaceIs[j];
+
+            if (nbrFaceI < neighbPatch().size())
+            {
+                // local faces
+                newFaces++;
+            }
+            else
+            {
+                // Proc faces
+                newProcFaces++;
+            }
+        }
+    }
+}
+
+
 Foam::label Foam::cyclicAMIPolyPatch::neighbPatchID() const
 {
     if (nbrPatchID_ == -1)
diff --git a/src/meshTools/AMIInterpolation/patches/cyclicAMI/cyclicAMIPolyPatch/cyclicAMIPolyPatch.H b/src/meshTools/AMIInterpolation/patches/cyclicAMI/cyclicAMIPolyPatch/cyclicAMIPolyPatch.H
index 7ec4bf8f99b6e40f0e6ab1e73eaad13938ba5976..5b1fcdeb4458e756a23da659d6b122b7e0226caf 100644
--- a/src/meshTools/AMIInterpolation/patches/cyclicAMI/cyclicAMIPolyPatch/cyclicAMIPolyPatch.H
+++ b/src/meshTools/AMIInterpolation/patches/cyclicAMI/cyclicAMIPolyPatch/cyclicAMIPolyPatch.H
@@ -326,6 +326,38 @@ public:
 
     // Member Functions
 
+        // Implicit treatment functions
+
+            //- Return number of new internal of this polyPatch faces
+            virtual void newInternalProcFaces(label&, label&) const;
+
+
+            //- Return nbrCells
+            virtual const labelUList& nbrCells() const
+            {
+                return neighbPatch().faceCells();
+            }
+
+            //- Return nbr patch ID
+            virtual label neighbPolyPatchID() const
+            {
+                return neighbPatch().index();
+            }
+
+            //- Return collocated faces map
+            virtual refPtr<labelListList> mapCollocatedFaces() const
+            {
+                const labelListList& sourceFaces = AMI().srcAddress();
+                return refPtr<labelListList>(new labelListList(sourceFaces));
+            }
+
+            //- Return implicit master
+            virtual bool masterImplicit() const
+            {
+                return owner();
+            }
+
+
         // Access
 
             //- Tolerance used e.g. for area calculations/limits
@@ -418,7 +450,8 @@ public:
                     const label facei
                 ) const;
 
-                //- Transform a patch-based direction from this side to nbr side
+                //- Transform a patch-based direction from this side to
+                //  nbr side
                 virtual void reverseTransformDirection
                 (
                     vector& d,
diff --git a/src/meshTools/mappedPatches/mappedPolyPatch/mappedPatchBase.H b/src/meshTools/mappedPatches/mappedPolyPatch/mappedPatchBase.H
index 09bdd1367a8aae6c05b8adfc51a076246fc67398..fc327fc260ceeee1c8fcaa6bccaec5bf45cb88fd 100644
--- a/src/meshTools/mappedPatches/mappedPolyPatch/mappedPatchBase.H
+++ b/src/meshTools/mappedPatches/mappedPolyPatch/mappedPatchBase.H
@@ -524,6 +524,9 @@ public:
                 const bool forceUpdate = false
             ) const;
 
+            //- Is it owner
+            inline bool owner() const;
+
             //- Return a pointer to the AMI projection surface
             const autoPtr<Foam::searchableSurface>& surfPtr() const;
 
@@ -552,6 +555,7 @@ public:
                 const polyMesh::cellDecomposition
             );
 
+
         // For database storage
 
             inline const fileName& sampleDatabasePath() const
diff --git a/src/meshTools/mappedPatches/mappedPolyPatch/mappedPatchBaseI.H b/src/meshTools/mappedPatches/mappedPolyPatch/mappedPatchBaseI.H
index 2a3695d7cd8c4f968a30f6639105de6166279eaf..f80c3defb182e1a84c0bd68ba7c6d30674f12614 100644
--- a/src/meshTools/mappedPatches/mappedPolyPatch/mappedPatchBaseI.H
+++ b/src/meshTools/mappedPatches/mappedPolyPatch/mappedPatchBaseI.H
@@ -74,7 +74,7 @@ inline const Foam::word& Foam::mappedPatchBase::samplePatch() const
             FatalErrorInFunction
                 << "Supply either a patchName or a coupleGroup"
                 << " for patch " << patch_.name()
-                << " in region " << patch_.boundaryMesh().mesh().name()
+                << " in region " << patch_.boundaryMesh().mesh().name() << nl
                 << exit(FatalError);
         }
 
@@ -238,4 +238,10 @@ inline const Foam::AMIPatchToPatchInterpolation& Foam::mappedPatchBase::AMI
 }
 
 
+inline bool Foam::mappedPatchBase::owner() const
+{
+    return (patch_.boundaryMesh().mesh().name() < sampleRegion());
+}
+
+
 // ************************************************************************* //
diff --git a/src/meshTools/mappedPatches/mappedPolyPatch/mappedPolyPatch.H b/src/meshTools/mappedPatches/mappedPolyPatch/mappedPolyPatch.H
index d09a2665a52a698393f7ce17e3eb1a1028f0af3a..3dffd7328fad05f5cf226ce0f0c8cee39aaa8257 100644
--- a/src/meshTools/mappedPatches/mappedPolyPatch/mappedPolyPatch.H
+++ b/src/meshTools/mappedPatches/mappedPolyPatch/mappedPolyPatch.H
@@ -214,6 +214,60 @@ public:
             );
         }
 
+        // Implicit treatment functions
+
+            //- Return number of new internal of this polyPatch faces
+            virtual void newInternalProcFaces
+            (
+                label& iFaces,
+                label& pFaces
+            ) const
+            {
+                label nbrFaces =
+                    lookupPatch(sampleRegion_, samplePatch_).size();
+                iFaces = patch_.size();
+                pFaces = max(iFaces - nbrFaces, 0);
+            }
+
+
+            //- Return nbrCells
+            virtual const labelUList& nbrCells() const
+            {
+                return lookupPatch(sampleRegion_, samplePatch_).faceCells();
+            }
+
+            //- Return nbr patch ID
+            virtual label neighbPolyPatchID() const
+            {
+                return lookupPatch(sampleRegion_, samplePatch_).index();
+            }
+
+            //- Return collocated faces map
+            virtual refPtr<labelListList> mapCollocatedFaces() const
+            {
+                refPtr<labelListList> tMap(new labelListList(patch_.size()));
+                labelListList& map = tMap.ref();
+                forAll(map, i)
+                {
+                    labelList& subMap = map[i];
+                    subMap.setSize(1);
+                    subMap[0] = i;
+                }
+                return tMap;
+            }
+
+            //- Return implicit master
+            virtual bool masterImplicit() const
+            {
+                return owner();
+            }
+
+            //- Return neigh region ID
+            virtual word neighbRegionID() const
+            {
+                return sampleRegion_;
+            }
+
 
     //- Destructor
     virtual ~mappedPolyPatch();
diff --git a/src/meshTools/mappedPatches/mappedPolyPatch/mappedWallPolyPatch.H b/src/meshTools/mappedPatches/mappedPolyPatch/mappedWallPolyPatch.H
index e432ea192f827393852c2b4e041503b95929d5ff..271ac80d1973f2852c61a458e8b8afe27b2c1a0c 100644
--- a/src/meshTools/mappedPatches/mappedPolyPatch/mappedWallPolyPatch.H
+++ b/src/meshTools/mappedPatches/mappedPolyPatch/mappedWallPolyPatch.H
@@ -149,7 +149,7 @@ public:
         );
 
         //- Construct given the original patch and resetting the
-        //  face list and boundary mesh information
+        //- face list and boundary mesh information
         mappedWallPolyPatch
         (
             const mappedWallPolyPatch& pp,
@@ -176,7 +176,7 @@ public:
         }
 
         //- Construct and return a clone, resetting the face list
-        //  and boundary mesh
+        //- and boundary mesh
         virtual autoPtr<polyPatch> clone
         (
             const polyBoundaryMesh& bm,
@@ -199,7 +199,7 @@ public:
         }
 
         //- Construct and return a clone, resetting the face list
-        //  and boundary mesh
+        //- and boundary mesh
         virtual autoPtr<polyPatch> clone
         (
             const polyBoundaryMesh& bm,
@@ -221,6 +221,55 @@ public:
             );
         }
 
+        // Implicit treatment functions
+
+            //- Return number of new internal of this polyPatch faces
+            virtual void newInternalProcFaces(label& iFaces, label& pFaces) const
+            {
+                label nbrFaces = lookupPatch(sampleRegion_, samplePatch_).size();
+                iFaces = patch_.size();
+                pFaces = max(iFaces - nbrFaces, 0);
+            }
+
+
+            //- Return nbrCells
+            virtual const labelUList& nbrCells() const
+            {
+                return lookupPatch(sampleRegion_, samplePatch_).faceCells();
+            }
+
+            //- Return nbr patch ID
+            virtual label neighbPolyPatchID() const
+            {
+                return lookupPatch(sampleRegion_, samplePatch_).index();
+            }
+
+            //- Return collocated faces map
+            virtual refPtr<labelListList> mapCollocatedFaces() const
+            {
+                refPtr<labelListList> tMap(new labelListList(patch_.size()));
+                labelListList& map = tMap.ref();
+                forAll (map, i)
+                {
+                    labelList& subMap = map[i];
+                    subMap.setSize(1);
+                    subMap[0] = i;
+                }
+                return tMap;
+            }
+
+            //- Return implicit master
+            virtual bool masterImplicit() const
+            {
+                return owner();
+            }
+
+            //- Return neigh region ID
+            virtual word neighbRegionID() const
+            {
+                return sampleRegion_;
+            }
+
 
     //- Destructor
     virtual ~mappedWallPolyPatch();
diff --git a/src/overset/Make/files b/src/overset/Make/files
index 70acd1f108dd0965fdeadec3bfe439f16bc770c2..a8ebde68ba45e32313c4d6ee794667326505451a 100644
--- a/src/overset/Make/files
+++ b/src/overset/Make/files
@@ -23,8 +23,7 @@ oversetAdjustPhi/oversetAdjustPhi.C
 
 regionsToCell/regionsToCell.C
 
-lduPrimitiveProcessorInterface/lduPrimitiveProcessorInterface.C
-lduPrimitiveProcessorInterface/calculatedProcessorFvPatchFields.C
+
 lduPrimitiveProcessorInterface/GAMG/calculatedProcessorGAMGInterface.C
 lduPrimitiveProcessorInterface/GAMG/calculatedProcessorGAMGInterfaceField.C
 
diff --git a/src/overset/lduPrimitiveProcessorInterface/GAMG/calculatedProcessorGAMGInterface.C b/src/overset/lduPrimitiveProcessorInterface/GAMG/calculatedProcessorGAMGInterface.C
index f89982f1acecec01aaa1e60b9578b2b1cf0ea80b..e252801633ca1eeb1967e0230ed0df4da8cd4207 100644
--- a/src/overset/lduPrimitiveProcessorInterface/GAMG/calculatedProcessorGAMGInterface.C
+++ b/src/overset/lduPrimitiveProcessorInterface/GAMG/calculatedProcessorGAMGInterface.C
@@ -197,12 +197,26 @@ Foam::calculatedProcessorGAMGInterface::internalFieldTransfer
     const labelUList& iF
 ) const
 {
-    tmp<Field<label>> tfld(receive<label>(commsType, this->size()));
+    tmp<labelField> tfld(receive<label>(commsType, this->size()));
 
     return tfld;
 }
 
 
+Foam::tmp<Foam::labelField>
+Foam::calculatedProcessorGAMGInterface::internalFieldTransfer
+(
+    const Pstream::commsTypes commsType,
+    const labelUList& iF,
+    const labelUList& faceCells
+) const
+{
+    NotImplemented;
+
+    return tmp<labelField>::New(this->size(), Zero);
+}
+
+
 void Foam::calculatedProcessorGAMGInterface::write(Ostream& os) const
 {
     GAMGInterface::write(os);
diff --git a/src/overset/lduPrimitiveProcessorInterface/GAMG/calculatedProcessorGAMGInterface.H b/src/overset/lduPrimitiveProcessorInterface/GAMG/calculatedProcessorGAMGInterface.H
index 8428fab2cc56a4cd38222b8d33a84a2e8ce77798..5c3bf4ab7e9e98d0ac9d9c5c9fce20b635a4de49 100644
--- a/src/overset/lduPrimitiveProcessorInterface/GAMG/calculatedProcessorGAMGInterface.H
+++ b/src/overset/lduPrimitiveProcessorInterface/GAMG/calculatedProcessorGAMGInterface.H
@@ -150,7 +150,17 @@ public:
             ) const;
 
 
-        //- Processor interface functions
+            //- Transfer and return internal field adjacent to the interface
+            //- using faceCells mapping
+            virtual tmp<labelField> internalFieldTransfer
+            (
+                const Pstream::commsTypes commsType,
+                const labelUList& iF,
+                const labelUList& faceCells
+            ) const;
+
+
+        // Processor interface functions
 
             //- Return communicator used for sending
             virtual label comm() const
@@ -186,7 +196,7 @@ public:
         // I/O
 
             //- Write to stream
-            virtual void write(Ostream&) const;
+            virtual void write(Ostream& os) const;
 };
 
 
diff --git a/src/overset/lduPrimitiveProcessorInterface/GAMG/calculatedProcessorGAMGInterfaceField.C b/src/overset/lduPrimitiveProcessorInterface/GAMG/calculatedProcessorGAMGInterfaceField.C
index daef9e63c9b575169a823a61bb026a52e319912b..b856cd26a48db7aa023ceff7d8d07941bc7caecc 100644
--- a/src/overset/lduPrimitiveProcessorInterface/GAMG/calculatedProcessorGAMGInterfaceField.C
+++ b/src/overset/lduPrimitiveProcessorInterface/GAMG/calculatedProcessorGAMGInterfaceField.C
@@ -92,6 +92,8 @@ void Foam::calculatedProcessorGAMGInterfaceField::initInterfaceMatrixUpdate
 (
     solveScalarField&,
     const bool add,
+    const lduAddressing& lduAddr,
+    const label patchId,
     const solveScalarField& psiInternal,
     const scalarField&,
     const direction,
@@ -144,6 +146,8 @@ void Foam::calculatedProcessorGAMGInterfaceField::updateInterfaceMatrix
 (
     solveScalarField& result,
     const bool add,
+    const lduAddressing& lduAddr,
+    const label patchId,
     const solveScalarField&,
     const scalarField& coeffs,
     const direction cmpt,
@@ -155,6 +159,8 @@ void Foam::calculatedProcessorGAMGInterfaceField::updateInterfaceMatrix
         return;
     }
 
+    const labelUList& faceCells = lduAddr.patchAddr(patchId);
+
     if
     (
         commsType == Pstream::commsTypes::nonBlocking
@@ -180,7 +186,7 @@ void Foam::calculatedProcessorGAMGInterfaceField::updateInterfaceMatrix
         transformCoupleField(scalarReceiveBuf_, cmpt);
 
         // Multiply the field by coefficients and add into the result
-        addToInternalField(result, !add, coeffs, scalarReceiveBuf_);
+        addToInternalField(result, !add, faceCells, coeffs, scalarReceiveBuf_);
     }
     else
     {
@@ -194,7 +200,7 @@ void Foam::calculatedProcessorGAMGInterfaceField::updateInterfaceMatrix
         );
         transformCoupleField(pnf, cmpt);
 
-        addToInternalField(result, !add, coeffs, pnf);
+        addToInternalField(result, !add, faceCells, coeffs, pnf);
     }
 
     const_cast<calculatedProcessorGAMGInterfaceField&>(*this).updatedMatrix()
diff --git a/src/overset/lduPrimitiveProcessorInterface/GAMG/calculatedProcessorGAMGInterfaceField.H b/src/overset/lduPrimitiveProcessorInterface/GAMG/calculatedProcessorGAMGInterfaceField.H
index 8d583b368d8e45a9ff63cb8b73189eeaa2049766..53101421b3e3bc570a1a2242e1cce9094b02eda6 100644
--- a/src/overset/lduPrimitiveProcessorInterface/GAMG/calculatedProcessorGAMGInterfaceField.H
+++ b/src/overset/lduPrimitiveProcessorInterface/GAMG/calculatedProcessorGAMGInterfaceField.H
@@ -141,6 +141,8 @@ public:
             (
                 solveScalarField& result,
                 const bool add,
+                const lduAddressing& lduAddr,
+                const label patchId,
                 const solveScalarField& psiInternal,
                 const scalarField& coeffs,
                 const direction cmpt,
@@ -152,6 +154,8 @@ public:
             (
                 solveScalarField& result,
                 const bool add,
+                const lduAddressing& lduAddr,
+                const label patchId,
                 const solveScalarField& psiInternal,
                 const scalarField& coeffs,
                 const direction cmpt,
diff --git a/src/phaseSystemModels/reactingEuler/functionObjects/Make/options b/src/phaseSystemModels/reactingEuler/functionObjects/Make/options
index b50eca09b5fdbdfdc1dcee7b39c31e8eae687160..7f852f44651dcf7c53d6830f81d13f07c4358194 100644
--- a/src/phaseSystemModels/reactingEuler/functionObjects/Make/options
+++ b/src/phaseSystemModels/reactingEuler/functionObjects/Make/options
@@ -2,6 +2,7 @@ phaseSystem = $(LIB_SRC)/phaseSystemModels/reactingEuler
 
 EXE_INC = \
     -I${phaseSystem}/multiphaseSystem/lnInclude \
+    -I$(LIB_SRC)/meshTools/lnInclude \
     -I$(LIB_SRC)/finiteVolume/lnInclude \
     -I$(LIB_SRC)/thermophysicalModels/basic/lnInclude \
     -I$(LIB_SRC)/transportModels/compressible/lnInclude \
@@ -12,4 +13,5 @@ LIB_LIBS = \
     -lfiniteVolume \
     -lfieldFunctionObjects \
     -lreactingMultiphaseSystem \
-    -ldynamicMesh
+    -ldynamicMesh \
+    -lmeshTools
diff --git a/src/regionModels/surfaceFilmModels/kinematicSingleLayer/kinematicSingleLayer.C b/src/regionModels/surfaceFilmModels/kinematicSingleLayer/kinematicSingleLayer.C
index 2e98c357d5366b41fbaac01943bc00e4ebebe0f5..d448c5fdf6056533199325be891551ae27842335 100644
--- a/src/regionModels/surfaceFilmModels/kinematicSingleLayer/kinematicSingleLayer.C
+++ b/src/regionModels/surfaceFilmModels/kinematicSingleLayer/kinematicSingleLayer.C
@@ -348,7 +348,7 @@ void kinematicSingleLayer::solveThickness
 (
     const volScalarField& pu,
     const volScalarField& pp,
-    const fvVectorMatrix& UEqn
+    fvVectorMatrix& UEqn
 )
 {
     DebugInFunction << endl;
@@ -893,13 +893,14 @@ void kinematicSingleLayer::evolveRegion()
         tmp<volScalarField> tpu(this->pu());
 
         // Solve for momentum for U_
-        tmp<fvVectorMatrix> UEqn = solveMomentum(tpu(), tpp());
+        tmp<fvVectorMatrix> tUEqn = solveMomentum(tpu(), tpp());
+        fvVectorMatrix& UEqn = tUEqn.ref();
 
         // Film thickness correction loop
         for (int corr=1; corr<=nCorr_; corr++)
         {
             // Solve thickness for delta_
-            solveThickness(tpu(), tpp(), UEqn());
+            solveThickness(tpu(), tpp(), UEqn);
         }
     }
 
diff --git a/src/regionModels/surfaceFilmModels/kinematicSingleLayer/kinematicSingleLayer.H b/src/regionModels/surfaceFilmModels/kinematicSingleLayer/kinematicSingleLayer.H
index f4b38253f852cf4c30307b7b9d6b84994f1789b0..4ee45767695a4a6a6b252959015550152e87d7e5 100644
--- a/src/regionModels/surfaceFilmModels/kinematicSingleLayer/kinematicSingleLayer.H
+++ b/src/regionModels/surfaceFilmModels/kinematicSingleLayer/kinematicSingleLayer.H
@@ -292,7 +292,7 @@ protected:
             (
                 const volScalarField& pu,
                 const volScalarField& pp,
-                const fvVectorMatrix& UEqn
+                fvVectorMatrix& UEqn
             );
 
 
diff --git a/src/regionModels/surfaceFilmModels/thermoSingleLayer/thermoSingleLayer.C b/src/regionModels/surfaceFilmModels/thermoSingleLayer/thermoSingleLayer.C
index 6c947d1eaa7ae4e430d5cdcd8c86c8db4acc5cb5..d46132aa6f66ddfdff872f7cc7c02b58b3c83f30 100644
--- a/src/regionModels/surfaceFilmModels/thermoSingleLayer/thermoSingleLayer.C
+++ b/src/regionModels/surfaceFilmModels/thermoSingleLayer/thermoSingleLayer.C
@@ -625,7 +625,8 @@ void thermoSingleLayer::evolveRegion()
         tmp<volScalarField> tpp(this->pp());
 
         // Solve for momentum for U_
-        tmp<fvVectorMatrix> UEqn = solveMomentum(tpu(), tpp());
+        tmp<fvVectorMatrix> tUEqn = solveMomentum(tpu(), tpp());
+        fvVectorMatrix& UEqn = tUEqn.ref();
 
         // Solve energy for hs_ - also updates thermo
         solveEnergy();
@@ -634,7 +635,7 @@ void thermoSingleLayer::evolveRegion()
         for (int corr=1; corr<=nCorr_; corr++)
         {
             // Solve thickness for delta_
-            solveThickness(tpu(), tpp(), UEqn());
+            solveThickness(tpu(), tpp(), UEqn);
         }
     }
 
diff --git a/src/thermophysicalModels/basic/derivedFvPatchFields/mixedEnergy/mixedEnergyFvPatchScalarField.C b/src/thermophysicalModels/basic/derivedFvPatchFields/mixedEnergy/mixedEnergyFvPatchScalarField.C
index 5a36c0c61daa6d1f8ad52a3e809b78d7b01b8493..6b6aea5b16954953dfaddd5cf07c2203cf35dfe7 100644
--- a/src/thermophysicalModels/basic/derivedFvPatchFields/mixedEnergy/mixedEnergyFvPatchScalarField.C
+++ b/src/thermophysicalModels/basic/derivedFvPatchFields/mixedEnergy/mixedEnergyFvPatchScalarField.C
@@ -31,6 +31,7 @@ License
 #include "volFields.H"
 #include "basicThermo.H"
 
+#include "fvMatrix.H"
 
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
@@ -46,6 +47,7 @@ mixedEnergyFvPatchScalarField
     valueFraction() = 0.0;
     refValue() = 0.0;
     refGrad() = 0.0;
+    source() = 0.0;
 }
 
 
@@ -103,7 +105,6 @@ void Foam::mixedEnergyFvPatchScalarField::updateCoeffs()
     {
         return;
     }
-
     const basicThermo& thermo = basicThermo::lookupThermo(*this);
     const label patchi = patch().index();
 
@@ -129,6 +130,64 @@ void Foam::mixedEnergyFvPatchScalarField::updateCoeffs()
 }
 
 
+void Foam::mixedEnergyFvPatchScalarField::manipulateMatrix
+(
+    fvMatrix<scalar>& matrix,
+    const label mat,
+    const direction cmpt
+)
+{
+    const basicThermo& thermo = basicThermo::lookupThermo(*this);
+
+    label index = this->patch().index();
+
+    const label globalPatchID =
+        matrix.lduMeshAssembly().patchLocalToGlobalMap()[mat][index];
+
+    const mixedFvPatchField<scalar>& fPatch =
+        refCast<const mixedFvPatchField>(thermo.T().boundaryField()[index]);
+
+    const Field<scalar> intCoeffsCmpt
+    (
+        matrix.internalCoeffs()[globalPatchID].component(cmpt)
+    );
+
+    const scalarField sourceCorr(fPatch.source());
+
+    const labelUList& u = matrix.lduAddr().upperAddr();
+    const labelUList& l = matrix.lduAddr().lowerAddr();
+
+    const labelList& faceMap =
+        matrix.lduMeshAssembly().faceBoundMap()[mat][index];
+
+    forAll(faceMap, j)
+    {
+        label globalFaceI = faceMap[j];
+
+        if (globalFaceI != -1)
+        {
+            const scalar intCorr = -intCoeffsCmpt[j];
+            const scalar srcCorr = -sourceCorr[j];
+
+            if (this->patch().patch().masterImplicit())
+            {
+                matrix.diag()[u[globalFaceI]] -= intCorr;
+                if (matrix.asymmetric())
+                {
+                    matrix.lower()[globalFaceI] += intCorr;
+                }
+                matrix.source()[u[globalFaceI]] += srcCorr;
+            }
+            else
+            {
+                matrix.diag()[l[globalFaceI]] -= intCorr;
+                matrix.upper()[globalFaceI] += intCorr;
+                matrix.source()[l[globalFaceI]] += srcCorr;
+            }
+        }
+    }
+}
+
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
 namespace Foam
diff --git a/src/thermophysicalModels/basic/derivedFvPatchFields/mixedEnergy/mixedEnergyFvPatchScalarField.H b/src/thermophysicalModels/basic/derivedFvPatchFields/mixedEnergy/mixedEnergyFvPatchScalarField.H
index d540c4420c487a5f997bacc165d454b08b369542..882215f3d757f36390625e0e37ec609b7431d8e2 100644
--- a/src/thermophysicalModels/basic/derivedFvPatchFields/mixedEnergy/mixedEnergyFvPatchScalarField.H
+++ b/src/thermophysicalModels/basic/derivedFvPatchFields/mixedEnergy/mixedEnergyFvPatchScalarField.H
@@ -142,6 +142,14 @@ public:
 
             //- Update the coefficients associated with the patch field
             virtual void updateCoeffs();
+
+            //- Manipulate matrix
+            virtual void manipulateMatrix
+            (
+                fvMatrix<scalar>& m,
+                const label iMatrix,
+                const direction cmpt
+            );
 };
 
 
diff --git a/src/thermophysicalModels/basic/heThermo/heThermo.C b/src/thermophysicalModels/basic/heThermo/heThermo.C
index d967280551237405e76de7960d0ae02560d6e583..2b25c54e60d8716a8e6c556bfd84f749e8971853 100644
--- a/src/thermophysicalModels/basic/heThermo/heThermo.C
+++ b/src/thermophysicalModels/basic/heThermo/heThermo.C
@@ -82,6 +82,8 @@ void Foam::heThermo<BasicThermo, MixtureType>::init
             T.boundaryField()[patchi],
             patchi
         );
+
+        heBf[patchi].useImplicit() = T.boundaryField()[patchi].useImplicit();
     }
 
     this->heBoundaryCorrection(he);
diff --git a/src/thermophysicalModels/solidThermo/solidThermo/heSolidThermo.C b/src/thermophysicalModels/solidThermo/solidThermo/heSolidThermo.C
index b34b15b5f8554722319f9b1e43790029d6ba11a4..e2b581d21d7d8fb6f4021001b1d309e14cb9d3ec 100644
--- a/src/thermophysicalModels/solidThermo/solidThermo/heSolidThermo.C
+++ b/src/thermophysicalModels/solidThermo/solidThermo/heSolidThermo.C
@@ -39,8 +39,6 @@ void Foam::heSolidThermo<BasicSolidThermo, MixtureType>::calculate()
     const scalarField& hCells = this->he_;
     const scalarField& pCells = this->p_;
     scalarField& rhoCells = this->rho_.primitiveFieldRef();
-    //scalarField& psiCells = this->psi_.primitiveFieldRef();
-    //scalarField& muCells = this->mu_.primitiveFieldRef();
     scalarField& alphaCells = this->alpha_.primitiveFieldRef();
 
     forAll(TCells, celli)
@@ -62,8 +60,6 @@ void Foam::heSolidThermo<BasicSolidThermo, MixtureType>::calculate()
         }
 
         rhoCells[celli] = volMixture_.rho(pCells[celli], TCells[celli]);
-        //psiCells[celli] = volMixture_.psi(pCells[celli], TCells[celli]);
-        //muCells[celli] = volMixture_.mu(pCells[celli], TCells[celli]);
 
         alphaCells[celli] =
             volMixture_.kappa(pCells[celli], TCells[celli])
@@ -74,8 +70,6 @@ void Foam::heSolidThermo<BasicSolidThermo, MixtureType>::calculate()
     volScalarField::Boundary& pBf = this->p_.boundaryFieldRef();
     volScalarField::Boundary& TBf = this->T_.boundaryFieldRef();
     volScalarField::Boundary& rhoBf = this->rho_.boundaryFieldRef();
-    //volScalarField::Boundary& psiBf = this->psi_.boundaryFieldRef();
-    //volScalarField::Boundary& muBf = this->mu_.boundaryFieldRef();
     volScalarField::Boundary& heBf = this->he().boundaryFieldRef();
     volScalarField::Boundary& alphaBf = this->alpha_.boundaryFieldRef();
 
@@ -84,8 +78,6 @@ void Foam::heSolidThermo<BasicSolidThermo, MixtureType>::calculate()
         fvPatchScalarField& pp = pBf[patchi];
         fvPatchScalarField& pT = TBf[patchi];
         fvPatchScalarField& prho = rhoBf[patchi];
-        //fvPatchScalarField& ppsi = psiBf[patchi];
-        //fvPatchScalarField& pmu = muBf[patchi];
         fvPatchScalarField& phe = heBf[patchi];
         fvPatchScalarField& palpha = alphaBf[patchi];
 
@@ -105,11 +97,8 @@ void Foam::heSolidThermo<BasicSolidThermo, MixtureType>::calculate()
                         facei
                     );
 
-
                 phe[facei] = mixture_.HE(pp[facei], pT[facei]);
                 prho[facei] = volMixture_.rho(pp[facei], pT[facei]);
-                //ppsi[facei] = volMixture_.psi(pp[facei], pT[facei]);
-                //pmu[facei] = volMixture_.mu(pp[facei], pT[facei]);
 
                 palpha[facei] =
                     volMixture_.kappa(pp[facei], pT[facei])
@@ -138,8 +127,6 @@ void Foam::heSolidThermo<BasicSolidThermo, MixtureType>::calculate()
                 }
 
                 prho[facei] = volMixture_.rho(pp[facei], pT[facei]);
-                //ppsi[facei] = volMixture_.psi(pp[facei], pT[facei]);
-                //pmu[facei] = volMixture_.mu(pp[facei], pT[facei]);
 
                 palpha[facei] =
                     volMixture_.kappa(pp[facei], pT[facei])
diff --git a/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/0.orig/T b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/0.orig/T
new file mode 100644
index 0000000000000000000000000000000000000000..bce6faa6c4a27f24976b4124776cb80308f8321e
--- /dev/null
+++ b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/0.orig/T
@@ -0,0 +1,31 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2106                                 |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       volScalarField;
+    object      T;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+dimensions      [0 0 0 1 0 0 0];
+
+internalField   uniform 300;
+
+boundaryField
+{
+     #include "include/emptyPatches"
+    ".*"
+    {
+        type            calculated;
+        value           uniform 300;
+    }
+}
+
+// ************************************************************************* //
diff --git a/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/0.orig/U b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/0.orig/U
new file mode 100644
index 0000000000000000000000000000000000000000..9e934deaac118aedeb8b3a795bbe693c67839c61
--- /dev/null
+++ b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/0.orig/U
@@ -0,0 +1,31 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2106                                 |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       volVectorField;
+    object      U;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+dimensions      [0 1 -1 0 0 0 0];
+
+internalField   uniform (0.01 0 0);
+
+boundaryField
+{
+     #include "include/emptyPatches"
+    ".*"
+    {
+        type            calculated;
+        value           uniform (0.01 0 0);
+    }
+}
+
+// ************************************************************************* //
diff --git a/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/0.orig/epsilon b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/0.orig/epsilon
new file mode 100644
index 0000000000000000000000000000000000000000..cc12c263fc1b11503e655d6a4201ba9deabdd7af
--- /dev/null
+++ b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/0.orig/epsilon
@@ -0,0 +1,33 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2106                                 |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       volScalarField;
+    object      epsilon;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+dimensions      [0 2 -3 0 0 0 0];
+
+internalField   uniform 0.01;
+
+boundaryField
+{
+    #include "include/emptyPatches"
+
+    ".*"
+    {
+        type            calculated;
+        value           uniform 0.01;
+    }
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/0.orig/include/emptyPatches b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/0.orig/include/emptyPatches
new file mode 100644
index 0000000000000000000000000000000000000000..1e1756f17d36d8e29ebcb3903bc8bf66fcca5f1d
--- /dev/null
+++ b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/0.orig/include/emptyPatches
@@ -0,0 +1,20 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Web:      www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+
+minZ
+{
+    type empty;
+}
+
+maxZ
+{
+    type empty;
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/0.orig/k b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/0.orig/k
new file mode 100644
index 0000000000000000000000000000000000000000..e9adb29aa30f4f4125aebc0fdfa61e944e7e7bb9
--- /dev/null
+++ b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/0.orig/k
@@ -0,0 +1,32 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2106                                 |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       volScalarField;
+    object      k;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+dimensions      [0 2 -2 0 0 0 0];
+
+internalField   uniform 0.1;
+
+boundaryField
+{
+    #include "include/emptyPatches"
+    ".*"
+    {
+        type            calculated;
+        value           uniform 0.1;
+    }
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/0.orig/p b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/0.orig/p
new file mode 100644
index 0000000000000000000000000000000000000000..d6e788e069ef87a9077fa058cbbcf479cfb3e229
--- /dev/null
+++ b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/0.orig/p
@@ -0,0 +1,31 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2106                                 |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       volScalarField;
+    object      p;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+dimensions      [1 -1 -2 0 0 0 0];
+
+internalField   uniform 1e5;
+
+boundaryField
+{
+     #include "include/emptyPatches"
+    ".*"
+    {
+        type            calculated;
+        value           uniform 1e5;
+    }
+}
+
+// ************************************************************************* //
diff --git a/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/0.orig/p_rgh b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/0.orig/p_rgh
new file mode 100644
index 0000000000000000000000000000000000000000..e15315f35deb019261a863fdaed7fabd8da5bbb6
--- /dev/null
+++ b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/0.orig/p_rgh
@@ -0,0 +1,31 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2106                                 |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       volScalarField;
+    object      p_rgh;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+dimensions      [1 -1 -2 0 0 0 0];
+
+internalField   uniform 1e5;
+
+boundaryField
+{
+     #include "include/emptyPatches"
+    ".*"
+    {
+        type            calculated;
+        value           uniform 1e5;
+    }
+}
+
+// ************************************************************************* //
diff --git a/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/Allclean b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/Allclean
new file mode 100755
index 0000000000000000000000000000000000000000..711e9348ef5ce23a47a7d211d44b4bf3ac2fef91
--- /dev/null
+++ b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/Allclean
@@ -0,0 +1,11 @@
+#!/bin/sh
+cd ${0%/*} || exit 1                        # Run from this directory
+. $WM_PROJECT_DIR/bin/tools/CleanFunctions  # Tutorial clean functions
+
+cleanCase0
+
+rm -rf VTK
+rm -rf constant/cellToRegion
+rm -rf constant/*/polyMesh  # region meshes
+
+#------------------------------------------------------------------------------
diff --git a/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/Allmesh b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/Allmesh
new file mode 100755
index 0000000000000000000000000000000000000000..c25b4a9d74ce5a9e0a532b70d56f20027c2d92d7
--- /dev/null
+++ b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/Allmesh
@@ -0,0 +1,34 @@
+#!/bin/sh
+cd ${0%/*} || exit 1                        # Run from this directory
+. $WM_PROJECT_DIR/bin/tools/RunFunctions    # Tutorial run functions
+#------------------------------------------------------------------------------
+
+runApplication blockMesh
+runApplication topoSet
+rm log.topoSet
+runApplication topoSet -dict system/topoSetDict.f1
+# Restore initial fields
+restore0Dir
+
+runApplication splitMeshRegions -cellZones -overwrite
+
+# Remove fluid fields from solid regions (important for post-processing)
+for region in $(foamListRegions solid)
+do
+    rm -f 0/$region/{nut,alphat,epsilon,k,U,p_rgh}
+    rm -f processor*/0/$region/{nut,alphat,epsilon,k,U,p_rgh}
+done
+
+for region in $(foamListRegions)
+do
+    runApplication -s $region changeDictionary -region $region
+done
+
+runApplication createBaffles -region rightFluid -overwrite
+
+echo
+echo "Use paraFoam -touch-all to create files for paraview post-processing"
+echo
+echo "End"
+
+#------------------------------------------------------------------------------
diff --git a/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/Allrun b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/Allrun
new file mode 100755
index 0000000000000000000000000000000000000000..80d0e1968dc415594998d034fd02860fe34fff40
--- /dev/null
+++ b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/Allrun
@@ -0,0 +1,10 @@
+#!/bin/sh
+cd ${0%/*} || exit 1                        # Run from this directory
+. $WM_PROJECT_DIR/bin/tools/RunFunctions    # Tutorial run functions
+
+runApplication ./Allmesh
+
+# Run
+runApplication $(getApplication)
+
+#------------------------------------------------------------------------------
diff --git a/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/constant/g b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/constant/g
new file mode 100644
index 0000000000000000000000000000000000000000..9cd8d8d5612df3dbc432664c845a5f3e4b310348
--- /dev/null
+++ b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/constant/g
@@ -0,0 +1,20 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2106                                 |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       uniformDimensionedVectorField;
+    object      g;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+dimensions      [0 1 -2 0 0 0 0];
+value           (0 0 0);
+
+// ************************************************************************* //
diff --git a/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/constant/leftSolid/radiationProperties b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/constant/leftSolid/radiationProperties
new file mode 100644
index 0000000000000000000000000000000000000000..2b3e4e21b181e1498d90e58a58351a8146c4ecf7
--- /dev/null
+++ b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/constant/leftSolid/radiationProperties
@@ -0,0 +1,42 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2106                                 |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "constant";
+    object      radiationProperties;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+radiation       off;
+
+radiationModel  none;
+
+absorptionEmissionModel multiBandSolidAbsorptionEmission;
+
+multiBandSolidAbsorptionEmissionCoeffs
+{
+    absorptivity    (0.7 0.7);
+    emissivity      (0.7 0.7);
+}
+
+transmissivityModel     multiBandSolidTransmissivity;
+
+multiBandSolidTransmissivityCoeffs
+{
+    transmissivity    (0 0);
+}
+
+scatterModel    none;
+
+sootModel none;
+
+// ************************************************************************* //
diff --git a/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/constant/leftSolid/thermophysicalProperties b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/constant/leftSolid/thermophysicalProperties
new file mode 100644
index 0000000000000000000000000000000000000000..6d5a57ec976d87f7d2b5fd2de765d94118c2a65d
--- /dev/null
+++ b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/constant/leftSolid/thermophysicalProperties
@@ -0,0 +1,52 @@
+/*--------------------------------*- C++ -*----------------------------------* \
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2106                                 |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      thermophysicalProperties;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+thermoType
+{
+    type            heSolidThermo;
+    mixture         pureMixture;
+    transport       constIso;
+    thermo          hConst;
+    equationOfState rhoConst;
+    specie          specie;
+    energy          sensibleEnthalpy;
+}
+
+mixture
+{
+    specie
+    {
+        molWeight   12;
+    }
+
+    transport
+    {
+        kappa   80;
+    }
+
+    thermodynamics
+    {
+        Hf      0;
+        Cp      450;
+    }
+
+    equationOfState
+    {
+        rho     8000;
+    }
+}
+
+// ************************************************************************* //
diff --git a/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/constant/regionProperties b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/constant/regionProperties
new file mode 100644
index 0000000000000000000000000000000000000000..aa6cac145df10221aa11498a2b05ab4fad2111db
--- /dev/null
+++ b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/constant/regionProperties
@@ -0,0 +1,24 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2106                                 |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "constant";
+    object      regionProperties;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+regions
+(
+    fluid       (rightFluid)
+    solid       (leftSolid)
+);
+
+// ************************************************************************* //
diff --git a/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/constant/rightFluid/radiationProperties b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/constant/rightFluid/radiationProperties
new file mode 100644
index 0000000000000000000000000000000000000000..7ccb90e90939e95b72bc3b9945d70d4fc2d044b6
--- /dev/null
+++ b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/constant/rightFluid/radiationProperties
@@ -0,0 +1,30 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2106                                 |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "constant";
+    object      radiationProperties;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+radiation       off;
+
+radiationModel  none;
+
+absorptionEmissionModel none;
+
+scatterModel    none;
+
+sootModel       none;
+
+transmissivityModel none;
+
+// ************************************************************************* //
diff --git a/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/constant/rightFluid/thermophysicalProperties b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/constant/rightFluid/thermophysicalProperties
new file mode 100644
index 0000000000000000000000000000000000000000..a4eac2272d5dd8de6f7879031c0b1bfe8413a92e
--- /dev/null
+++ b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/constant/rightFluid/thermophysicalProperties
@@ -0,0 +1,47 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2106                                 |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      thermophysicalProperties;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+thermoType
+{
+    type            heRhoThermo;
+    mixture         pureMixture;
+    transport       const;
+    thermo          hConst;
+    equationOfState perfectGas;
+    specie          specie;
+    energy          sensibleEnthalpy;
+}
+
+mixture
+{
+    specie
+    {
+        molWeight       28.9;
+    }
+    thermodynamics
+    {
+        Cp              1000;
+        Hf              0;
+    }
+    transport
+    {
+        mu              1.8e-05;
+        Pr              0.7;
+    }
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/constant/rightFluid/turbulenceProperties b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/constant/rightFluid/turbulenceProperties
new file mode 100644
index 0000000000000000000000000000000000000000..85f36873d6e2341d3d8dbccc13d206fbd07508ee
--- /dev/null
+++ b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/constant/rightFluid/turbulenceProperties
@@ -0,0 +1,19 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2106                                 |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      turbulenceProperties;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+simulationType  laminar;
+
+// ************************************************************************* //
diff --git a/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/system/blockMeshDict b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/system/blockMeshDict
new file mode 100644
index 0000000000000000000000000000000000000000..3b48e46b110612972f6824d08435820c5a9997aa
--- /dev/null
+++ b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/system/blockMeshDict
@@ -0,0 +1,96 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2106                                 |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      blockMeshDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+scale   1;
+
+vertices
+(
+    (-0.1 -0.04  -0.05)
+    ( 0.1 -0.04  -0.05)
+    ( 0.1  0.04  -0.05)
+    (-0.1  0.04  -0.05)
+    (-0.1 -0.04   0.05)
+    ( 0.1 -0.04   0.05)
+    ( 0.1  0.04   0.05)
+    (-0.1  0.04   0.05)
+);
+
+blocks
+(
+    hex (0 1 2 3 4 5 6 7) (50 30 1) simpleGrading (1 1 1)
+);
+
+edges
+(
+);
+
+boundary
+(
+    maxY
+    {
+        type patch;
+        faces
+        (
+            (3 7 6 2)
+        );
+    }
+    minX
+    {
+        type patch;
+        faces
+        (
+            (0 4 7 3)
+        );
+    }
+    maxX
+    {
+        type patch;
+        faces
+        (
+            (2 6 5 1)
+        );
+    }
+    minY
+    {
+        type patch;
+        faces
+        (
+            (1 5 4 0)
+        );
+    }
+    minZ
+    {
+        type empty;
+        faces
+        (
+            (0 3 2 1)
+        );
+    }
+    maxZ
+    {
+        type empty;
+        faces
+        (
+            (4 5 6 7)
+        );
+    }
+);
+
+mergePatchPairs
+(
+);
+
+// ************************************************************************* //
diff --git a/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/system/controlDict b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/system/controlDict
new file mode 100644
index 0000000000000000000000000000000000000000..b30c8e4e5523e589237537f55d24cd989add5b17
--- /dev/null
+++ b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/system/controlDict
@@ -0,0 +1,57 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2106                                 |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "system";
+    object      controlDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+application     chtMultiRegionFoam;
+
+startFrom       startTime;
+
+startTime       0.00;
+
+stopAt          endTime;
+
+endTime         100;
+
+deltaT          0.0001;
+
+writeControl    adjustable;
+
+writeInterval   10;
+
+purgeWrite      0;
+
+writeFormat     ascii;
+
+writePrecision  8;
+
+writeCompression off;
+
+timeFormat      general;
+
+timePrecision   6;
+
+runTimeModifiable yes;
+
+maxCo           0.6;
+
+// Maximum diffusion number
+maxDi           10.0;
+
+adjustTimeStep  yes;
+
+maxDeltaT       1;
+
+// ************************************************************************* //
diff --git a/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/system/fvSchemes b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/system/fvSchemes
new file mode 100644
index 0000000000000000000000000000000000000000..bd5a89bc88bd5ae3b46332790efbd9f61aa02645
--- /dev/null
+++ b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/system/fvSchemes
@@ -0,0 +1,42 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2106                                 |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      fvSchemes;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+ddtSchemes
+{
+}
+
+gradSchemes
+{
+}
+
+divSchemes
+{
+}
+
+laplacianSchemes
+{
+}
+
+interpolationSchemes
+{
+}
+
+snGradSchemes
+{
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/system/fvSolution b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/system/fvSolution
new file mode 100644
index 0000000000000000000000000000000000000000..c41e10e9e9f25bb422fcbea40f9fd19e14514e38
--- /dev/null
+++ b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/system/fvSolution
@@ -0,0 +1,22 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2106                                 |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      fvSolution;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+PIMPLE
+{
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/system/leftSolid/changeDictionaryDict b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/system/leftSolid/changeDictionaryDict
new file mode 100644
index 0000000000000000000000000000000000000000..dfa626d419d17c58c1121c21b020bcf9db39731c
--- /dev/null
+++ b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/system/leftSolid/changeDictionaryDict
@@ -0,0 +1,47 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2106                                 |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      changeDictionaryDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+T
+{
+    internalField   uniform 300;
+
+    boundaryField
+    {
+        minX
+        {
+            type            fixedValue;
+            value           uniform 350;
+        }
+
+        "leftSolid_to_.*"
+        {
+            type            compressible::turbulentTemperatureRadCoupledMixed;
+            Tnbr            T;
+            qrNbr           none;
+            qr              none;
+            useImplicit     true;
+            kappaMethod     solidThermo;
+            value           uniform 300;
+        }
+
+        "minY|maxY"
+        {
+            type            zeroGradient;
+        }
+    }
+}
+
+// ************************************************************************* //
diff --git a/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/system/leftSolid/fvSchemes b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/system/leftSolid/fvSchemes
new file mode 100644
index 0000000000000000000000000000000000000000..2901236631eb4e9a0a83d85c12e252265d60caf4
--- /dev/null
+++ b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/system/leftSolid/fvSchemes
@@ -0,0 +1,50 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2106                                 |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "system/leftSolid";
+    object      fvSchemes;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+ddtSchemes
+{
+    default     Euler;
+}
+
+gradSchemes
+{
+    default         Gauss linear;
+}
+
+divSchemes
+{
+    default         none;
+}
+
+laplacianSchemes
+{
+    default             none;
+    laplacian(alpha,h)  Gauss linear uncorrected;
+}
+
+interpolationSchemes
+{
+    default         linear;
+}
+
+snGradSchemes
+{
+    default         uncorrected;
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/system/leftSolid/fvSolution b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/system/leftSolid/fvSolution
new file mode 100644
index 0000000000000000000000000000000000000000..8d0eb33742ba70e1b8260cd5429e63b15e1448f8
--- /dev/null
+++ b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/system/leftSolid/fvSolution
@@ -0,0 +1,40 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2106                                 |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      fvSolution;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+solvers
+{
+    h
+    {
+        solver           PBiCGStab;
+        preconditioner   DIC;
+        tolerance        1e-06;
+        relTol           0.1;
+    }
+
+    hFinal
+    {
+        $h;
+        tolerance        1e-06;
+        relTol           0;
+    }
+}
+
+PIMPLE
+{
+    nNonOrthogonalCorrectors 0;
+}
+
+// ************************************************************************* //
diff --git a/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/system/rightFluid/changeDictionaryDict b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/system/rightFluid/changeDictionaryDict
new file mode 100644
index 0000000000000000000000000000000000000000..e64ee8b92c0e75b5f7416f213dfb316bc28a4743
--- /dev/null
+++ b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/system/rightFluid/changeDictionaryDict
@@ -0,0 +1,108 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2106                                 |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      changeDictionaryDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+T
+{
+    internalField   uniform 300;
+
+    boundaryField
+    {
+        maxX
+        {
+            type            fixedValue;
+            value           uniform 350;
+        }
+
+        "rightFluid_to_.*"
+        {
+            type            compressible::turbulentTemperatureRadCoupledMixed;
+            Tnbr            T;
+            qrNbr           none;
+            qr              none;
+            kappaMethod     fluidThermo;
+            qrNbr           none;
+            qr              none;
+            useImplicit     true;
+            value           uniform 300;
+        }
+
+        "minY|maxY"
+        {
+            type            zeroGradient;
+        }
+    }
+}
+
+U
+{
+    internalField   uniform (0 0 0);
+
+    boundaryField
+    {
+         "minX|maxX|minY|maxY"
+        {
+            type            fixedValue;
+            value           uniform ( 0 0 0 );
+        }
+
+        "rightFluid_to_.*"
+        {
+            type            fixedValue;
+            value           uniform ( 0 0 0 );
+        }
+    }
+}
+
+p_rgh
+{
+    internalField   uniform 1e5;
+
+    boundaryField
+    {
+        "minX|maxX|minY|maxY"
+        {
+            type            fixedFluxPressure;
+            value           uniform 1e5;
+        }
+
+        "rightFluid_to_.*"
+        {
+            type            fixedFluxPressure;
+            value           uniform 1e5;
+        }
+    }
+}
+
+p
+{
+    internalField   uniform 1e5;
+
+    boundaryField
+    {
+        "minX|maxX|minY|maxY"
+        {
+            type            calculated;
+            value           uniform 1e5;
+        }
+        "rightFluid_to_.*"
+        {
+            type            calculated;
+            value           uniform 1e5;
+        }
+    }
+}
+
+// ************************************************************************* //
diff --git a/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/system/rightFluid/createBafflesDict b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/system/rightFluid/createBafflesDict
new file mode 100644
index 0000000000000000000000000000000000000000..aa02b3b8e8b4ec146efd38dc6a54e10bc4600beb
--- /dev/null
+++ b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/system/rightFluid/createBafflesDict
@@ -0,0 +1,79 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2106                                 |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      createBafflesDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+// Whether to convert internal faces only (so leave boundary faces intact).
+// This is only relevant if your face selection type can pick up boundary
+// faces.
+internalFacesOnly true;
+
+
+// Baffles to create.
+baffles
+{
+    cyclicFaces
+    {
+        //- Select faces and orientation through a searchableSurface
+        type        searchableSurface;
+        surface     searchablePlate;
+        origin      (0.061 -0.3 -0.3);
+        span        (0.0 0.6 0.6);
+
+        patches
+        {
+            master
+            {
+                //- Master side patch
+
+                name            porous_half0;
+                type            cyclic;
+                neighbourPatch  porous_half1;
+
+                //- Optional override of added patchfields. If not specified
+                //  any added patchfields are of type calculated.
+                patchFields
+                {
+                    p_rgh
+                    {
+                        type            cyclic;//porousBafflePressure;
+                        patchType       cyclic;
+                        D               1000;
+                        I               500;
+                        length          0.15;
+                        uniformJump     true;
+                        jump            uniform 0;
+                        value           uniform 0;
+                    }
+                }
+            }
+            slave
+            {
+                //- Slave side patch
+
+                name            porous_half1;
+                type            cyclic;
+                neighbourPatch  porous_half0;
+
+                patchFields
+                {
+                    ${...master.patchFields}
+                }
+            }
+        }
+    }
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/system/rightFluid/fvSchemes b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/system/rightFluid/fvSchemes
new file mode 100644
index 0000000000000000000000000000000000000000..8eb0db044216d6efa3b1685713a43beedfb67a91
--- /dev/null
+++ b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/system/rightFluid/fvSchemes
@@ -0,0 +1,61 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2106                                 |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "system/rightFluid";
+    object      fvSchemes;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+ddtSchemes
+{
+    default     Euler;
+}
+
+gradSchemes
+{
+     default         Gauss linear;
+}
+
+divSchemes
+{
+    default         none;
+
+    div(phi,U)          Gauss upwind;
+    div(phi,K)          Gauss upwind;
+    div(phi,h)          Gauss upwind;
+    div(phi,k)          Gauss upwind;
+
+    div(phi,epsilon)    Gauss upwind;
+
+    div(((rho*nuEff)*dev2(T(grad(U))))) Gauss linear;
+}
+
+laplacianSchemes
+{
+    default         Gauss linear corrected;
+}
+
+interpolationSchemes
+{
+    default         linear;
+}
+
+snGradSchemes
+{
+    default         corrected;
+}
+
+fluxRequired
+{
+    p_rgh;
+}
+// ************************************************************************* //
diff --git a/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/system/rightFluid/fvSolution b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/system/rightFluid/fvSolution
new file mode 100644
index 0000000000000000000000000000000000000000..060608a8cb45f4e918d9041cdac1d1b55a171916
--- /dev/null
+++ b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/system/rightFluid/fvSolution
@@ -0,0 +1,105 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2106                                 |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      fvSolution;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+solvers
+{
+    rho
+    {
+        solver          PCG;
+        preconditioner  DIC;
+        tolerance       1e-7;
+        relTol          0.1;
+    }
+
+    rhoFinal
+    {
+        $rho;
+        tolerance       1e-7;
+        relTol          0;
+    }
+
+    p_rgh
+    {
+        solver           GAMG;
+        tolerance        1e-7;
+        relTol           0.01;
+        preconditioner  DIC;
+        smoother         GaussSeidel;
+        agglomerator     assembledFaceAreaPair;
+        maxIter         100;
+        cacheAgglomeration  false;
+
+    }
+
+    p_rghFinal
+    {
+        $p_rgh;
+        tolerance        1e-7;
+        relTol           0;
+    }
+
+    h
+    {
+        solver           GAMG;
+        tolerance        1e-7;
+        relTol           0.01;
+        preconditioner  DIC;
+        smoother         GaussSeidel;
+        agglomerator     assembledFaceAreaPair;
+        cacheAgglomeration  false;
+    }
+
+    hFinal
+    {
+        $h;
+        tolerance        1e-7;
+        relTol           0;
+    }
+
+    "(U|k|epsilon|R)"
+    {
+        solver           PBiCGStab;
+        preconditioner   DILU;
+        tolerance        1e-7;
+        relTol           0.1;
+    }
+
+    "(U|k|epsilon|R)Final"
+    {
+        $U;
+        tolerance        1e-7;
+        relTol           0;
+    }
+}
+
+PIMPLE
+{
+    momentumPredictor   no;
+    nCorrectors         3;
+    nNonOrthogonalCorrectors 0;
+    pRefPoint        (0.09 0 0);
+    pRefValue       1e5;
+}
+
+relaxationFactors
+{
+    equations
+    {
+        ".*"           1;
+    }
+}
+
+// ************************************************************************* //
diff --git a/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/system/topoSetDict b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/system/topoSetDict
new file mode 100644
index 0000000000000000000000000000000000000000..54c9527acafddb8105c0a034d068604d9edae1ae
--- /dev/null
+++ b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/system/topoSetDict
@@ -0,0 +1,66 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2106                                 |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      topoSetDict;
+}
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+actions
+(
+    // leftSolid
+    {
+        name    heaterCellSet;
+        type    cellSet;
+        action  new;
+        source  boxToCell;
+        sourceInfo
+        {
+            box (-0.1001 -100 -100 )(0.0 100 100);
+        }
+    }
+    {
+        name    leftSolid;
+        type    cellZoneSet;
+        action  new;
+        source  setToCellZone;
+        sourceInfo
+        {
+            set heaterCellSet;
+        }
+    }
+
+    // rightFluid
+    {
+        name    rightFLuidCellSet;
+        type    cellSet;
+        action  new;
+        source  boxToCell;
+        sourceInfo
+        {
+            box (0.00 -100 -100 )(0.1001 100 100);
+        }
+    }
+    {
+        name    rightFluid;
+        type    cellZoneSet;
+        action  new;
+        source  setToCellZone;
+        sourceInfo
+        {
+            set rightFLuidCellSet;
+        }
+    }
+);
+
+
+// ************************************************************************* //
diff --git a/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/system/topoSetDict.f1 b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/system/topoSetDict.f1
new file mode 100755
index 0000000000000000000000000000000000000000..4cf6a8cb8f104223bd2a41ef3673cecb3f017ab1
--- /dev/null
+++ b/tutorials/basic/chtMultiRegionFoam/2DImplicitCyclic/system/topoSetDict.f1
@@ -0,0 +1,59 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Web:      www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      topoSetDict;
+}
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+actions
+(
+    // 0. Create cell sets
+    {
+        name    c1;
+        type    cellSet;
+        action  new;
+        source  zoneToCell;
+	    zones	(leftSolid);
+
+    }
+     {
+        name    f1;
+        type    faceSet;
+        action  new;
+        source  cellToFace;
+        option  all;
+	    sets	(c1);
+
+    }
+
+     {
+        name    c2;
+        type    cellSet;
+        action  new;
+        source  zoneToCell;
+	    zones	(rightFluid);
+
+    }
+     {
+        name    f2;
+        type    faceSet;
+        action  new;
+        source  cellToFace;
+        option  all;
+	    sets	(c2);
+
+    }
+);
+
+
+// ************************************************************************* //
diff --git a/tutorials/basic/laplacianFoam/implicitAMI/0/T b/tutorials/basic/laplacianFoam/implicitAMI/0/T
new file mode 100644
index 0000000000000000000000000000000000000000..e19204f63b2ed80359554d289c1f845d815899c6
--- /dev/null
+++ b/tutorials/basic/laplacianFoam/implicitAMI/0/T
@@ -0,0 +1,63 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       volScalarField;
+    object      T;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+dimensions      [0 0 0 1 0 0 0];
+
+internalField   uniform 1;
+
+boundaryField
+{
+    AMI1
+    {
+        type            cyclicAMI;
+        useImplicit     true;
+    }
+
+    AMI2
+    {
+        type            cyclicAMI;
+        useImplicit     true;
+    }
+
+    top
+    {
+        type            zeroGradient;
+    }
+
+    bottom
+    {
+        type            zeroGradient;
+    }
+
+    left
+    {
+        type            fixedValue;
+        value           uniform 1;
+    }
+
+    right
+    {
+        type            fixedValue;
+        value           uniform 0;
+    }
+
+    frontAndBack
+    {
+        type            empty;
+    }
+}
+
+// ************************************************************************* //
diff --git a/tutorials/basic/laplacianFoam/implicitAMI/constant/transportProperties b/tutorials/basic/laplacianFoam/implicitAMI/constant/transportProperties
new file mode 100644
index 0000000000000000000000000000000000000000..fb641eeeb3a2d644d8c349d81d6eaf43516f2e73
--- /dev/null
+++ b/tutorials/basic/laplacianFoam/implicitAMI/constant/transportProperties
@@ -0,0 +1,21 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "constant";
+    object      transportProperties;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+DT              4e-05;
+
+
+// ************************************************************************* //
diff --git a/tutorials/basic/laplacianFoam/implicitAMI/system/blockMeshDict b/tutorials/basic/laplacianFoam/implicitAMI/system/blockMeshDict
new file mode 100644
index 0000000000000000000000000000000000000000..4c8dde3327b7b55eaf92b92a103fa6daee35567f
--- /dev/null
+++ b/tutorials/basic/laplacianFoam/implicitAMI/system/blockMeshDict
@@ -0,0 +1,136 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      blockMeshDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+scale   0.1;
+
+vertices
+(
+    (0 0 0)
+    (0.5 0 0)
+    (0.5 1 0)
+    (0 1 0)
+    (0 0 0.1)
+    (0.5 0 0.1)
+    (0.5 1 0.1)
+    (0 1 0.1)
+
+
+    (0.5 0 0)
+    (1 0 0)
+    (1 1 0)
+    (0.5 1 0)
+    (0.5 0 0.1)
+    (1 0 0.1)
+    (1 1 0.1)
+    (0.5 1 0.1)
+
+);
+
+blocks
+(
+    //- Left block
+    hex (0 1 2 3 4 5 6 7) left (3 3 1) simpleGrading (1 1 1)
+
+    //- Right block
+    hex (8 9 10 11 12 13 14 15) right (2 2 1) simpleGrading (1 1 1)
+);
+
+edges
+(
+);
+
+boundary
+(
+    AMI1
+    {
+        type            cyclicAMI;
+        neighbourPatch  AMI2;
+        transform       noOrdering;
+        faces
+        (
+            (2 6 5 1)
+        );
+    }
+
+    AMI2
+    {
+        type            cyclicAMI;
+        neighbourPatch  AMI1;
+        transform       noOrdering;
+        faces
+        (
+            (8 12 15 11)
+        );
+    }
+
+    top
+    {
+        type patch;
+        faces
+        (
+            (3 7 6 2)
+
+            (11 15 14 10)
+        );
+    }
+    bottom
+    {
+        type patch;
+        faces
+        (
+            (1 5 4 0)
+
+            (9 13 12 8)
+        );
+    }
+    left
+    {
+        type patch;
+        faces
+        (
+            (0 4 7 3)
+
+        );
+    }
+
+    right
+    {
+        type patch;
+        faces
+        (
+            (10 14 13 9)
+        );
+    }
+
+    frontAndBack
+    {
+        type empty;
+        faces
+        (
+            (0 3 2 1)
+            (4 5 6 7)
+
+            (8 11 10 9)
+            (12 13 14 15)
+        );
+    }
+);
+
+mergePatchPairs
+(
+);
+
+// ************************************************************************* //
diff --git a/tutorials/basic/laplacianFoam/implicitAMI/system/controlDict b/tutorials/basic/laplacianFoam/implicitAMI/system/controlDict
new file mode 100644
index 0000000000000000000000000000000000000000..b5cc07fc54abfbdfd114a3d2ab2ffcf0e0e71429
--- /dev/null
+++ b/tutorials/basic/laplacianFoam/implicitAMI/system/controlDict
@@ -0,0 +1,74 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "system";
+    object      controlDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+libs        (utilityFunctionObjects);
+
+DebugSwitches
+{
+//    mappedPatchBase 2;
+//    syncObjects     2;
+}
+
+
+application     laplacianFoam;
+
+startFrom       startTime;  //latestTime;
+
+startTime       0;
+
+stopAt          endTime;
+
+endTime         1;
+
+deltaT          1;
+
+//writeControl    runTime;
+//writeInterval   0.1;
+writeControl    timeStep;
+writeInterval   1;
+
+purgeWrite      0;
+
+writeFormat     ascii;
+
+writePrecision  6;
+
+writeCompression off;
+
+timeFormat      general;
+
+timePrecision   6;
+
+runTimeModifiable true;
+
+//functions
+//{
+//    syncObjects
+//    {
+//        type        syncObjects;
+//        libs        (utilityFunctionObjects);
+//
+//        // Where is data located relative to runTime. Given as a filename
+//        // with every '/' indicating a sub-objectRegistry w.r.t. runTime.
+//        // Local data is under <root>/send/processorXXX. After execution
+//        // data will be under the corresponding <root>/receive/processorYYY
+//        // objectRegistry
+//        //root        "level0/level1/level2";
+//    }
+//}
+
+// ************************************************************************* //
diff --git a/tutorials/basic/laplacianFoam/implicitAMI/system/decomposeParDict b/tutorials/basic/laplacianFoam/implicitAMI/system/decomposeParDict
new file mode 100644
index 0000000000000000000000000000000000000000..a1ee695090139c706ea390e32d9ee2c6eb0d796f
--- /dev/null
+++ b/tutorials/basic/laplacianFoam/implicitAMI/system/decomposeParDict
@@ -0,0 +1,25 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    note        "mesh decomposition control dictionary";
+    object      decomposeParDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+//- The total number of domains (mandatory)
+numberOfSubdomains  2;
+
+//- The decomposition method (mandatory)
+method          hierarchical;
+n               (2 1 1);
+
+// ************************************************************************* //
diff --git a/tutorials/basic/laplacianFoam/implicitAMI/system/fvSchemes b/tutorials/basic/laplacianFoam/implicitAMI/system/fvSchemes
new file mode 100644
index 0000000000000000000000000000000000000000..028412c048bc60930f515133d664e80d877458a6
--- /dev/null
+++ b/tutorials/basic/laplacianFoam/implicitAMI/system/fvSchemes
@@ -0,0 +1,52 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "system";
+    object      fvSchemes;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+ddtSchemes
+{
+    default         steadyState;    //Euler;
+}
+
+gradSchemes
+{
+    default         Gauss linear;
+    grad(T)         Gauss linear;
+}
+
+divSchemes
+{
+    default         none;
+}
+
+laplacianSchemes
+{
+    default         none;
+    laplacian(DT,T) Gauss linear corrected;
+    laplacian(DTV,T) Gauss linear corrected;
+}
+
+interpolationSchemes
+{
+    default         linear;
+}
+
+snGradSchemes
+{
+    default         corrected;
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/basic/laplacianFoam/implicitAMI/system/fvSolution b/tutorials/basic/laplacianFoam/implicitAMI/system/fvSolution
new file mode 100644
index 0000000000000000000000000000000000000000..a7c94ca0baf966142adfbe3283a2d22ad68bb866
--- /dev/null
+++ b/tutorials/basic/laplacianFoam/implicitAMI/system/fvSolution
@@ -0,0 +1,35 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "system";
+    object      fvSolution;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+solvers
+{
+    T
+    {
+        solver          PCG;
+        preconditioner  DIC;
+        tolerance       1e-06;
+        relTol          0;
+    }
+}
+
+SIMPLE
+{
+    nNonOrthogonalCorrectors 2;
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/basic/simpleFoam/implicitAMI/0/U b/tutorials/basic/simpleFoam/implicitAMI/0/U
new file mode 100644
index 0000000000000000000000000000000000000000..b59bae518af5012f48fa8df3966930c00f846bea
--- /dev/null
+++ b/tutorials/basic/simpleFoam/implicitAMI/0/U
@@ -0,0 +1,65 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       volVectorField;
+    location    "0";
+    object      U;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+dimensions      [0 1 -1 0 0 0 0];
+
+internalField   uniform (0 0 0);
+
+boundaryField
+{
+    AMI1
+    {
+        type            cyclicAMI;
+    }
+
+    AMI2
+    {
+        type            cyclicAMI;
+    }
+
+    top
+    {
+        type            uniformFixedValue;
+        uniformValue    (0 0 0);
+    }
+
+    bottom
+    {
+        type            uniformFixedValue;
+        uniformValue    (0 0 0);
+    }
+
+    left
+    {
+        type            fixedValue;
+        value           uniform (1 0 0);
+    }
+
+    right
+    {
+        type            inletOutlet;
+        inletValue      uniform (0 0 0);
+    }
+
+    frontAndBack
+    {
+        type            empty;
+    }
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/basic/simpleFoam/implicitAMI/0/p b/tutorials/basic/simpleFoam/implicitAMI/0/p
new file mode 100644
index 0000000000000000000000000000000000000000..087273dcb15c574f1f0ba39b4758e75ff90dec67
--- /dev/null
+++ b/tutorials/basic/simpleFoam/implicitAMI/0/p
@@ -0,0 +1,62 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       volScalarField;
+    object      p;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+dimensions      [0 2 -2 0 0 0 0];
+
+internalField   uniform 0;
+
+boundaryField
+{
+    AMI1
+    {
+        type            cyclicAMI;
+        useImplicit     true;
+    }
+
+    AMI2
+    {
+        type            cyclicAMI;
+        useImplicit     true;
+    }
+
+    top
+    {
+        type            zeroGradient;
+    }
+
+    bottom
+    {
+        type            zeroGradient;
+    }
+
+    left
+    {
+        type            zeroGradient;
+    }
+
+    right
+    {
+        type            fixedValue;
+        value           uniform 0;
+    }
+
+    frontAndBack
+    {
+        type            empty;
+    }
+}
+
+// ************************************************************************* //
diff --git a/tutorials/basic/simpleFoam/implicitAMI/constant/transportProperties b/tutorials/basic/simpleFoam/implicitAMI/constant/transportProperties
new file mode 100644
index 0000000000000000000000000000000000000000..baa44bd7118cf93cc2b2c6db3d5e8b6171efc992
--- /dev/null
+++ b/tutorials/basic/simpleFoam/implicitAMI/constant/transportProperties
@@ -0,0 +1,26 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "constant";
+    object      transportProperties;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+//- For laplacianFoam
+DT              4e-05;
+
+//- For simpleFoam
+transportModel  Newtonian;
+nu              1.5e-05;
+
+
+// ************************************************************************* //
diff --git a/tutorials/basic/simpleFoam/implicitAMI/constant/turbulenceProperties b/tutorials/basic/simpleFoam/implicitAMI/constant/turbulenceProperties
new file mode 100644
index 0000000000000000000000000000000000000000..459ba7cb9cda229c95eff12b850d83459f6b30d3
--- /dev/null
+++ b/tutorials/basic/simpleFoam/implicitAMI/constant/turbulenceProperties
@@ -0,0 +1,19 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      turbulenceProperties;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+simulationType laminar;
+
+// ************************************************************************* //
diff --git a/tutorials/basic/simpleFoam/implicitAMI/system/blockMeshDict b/tutorials/basic/simpleFoam/implicitAMI/system/blockMeshDict
new file mode 100644
index 0000000000000000000000000000000000000000..016c18f56b3cc2f19d8fb3f8c62fd90fc0d92273
--- /dev/null
+++ b/tutorials/basic/simpleFoam/implicitAMI/system/blockMeshDict
@@ -0,0 +1,136 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      blockMeshDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+scale   0.1;
+
+vertices
+(
+    (0 0 0)
+    (0.5 0 0)
+    (0.5 1 0)
+    (0 1 0)
+    (0 0 0.1)
+    (0.5 0 0.1)
+    (0.5 1 0.1)
+    (0 1 0.1)
+
+
+    (0.5    0 0)
+    (1      1 0)
+    (1      2 0)
+    (0.5    1 0)
+    (0.5    0 0.1)
+    (1      1 0.1)
+    (1      2 0.1)
+    (0.5    1 0.1)
+
+);
+
+blocks
+(
+    //- Left block
+    hex (0 1 2 3 4 5 6 7) left (2 5 1) simpleGrading (1 1 1)
+
+    //- Right block
+    hex (8 9 10 11 12 13 14 15) right (2 7 1) simpleGrading (1 1 1)
+);
+
+edges
+(
+);
+
+boundary
+(
+    AMI1
+    {
+        type            cyclicAMI;
+        neighbourPatch  AMI2;
+        transform       noOrdering;
+        faces
+        (
+            (2 6 5 1)
+        );
+    }
+
+    AMI2
+    {
+        type            cyclicAMI;
+        neighbourPatch  AMI1;
+        transform       noOrdering;
+        faces
+        (
+            (8 12 15 11)
+        );
+    }
+
+    top
+    {
+        type patch;
+        faces
+        (
+            (3 7 6 2)
+
+            (11 15 14 10)
+        );
+    }
+    bottom
+    {
+        type patch;
+        faces
+        (
+            (1 5 4 0)
+
+            (9 13 12 8)
+        );
+    }
+    left
+    {
+        type patch;
+        faces
+        (
+            (0 4 7 3)
+
+        );
+    }
+
+    right
+    {
+        type patch;
+        faces
+        (
+            (10 14 13 9)
+        );
+    }
+
+    frontAndBack
+    {
+        type empty;
+        faces
+        (
+            (0 3 2 1)
+            (4 5 6 7)
+
+            (8 11 10 9)
+            (12 13 14 15)
+        );
+    }
+);
+
+mergePatchPairs
+(
+);
+
+// ************************************************************************* //
diff --git a/tutorials/basic/simpleFoam/implicitAMI/system/controlDict b/tutorials/basic/simpleFoam/implicitAMI/system/controlDict
new file mode 100644
index 0000000000000000000000000000000000000000..28332681516adda7679521b442aa35b2c0cdcbb5
--- /dev/null
+++ b/tutorials/basic/simpleFoam/implicitAMI/system/controlDict
@@ -0,0 +1,58 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "system";
+    object      controlDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+libs        (utilityFunctionObjects);
+
+DebugSwitches
+{
+//    fvScalarMatrix      2;
+//    fvVectorMatrix      2;
+//    fvMatrix            2;
+}
+
+
+application     simpleFoam;
+
+startFrom       startTime;
+
+startTime       0;
+
+stopAt          endTime;
+
+endTime         100;
+
+deltaT          1;
+
+writeControl    timeStep;
+
+writeInterval   10;
+
+purgeWrite      0;
+
+writeFormat     ascii;
+
+writePrecision  6;
+
+writeCompression off;
+
+timeFormat      general;
+
+timePrecision   6;
+
+runTimeModifiable true;
+
+// ************************************************************************* //
diff --git a/tutorials/basic/simpleFoam/implicitAMI/system/decomposeParDict b/tutorials/basic/simpleFoam/implicitAMI/system/decomposeParDict
new file mode 100644
index 0000000000000000000000000000000000000000..a1ee695090139c706ea390e32d9ee2c6eb0d796f
--- /dev/null
+++ b/tutorials/basic/simpleFoam/implicitAMI/system/decomposeParDict
@@ -0,0 +1,25 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    note        "mesh decomposition control dictionary";
+    object      decomposeParDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+//- The total number of domains (mandatory)
+numberOfSubdomains  2;
+
+//- The decomposition method (mandatory)
+method          hierarchical;
+n               (2 1 1);
+
+// ************************************************************************* //
diff --git a/tutorials/basic/simpleFoam/implicitAMI/system/fvSchemes b/tutorials/basic/simpleFoam/implicitAMI/system/fvSchemes
new file mode 100644
index 0000000000000000000000000000000000000000..c6bfe543455c29eacd55003a16408676f0688709
--- /dev/null
+++ b/tutorials/basic/simpleFoam/implicitAMI/system/fvSchemes
@@ -0,0 +1,57 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "system";
+    object      fvSchemes;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+ddtSchemes
+{
+    default         steadyState;
+}
+
+gradSchemes
+{
+    default         Gauss linear;
+    grad(T)         Gauss linear;
+}
+
+divSchemes
+{
+    default         none;
+    div(phi,U)      bounded Gauss linear;
+    div((nuEff*dev2(T(grad(U))))) Gauss linear;
+}
+
+laplacianSchemes
+{
+    default             none;
+    laplacian(DT,T)     Gauss linear corrected;
+    laplacian(DTV,T)    Gauss linear corrected;
+    laplacian(nuEff,U)  Gauss linear corrected;
+    laplacian((1|A(U)),p) Gauss linear corrected;
+    laplacian((1|((1|(1|A(U)))-H(1))),p)    Gauss linear corrected;
+}
+
+interpolationSchemes
+{
+    default         linear;
+}
+
+snGradSchemes
+{
+    default         corrected;
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/basic/simpleFoam/implicitAMI/system/fvSolution b/tutorials/basic/simpleFoam/implicitAMI/system/fvSolution
new file mode 100644
index 0000000000000000000000000000000000000000..803c5fad28402069a8beef51ed43abae2a530086
--- /dev/null
+++ b/tutorials/basic/simpleFoam/implicitAMI/system/fvSolution
@@ -0,0 +1,61 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "system";
+    object      fvSolution;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+solvers
+{
+    p
+    {
+        solver          PCG;
+        preconditioner  DIC;
+        tolerance       1e-7;
+        relTol          0.01;
+    }
+    U
+    {
+        solver          smoothSolver;
+        smoother        GaussSeidel;
+        tolerance       1e-8;
+        relTol          0.1;
+        nSweeps         1;
+    }
+}
+
+SIMPLE
+{
+    nNonOrthogonalCorrectors 0;
+    consistent true;
+}
+
+relaxationFactors
+{
+    equations
+    {
+        U               0.9;
+    }
+
+    fields
+    {
+        p               0.6;
+    }
+}
+
+cache
+{
+    grad(U);
+}
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/0.orig/T b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/0.orig/T
new file mode 100644
index 0000000000000000000000000000000000000000..ceb543abd8fdfb626bfded274a6d60c6414374a5
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/0.orig/T
@@ -0,0 +1,32 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       volScalarField;
+    object      T;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+dimensions      [0 0 0 1 0 0 0];
+
+internalField   uniform 300;
+
+boundaryField
+{
+    #includeEtc "caseDicts/setConstraintTypes"
+
+    ".*"
+    {
+        type    calculated;
+        value   $internalField;
+    }
+}
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/0.orig/U b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/0.orig/U
new file mode 100644
index 0000000000000000000000000000000000000000..d9c6293414468282d81f9306255689ded7e7bfa1
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/0.orig/U
@@ -0,0 +1,32 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       volVectorField;
+    object      U;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+dimensions      [0 1 -1 0 0 0 0];
+
+internalField   uniform (0.01 0 0);
+
+boundaryField
+{
+    #includeEtc "caseDicts/setConstraintTypes"
+
+    ".*"
+    {
+        type    calculated;
+        value   $internalField;
+    }
+}
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/0.orig/alphat b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/0.orig/alphat
new file mode 100644
index 0000000000000000000000000000000000000000..522f12c70d1dcdee8060ffc09242648af3b1d0e7
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/0.orig/alphat
@@ -0,0 +1,32 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       volScalarField;
+    object      alphat;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+dimensions      [1 -1 -1 0 0 0 0];
+
+internalField   uniform 0;
+
+boundaryField
+{
+    #includeEtc "caseDicts/setConstraintTypes"
+
+    ".*"
+    {
+        type    calculated;
+        value   $internalField;
+    }
+}
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/0.orig/epsilon b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/0.orig/epsilon
new file mode 100644
index 0000000000000000000000000000000000000000..ed05c8aa30e37950cd1f20077583322d45c23549
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/0.orig/epsilon
@@ -0,0 +1,32 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       volScalarField;
+    object      epsilon;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+dimensions      [0 2 -3 0 0 0 0];
+
+internalField   uniform 0.01;
+
+boundaryField
+{
+    #includeEtc "caseDicts/setConstraintTypes"
+
+    ".*"
+    {
+        type    calculated;
+        value   $internalField;
+    }
+}
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/0.orig/k b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/0.orig/k
new file mode 100644
index 0000000000000000000000000000000000000000..170238229cc9e0a443a8078d95d3fe7f90568d9a
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/0.orig/k
@@ -0,0 +1,32 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       volScalarField;
+    object      k;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+dimensions      [0 2 -2 0 0 0 0];
+
+internalField   uniform 0.1;
+
+boundaryField
+{
+    #includeEtc "caseDicts/setConstraintTypes"
+
+    ".*"
+    {
+        type    calculated;
+        value   $internalField;
+    }
+}
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/0.orig/p b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/0.orig/p
new file mode 100644
index 0000000000000000000000000000000000000000..bc3cc84cd475fb01fd088bb54dd19d8e5f7e1edc
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/0.orig/p
@@ -0,0 +1,32 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       volScalarField;
+    object      p;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+dimensions      [1 -1 -2 0 0 0 0];
+
+internalField   uniform 1e5;
+
+boundaryField
+{
+    #includeEtc "caseDicts/setConstraintTypes"
+
+    ".*"
+    {
+        type    calculated;
+        value   $internalField;
+    }
+}
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/0.orig/p_rgh b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/0.orig/p_rgh
new file mode 100644
index 0000000000000000000000000000000000000000..d034cb3839c01fa363438a52b9ff13898966e929
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/0.orig/p_rgh
@@ -0,0 +1,32 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       volScalarField;
+    object      p_rgh;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+dimensions      [1 -1 -2 0 0 0 0];
+
+internalField   uniform 1e5;
+
+boundaryField
+{
+    #includeEtc "caseDicts/setConstraintTypes"
+
+    ".*"
+    {
+        type            calculated;
+        value           $internalField;
+    }
+}
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/0.orig/rho b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/0.orig/rho
new file mode 100644
index 0000000000000000000000000000000000000000..f18533f113cca42b3fba5a1152500e0f49157364
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/0.orig/rho
@@ -0,0 +1,32 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       volScalarField;
+    object      rho;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+dimensions      [1 -3 0 0 0 0 0];
+
+internalField   uniform 8000;
+
+boundaryField
+{
+    #includeEtc "caseDicts/setConstraintTypes"
+
+    ".*"
+    {
+        type    calculated;
+        value   $internalField;
+    }
+}
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/Allclean b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/Allclean
new file mode 100755
index 0000000000000000000000000000000000000000..d2bde265332fe4a93d62b43012a9494029d60ebb
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/Allclean
@@ -0,0 +1,15 @@
+#!/bin/sh
+cd "${0%/*}" || exit                                # Run from this directory
+. ${WM_PROJECT_DIR:?}/bin/tools/CleanFunctions      # Tutorial clean functions
+#------------------------------------------------------------------------------
+
+cleanCase0
+
+rm -rf constant/extendedFeatureEdgeMesh
+rm -rf constant/triSurface
+
+rm -rf VTK
+rm -rf constant/cellToRegion
+rm -rf constant/*/polyMesh  # region meshes
+
+#------------------------------------------------------------------------------
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/Allrun-parallel b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/Allrun-parallel
new file mode 100755
index 0000000000000000000000000000000000000000..c42c272990847e8d68c0db987f72ab659fae51e1
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/Allrun-parallel
@@ -0,0 +1,61 @@
+#!/bin/sh
+cd "${0%/*}" || exit                                # Run from this directory
+. ${WM_PROJECT_DIR:?}/bin/tools/RunFunctions        # Tutorial run functions
+#------------------------------------------------------------------------------
+
+mkdir -p constant/triSurface
+
+cp -f "$FOAM_TUTORIALS"/resources/geometry/geom.stl.gz constant/triSurface
+
+rm -rf constant/polyMesh/sets
+
+# For meshing only
+decompDict="-decomposeParDict system/decomposeParDict"
+
+runApplication blockMesh
+runApplication surfaceFeatureExtract
+
+runApplication snappyHexMesh -overwrite
+runApplication topoSet -dict system/topoSetDict.f1
+
+runApplication $decompDict decomposePar
+
+# Restore initial fields
+restore0Dir -processor
+
+runParallel $decompDict splitMeshRegions -cellZones -overwrite
+
+# Remove fluid fields from solid regions (important for post-processing)
+for region in $(foamListRegions solid)
+do
+    rm -f 0/$region/{nut,alphat,epsilon,k,U,p_rgh}
+    rm -f processor*/0/$region/{nut,alphat,epsilon,k,U,p_rgh}
+done
+
+for region in $(foamListRegions)
+do
+    runParallel $decompDict -s $region changeDictionary -region $region
+done
+
+# Redistribute onto fewer processors, with special treatment for heater
+#for region in $(foamListRegions)
+#do
+#    runParallel -np 6 -s redist-$region \
+#        redistributePar -overwrite -region $region
+#done
+
+#-- Run in parallel
+runParallel $(getApplication)
+
+# Reconstruct
+for region in $(foamListRegions)
+do
+    runParallel -s reconstruct-$region \
+        redistributePar -reconstruct -region $region
+done
+
+echo
+echo "Use paraFoam -touch-all to create files for paraview post-processing"
+echo
+
+#------------------------------------------------------------------------------
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/constant/bottomAir/radiationProperties b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/constant/bottomAir/radiationProperties
new file mode 100644
index 0000000000000000000000000000000000000000..12d23ce2ac5ec56ad7192078138991bae9f56294
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/constant/bottomAir/radiationProperties
@@ -0,0 +1,22 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      radiationProperties;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+radiation       off;
+
+radiationModel  none;
+
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/constant/bottomAir/thermophysicalProperties b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/constant/bottomAir/thermophysicalProperties
new file mode 100644
index 0000000000000000000000000000000000000000..9533066d7e56ec3352b8db3439166369d0d0056f
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/constant/bottomAir/thermophysicalProperties
@@ -0,0 +1,47 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      thermophysicalProperties;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+thermoType
+{
+    type            heRhoThermo;
+    mixture         pureMixture;
+    transport       const;
+    thermo          hConst;
+    equationOfState perfectGas;
+    specie          specie;
+    energy          sensibleEnthalpy;
+}
+
+mixture
+{
+    specie
+    {
+        molWeight       28.9;
+    }
+    thermodynamics
+    {
+        Cp              1000;
+        Hf              0;
+    }
+    transport
+    {
+        mu              1.8e-05;
+        Pr              0.7;
+    }
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/constant/bottomAir/turbulenceProperties b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/constant/bottomAir/turbulenceProperties
new file mode 100644
index 0000000000000000000000000000000000000000..2752116e9e0e042596ba99baad5015b8234021bf
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/constant/bottomAir/turbulenceProperties
@@ -0,0 +1,19 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      turbulenceProperties;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+simulationType  laminar;
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/constant/g b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/constant/g
new file mode 100644
index 0000000000000000000000000000000000000000..0d8ca24848a8e2f1e3c7ffcb48942b3057494f88
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/constant/g
@@ -0,0 +1,20 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       uniformDimensionedVectorField;
+    object      g;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+dimensions      [0 1 -2 0 0 0 0];
+value           (0 -9.81 0);
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/constant/heater/radiationProperties b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/constant/heater/radiationProperties
new file mode 100644
index 0000000000000000000000000000000000000000..cedad3050ab01ae230b652a23877ca5270b48570
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/constant/heater/radiationProperties
@@ -0,0 +1,24 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "constant";
+    object      radiationProperties;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+radiation       off;
+
+radiationModel  none;
+
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/constant/heater/thermophysicalProperties b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/constant/heater/thermophysicalProperties
new file mode 100644
index 0000000000000000000000000000000000000000..16c7eb2f59731c59608bccde18830e5233d49e52
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/constant/heater/thermophysicalProperties
@@ -0,0 +1,52 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      thermophysicalProperties;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+thermoType
+{
+    type            heSolidThermo;
+    mixture         pureMixture;
+    transport       constIso;
+    thermo          hConst;
+    equationOfState rhoConst;
+    specie          specie;
+    energy          sensibleEnthalpy;
+}
+
+mixture
+{
+    specie
+    {
+        molWeight   12;
+    }
+
+    transport
+    {
+        kappa   80;
+    }
+
+    thermodynamics
+    {
+        Hf      0;
+        Cp      450;
+    }
+
+    equationOfState
+    {
+        rho     8000;
+    }
+}
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/constant/leftSolid/radiationProperties b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/constant/leftSolid/radiationProperties
new file mode 120000
index 0000000000000000000000000000000000000000..08087c37b4d0f37d8df26e11ea195b102f43e32d
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/constant/leftSolid/radiationProperties
@@ -0,0 +1 @@
+../heater/radiationProperties
\ No newline at end of file
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/constant/leftSolid/thermophysicalProperties b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/constant/leftSolid/thermophysicalProperties
new file mode 120000
index 0000000000000000000000000000000000000000..dc4d3a18ee4b034d4fdd38eef0466567d0d331bb
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/constant/leftSolid/thermophysicalProperties
@@ -0,0 +1 @@
+../heater/thermophysicalProperties
\ No newline at end of file
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/constant/regionProperties b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/constant/regionProperties
new file mode 100644
index 0000000000000000000000000000000000000000..1b03ad0e7f657f821538a1c6d3b50cce565d746d
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/constant/regionProperties
@@ -0,0 +1,25 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "constant";
+    object      regionProperties;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+regions
+(
+    fluid       (bottomAir topAir)
+    solid       (heater leftSolid rightSolid)
+);
+
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/constant/rightSolid/radiationProperties b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/constant/rightSolid/radiationProperties
new file mode 120000
index 0000000000000000000000000000000000000000..08087c37b4d0f37d8df26e11ea195b102f43e32d
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/constant/rightSolid/radiationProperties
@@ -0,0 +1 @@
+../heater/radiationProperties
\ No newline at end of file
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/constant/rightSolid/thermophysicalProperties b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/constant/rightSolid/thermophysicalProperties
new file mode 120000
index 0000000000000000000000000000000000000000..dc4d3a18ee4b034d4fdd38eef0466567d0d331bb
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/constant/rightSolid/thermophysicalProperties
@@ -0,0 +1 @@
+../heater/thermophysicalProperties
\ No newline at end of file
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/constant/topAir/radiationProperties b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/constant/topAir/radiationProperties
new file mode 120000
index 0000000000000000000000000000000000000000..e8deee4c2ffe9b4455a8acc5d1e9d0e39c379caa
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/constant/topAir/radiationProperties
@@ -0,0 +1 @@
+../bottomAir/radiationProperties
\ No newline at end of file
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/constant/topAir/thermophysicalProperties b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/constant/topAir/thermophysicalProperties
new file mode 120000
index 0000000000000000000000000000000000000000..bd35030a13bd2a596bd156fcb37634090c0342a4
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/constant/topAir/thermophysicalProperties
@@ -0,0 +1 @@
+../bottomAir/thermophysicalProperties
\ No newline at end of file
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/constant/topAir/turbulenceProperties b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/constant/topAir/turbulenceProperties
new file mode 120000
index 0000000000000000000000000000000000000000..435bf46f771a1525b3b0358a7cb3aea5243f7b91
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/constant/topAir/turbulenceProperties
@@ -0,0 +1 @@
+../bottomAir/turbulenceProperties
\ No newline at end of file
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/blockMeshDict b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/blockMeshDict
new file mode 100644
index 0000000000000000000000000000000000000000..d34b9742a717d182a4ff4dfa0ba315e7f5712937
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/blockMeshDict
@@ -0,0 +1,96 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      blockMeshDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+scale   1;
+
+vertices
+(
+    (-0.1 -0.04  -0.05)
+    ( 0.1 -0.04  -0.05)
+    ( 0.1  0.04  -0.05)
+    (-0.1  0.04  -0.05)
+    (-0.1 -0.04   0.05)
+    ( 0.1 -0.04   0.05)
+    ( 0.1  0.04   0.05)
+    (-0.1  0.04   0.05)
+);
+
+blocks
+(
+    hex (0 1 2 3 4 5 6 7) (30 10 10) simpleGrading (1 1 1)
+);
+
+edges
+(
+);
+
+boundary
+(
+    maxY
+    {
+        type wall;
+        faces
+        (
+            (3 7 6 2)
+        );
+    }
+    minX
+    {
+        type patch;
+        faces
+        (
+            (0 4 7 3)
+        );
+    }
+    maxX
+    {
+        type patch;
+        faces
+        (
+            (2 6 5 1)
+        );
+    }
+    minY
+    {
+        type wall;
+        faces
+        (
+            (1 5 4 0)
+        );
+    }
+    minZ
+    {
+        type wall;
+        faces
+        (
+            (0 3 2 1)
+        );
+    }
+    maxZ
+    {
+        type wall;
+        faces
+        (
+            (4 5 6 7)
+        );
+    }
+);
+
+mergePatchPairs
+(
+);
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/bottomAir/changeDictionaryDict b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/bottomAir/changeDictionaryDict
new file mode 100644
index 0000000000000000000000000000000000000000..efb5c71de49d66dfcc35cdc79c0c8d307808e6c5
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/bottomAir/changeDictionaryDict
@@ -0,0 +1,148 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      changeDictionaryDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+boundary
+{
+    minX
+    {
+        type            wall;
+    }
+    maxX
+    {
+        type            wall;
+    }
+}
+
+U
+{
+    internalField   uniform (0.01 0 0);
+
+    boundaryField
+    {
+        ".*"
+        {
+            type            fixedValue;
+            value           uniform (0 0 0);
+        }
+        "procBoundary.*"
+        {
+            type            processor;
+        }
+    }
+}
+
+T
+{
+    internalField   uniform 300;
+
+    boundaryField
+    {
+        ".*"
+        {
+            type            zeroGradient;
+        }
+
+        "procBoundary.*"
+        {
+            type            processor;
+        }
+
+        "bottomAir_to_.*"
+        {
+            type            compressible::turbulentTemperatureRadCoupledMixed;
+            Tnbr            T;
+            kappaMethod     fluidThermo;
+            value           uniform 300;
+            useImplicit     true;
+        }
+    }
+}
+
+epsilon
+{
+    // Set the value on all bc to non-zero. Not used in simulation
+    // since zeroGradient; only used in initialisation.
+    internalField   uniform 0.01;
+
+    boundaryField
+    {
+        ".*"
+        {
+            type            epsilonWallFunction;
+            value           uniform 0.01;
+        }
+        "procBoundary.*"
+        {
+            type            processor;
+        }
+    }
+}
+
+k
+{
+    internalField   uniform 0.1;
+
+    boundaryField
+    {
+        ".*"
+        {
+            type            kqRWallFunction;
+            value           uniform 0.1;
+        }
+        "procBoundary.*"
+        {
+            type            processor;
+        }
+    }
+}
+
+p_rgh
+{
+    internalField   uniform 1e5;
+
+    boundaryField
+    {
+        ".*"
+        {
+            type            fixedFluxPressure;
+            value           uniform 1e5;
+        }
+        "procBoundary.*"
+        {
+            type            processor;
+        }
+    }
+}
+
+p
+{
+    internalField   uniform 1e5;
+
+    boundaryField
+    {
+        ".*"
+        {
+            type            calculated;
+            value           uniform 1e5;
+        }
+        "procBoundary.*"
+        {
+            type            processor;
+        }
+    }
+}
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/bottomAir/decomposeParDict b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/bottomAir/decomposeParDict
new file mode 120000
index 0000000000000000000000000000000000000000..46638e60f61f453fde97c51772ad6111792db0f6
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/bottomAir/decomposeParDict
@@ -0,0 +1 @@
+../decomposeParDict
\ No newline at end of file
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/bottomAir/fvSchemes b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/bottomAir/fvSchemes
new file mode 100644
index 0000000000000000000000000000000000000000..824415f0f137140d55280812d36219eecb0c984e
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/bottomAir/fvSchemes
@@ -0,0 +1,56 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      fvSchemes;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+ddtSchemes
+{
+    default Euler;
+}
+
+gradSchemes
+{
+    default         Gauss linear;
+}
+
+divSchemes
+{
+    default         none;
+
+    div(phi,U)      Gauss upwind;
+    div(phi,K)      Gauss linear;
+    div(phi,h)      Gauss upwind;
+    div(phi,k)      Gauss upwind;
+    div(phi,epsilon) Gauss upwind;
+    div(phi,R)      Gauss upwind;
+    div(R)          Gauss linear;
+    div(((rho*nuEff)*dev2(T(grad(U))))) Gauss linear;
+}
+
+laplacianSchemes
+{
+    default         Gauss linear corrected;
+}
+
+interpolationSchemes
+{
+    default         linear;
+}
+
+snGradSchemes
+{
+    default         corrected;
+}
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/bottomAir/fvSolution b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/bottomAir/fvSolution
new file mode 100644
index 0000000000000000000000000000000000000000..01494b7848838fc58e875c61e5c44e5b9d5d9eff
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/bottomAir/fvSolution
@@ -0,0 +1,99 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      fvSolution;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+solvers
+{
+    "(rho|rhoFinal)"
+    {
+        solver          PCG;
+        preconditioner  DIC;
+        tolerance       1e-7;
+        relTol          0;
+    }
+
+    p_rgh
+    {
+
+        solver          PCG;
+        preconditioner  DIC;
+
+        //solver           GAMG;
+        tolerance        1e-7;
+        relTol           0.01;
+
+        //smoother         GaussSeidel;
+
+    }
+
+    p_rghFinal
+    {
+        $p_rgh;
+        tolerance        1e-7;
+        relTol           0;
+    }
+
+    h
+    {
+        solver           PBiCGStab;
+        preconditioner   DILU;
+        tolerance        1e-8;
+        relTol           0.1;
+        minIter          1;
+    }
+
+    hFinal
+    {
+        $h;
+        tolerance        1e-08;
+        relTol           0;
+        minIter          1;
+    }
+
+    "(U|k|epsilon|R)"
+    {
+        solver           PBiCGStab;
+        preconditioner   DILU;
+        tolerance        1e-7;
+        relTol           0.1;
+    }
+
+    "(U|k|epsilon|R)Final"
+    {
+        $U;
+        tolerance        1e-07;
+        relTol           0;
+    }
+}
+
+PIMPLE
+{
+    momentumPredictor   yes;
+    nCorrectors         2;
+    nNonOrthogonalCorrectors 0;
+    pRefCell    0;
+    pRefValue   1e5;
+}
+
+relaxationFactors
+{
+    equations
+    {
+        "h.*"           1;
+        "U.*"           1;
+    }
+}
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/controlDict b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/controlDict
new file mode 100644
index 0000000000000000000000000000000000000000..3a4d6cf3244c34386a65443c3fe65305fe25b640
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/controlDict
@@ -0,0 +1,54 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "system";
+    object      controlDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+application     chtMultiRegionFoam;
+
+startFrom       startTime;
+
+startTime       0;
+
+stopAt          endTime;
+
+endTime         75;
+
+deltaT          0.001;
+
+writeControl    adjustable;
+
+writeInterval   15;
+
+purgeWrite      0;
+
+writeFormat     ascii;
+
+writePrecision  7;
+
+writeCompression off;
+
+timeFormat      general;
+
+timePrecision   6;
+
+runTimeModifiable true;
+
+maxCo           0.3;
+
+maxDi           10.0;
+
+adjustTimeStep  yes;
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/decomposeParDict b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/decomposeParDict
new file mode 100644
index 0000000000000000000000000000000000000000..fe8f307df9cb9ea50ee29ca23612317343bd6dac
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/decomposeParDict
@@ -0,0 +1,35 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Web:      www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      decomposeParDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+numberOfSubdomains  3;
+
+// method          assembleDecomp;
+// method          hierarchical;
+// method          simple;
+// method          manual;
+method  scotch;
+
+constraints
+{
+    faces
+    {
+        type    preserveFaceZones;
+        zones   (f1 f2 f3 f4 f5);
+        enabled true;
+    }
+}
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/fvSchemes b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/fvSchemes
new file mode 100644
index 0000000000000000000000000000000000000000..ac3cd1a53d1e2040c172aa85551f632bd5a8b6ba
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/fvSchemes
@@ -0,0 +1,42 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      fvSchemes;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+ddtSchemes
+{
+}
+
+gradSchemes
+{
+}
+
+divSchemes
+{
+}
+
+laplacianSchemes
+{
+}
+
+interpolationSchemes
+{
+}
+
+snGradSchemes
+{
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/fvSolution b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/fvSolution
new file mode 100644
index 0000000000000000000000000000000000000000..0b9de7f09a310ab9b09e3bd49929675b51da2fa4
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/fvSolution
@@ -0,0 +1,22 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      fvSolution;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+PIMPLE
+{
+    nOuterCorrectors 1;
+}
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/heater/changeDictionaryDict b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/heater/changeDictionaryDict
new file mode 100644
index 0000000000000000000000000000000000000000..4b2208aeec8ab304212e85221bc3e4bdeff16023
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/heater/changeDictionaryDict
@@ -0,0 +1,64 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      changeDictionaryDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+boundary
+{
+    minY
+    {
+        type            patch;
+    }
+    minZ
+    {
+        type            patch;
+    }
+    maxZ
+    {
+        type            patch;
+    }
+}
+
+T
+{
+    internalField   uniform 300;
+
+    boundaryField
+    {
+        ".*"
+        {
+            type            zeroGradient;
+            value           uniform 300;
+        }
+        "procBoundary.*"
+        {
+            type            processor;
+        }
+        "heater_to_.*"
+        {
+            type            compressible::turbulentTemperatureRadCoupledMixed;
+            Tnbr            T;
+            kappaMethod     solidThermo;
+            value           uniform 300;
+            useImplicit     true;
+        }
+        minY
+        {
+            type            fixedValue;
+            value           uniform 500;
+        }
+    }
+}
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/heater/decomposeParDict b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/heater/decomposeParDict
new file mode 120000
index 0000000000000000000000000000000000000000..46638e60f61f453fde97c51772ad6111792db0f6
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/heater/decomposeParDict
@@ -0,0 +1 @@
+../decomposeParDict
\ No newline at end of file
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/heater/fvSchemes b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/heater/fvSchemes
new file mode 100644
index 0000000000000000000000000000000000000000..083ce3c9b2571311c1248a5a07940281383c394e
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/heater/fvSchemes
@@ -0,0 +1,49 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      fvSchemes;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+ddtSchemes
+{
+    default         Euler;
+}
+
+gradSchemes
+{
+    default         Gauss linear;
+}
+
+divSchemes
+{
+    default         none;
+}
+
+laplacianSchemes
+{
+    default             none;
+    laplacian(alpha,h)  Gauss linear corrected;
+}
+
+interpolationSchemes
+{
+    default         linear;
+}
+
+snGradSchemes
+{
+    default         corrected;
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/heater/fvSolution b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/heater/fvSolution
new file mode 100644
index 0000000000000000000000000000000000000000..a8e028278e3b3a838646a0daf9e5c9f1ea857bc3
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/heater/fvSolution
@@ -0,0 +1,40 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      fvSolution;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+solvers
+{
+    h
+    {
+        solver           PCG;
+        preconditioner   DIC;
+        tolerance        1e-06;
+        relTol           0.1;
+    }
+
+    hFinal
+    {
+        $h;
+        tolerance        1e-06;
+        relTol           0;
+    }
+}
+
+PIMPLE
+{
+    nNonOrthogonalCorrectors 0;
+}
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/leftSolid/changeDictionaryDict b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/leftSolid/changeDictionaryDict
new file mode 100644
index 0000000000000000000000000000000000000000..a94dbdb584cf56c486f899fb03b1bc3176722e78
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/leftSolid/changeDictionaryDict
@@ -0,0 +1,55 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      changeDictionaryDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+boundary
+{
+    minZ
+    {
+        type            patch;
+    }
+    maxZ
+    {
+        type            patch;
+    }
+}
+
+T
+{
+    internalField   uniform 300;
+
+    boundaryField
+    {
+        ".*"
+        {
+            type            zeroGradient;
+            value           uniform 300;
+        }
+        "procBoundary.*"
+        {
+            type            processor;
+        }
+        "leftSolid_to_.*"
+        {
+            type            compressible::turbulentTemperatureRadCoupledMixed;
+            Tnbr            T;
+            kappaMethod     solidThermo;
+            value           uniform 300;
+            useImplicit     true;
+        }
+    }
+}
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/leftSolid/decomposeParDict b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/leftSolid/decomposeParDict
new file mode 120000
index 0000000000000000000000000000000000000000..d6dd0b5c0636316931ced9573920d72e86821030
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/leftSolid/decomposeParDict
@@ -0,0 +1 @@
+../heater/decomposeParDict
\ No newline at end of file
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/leftSolid/fvSchemes b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/leftSolid/fvSchemes
new file mode 120000
index 0000000000000000000000000000000000000000..63236f302cfd79847ce312cced35784fa149c827
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/leftSolid/fvSchemes
@@ -0,0 +1 @@
+../heater/fvSchemes
\ No newline at end of file
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/leftSolid/fvSolution b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/leftSolid/fvSolution
new file mode 100644
index 0000000000000000000000000000000000000000..a8e028278e3b3a838646a0daf9e5c9f1ea857bc3
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/leftSolid/fvSolution
@@ -0,0 +1,40 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      fvSolution;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+solvers
+{
+    h
+    {
+        solver           PCG;
+        preconditioner   DIC;
+        tolerance        1e-06;
+        relTol           0.1;
+    }
+
+    hFinal
+    {
+        $h;
+        tolerance        1e-06;
+        relTol           0;
+    }
+}
+
+PIMPLE
+{
+    nNonOrthogonalCorrectors 0;
+}
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/meshQualityDict b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/meshQualityDict
new file mode 100644
index 0000000000000000000000000000000000000000..89515475776bb349df562036b66e5c0a9ee8a0d9
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/meshQualityDict
@@ -0,0 +1,21 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      meshQualityDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+// Include defaults parameters from master dictionary
+#includeEtc "caseDicts/meshQualityDict"
+
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/rightSolid/changeDictionaryDict b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/rightSolid/changeDictionaryDict
new file mode 100644
index 0000000000000000000000000000000000000000..80d78b8f06a63bbbb8a8330faef923bacb91f830
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/rightSolid/changeDictionaryDict
@@ -0,0 +1,55 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      changeDictionaryDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+boundary
+{
+    minZ
+    {
+        type            patch;
+    }
+    maxZ
+    {
+        type            patch;
+    }
+}
+
+T
+{
+    internalField   uniform 300;
+
+    boundaryField
+    {
+        ".*"
+        {
+            type            zeroGradient;
+            value           uniform 300;
+        }
+        "procBoundary.*"
+        {
+            type            processor;
+        }
+        "rightSolid_to_.*"
+        {
+            type            compressible::turbulentTemperatureRadCoupledMixed;
+            Tnbr            T;
+            kappaMethod     solidThermo;
+            value           uniform 300;
+            useImplicit     true;
+        }
+    }
+}
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/rightSolid/decomposeParDict b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/rightSolid/decomposeParDict
new file mode 120000
index 0000000000000000000000000000000000000000..d6dd0b5c0636316931ced9573920d72e86821030
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/rightSolid/decomposeParDict
@@ -0,0 +1 @@
+../heater/decomposeParDict
\ No newline at end of file
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/rightSolid/fvSchemes b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/rightSolid/fvSchemes
new file mode 120000
index 0000000000000000000000000000000000000000..63236f302cfd79847ce312cced35784fa149c827
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/rightSolid/fvSchemes
@@ -0,0 +1 @@
+../heater/fvSchemes
\ No newline at end of file
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/rightSolid/fvSolution b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/rightSolid/fvSolution
new file mode 100644
index 0000000000000000000000000000000000000000..a8e028278e3b3a838646a0daf9e5c9f1ea857bc3
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/rightSolid/fvSolution
@@ -0,0 +1,40 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      fvSolution;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+solvers
+{
+    h
+    {
+        solver           PCG;
+        preconditioner   DIC;
+        tolerance        1e-06;
+        relTol           0.1;
+    }
+
+    hFinal
+    {
+        $h;
+        tolerance        1e-06;
+        relTol           0;
+    }
+}
+
+PIMPLE
+{
+    nNonOrthogonalCorrectors 0;
+}
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/snappyHexMeshDict b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/snappyHexMeshDict
new file mode 100644
index 0000000000000000000000000000000000000000..4549558d71d9cb6389df597dd1baf5eac4372d24
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/snappyHexMeshDict
@@ -0,0 +1,284 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      snappyHexMeshDict;
+}
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+// Which of the steps to run
+castellatedMesh true;
+snap            true;
+addLayers       false;
+
+
+// Geometry. Definition of all surfaces. All surfaces are of class
+// searchableSurface.
+// Surfaces are used
+// - to specify refinement for any mesh cell intersecting it
+// - to specify refinement for any mesh cell inside/outside/near
+// - to 'snap' the mesh boundary to the surface
+geometry
+{
+    geom.stl
+    {
+        type triSurfaceMesh;
+        name geom;
+    }
+}
+
+
+// Settings for the castellatedMesh generation.
+castellatedMeshControls
+{
+
+    // Refinement parameters
+    // ~~~~~~~~~~~~~~~~~~~~~
+
+    // If local number of cells is >= maxLocalCells on any processor
+    // switches from from refinement followed by balancing
+    // (current method) to (weighted) balancing before refinement.
+    maxLocalCells 100000;
+
+    // Overall cell limit (approximately). Refinement will stop immediately
+    // upon reaching this number so a refinement level might not complete.
+    // Note that this is the number of cells before removing the part which
+    // is not 'visible' from the keepPoint. The final number of cells might
+    // actually be a lot less.
+    maxGlobalCells 2000000;
+
+    // The surface refinement loop might spend lots of iterations
+    // refining just a few cells. This setting will cause refinement
+    // to stop if <= minimumRefine are selected for refinement. Note:
+    // it will at least do one iteration (unless the number of cells
+    // to refine is 0)
+    minRefinementCells 10;
+
+    // Number of buffer layers between different levels.
+    // 1 means normal 2:1 refinement restriction, larger means slower
+    // refinement.
+    nCellsBetweenLevels 2;
+
+
+
+    // Explicit feature edge refinement
+    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    // Specifies a level for any cell intersected by its edges.
+    // This is a featureEdgeMesh, read from constant/triSurface for now.
+    features
+    (
+        {
+            file "geom.extendedFeatureEdgeMesh";    //"geom.eMesh";
+            level 1;
+        }
+    );
+
+
+
+    // Surface based refinement
+    // ~~~~~~~~~~~~~~~~~~~~~~~~
+
+    // Specifies two levels for every surface. The first is the minimum level,
+    // every cell intersecting a surface gets refined up to the minimum level.
+    // The second level is the maximum level. Cells that 'see' multiple
+    // intersections where the intersections make an
+    // angle > resolveFeatureAngle get refined up to the maximum level.
+
+    refinementSurfaces
+    {
+        geom
+        {
+            // Surface-wise min and max refinement level
+            level (1 1);
+        }
+    }
+
+    // Resolve sharp angles
+    resolveFeatureAngle 30;
+
+
+    // Region-wise refinement
+    // ~~~~~~~~~~~~~~~~~~~~~~
+
+    // Specifies refinement level for cells in relation to a surface. One of
+    // three modes
+    // - distance. 'levels' specifies per distance to the surface the
+    //   wanted refinement level. The distances need to be specified in
+    //   descending order.
+    // - inside. 'levels' is only one entry and only the level is used. All
+    //   cells inside the surface get refined up to the level. The surface
+    //   needs to be closed for this to be possible.
+    // - outside. Same but cells outside.
+
+    refinementRegions
+    {
+        //refinementBox
+        //{
+        //    mode inside;
+        //    levels ((1E15 4));
+        //}
+    }
+
+
+    // Mesh selection
+    // ~~~~~~~~~~~~~~
+
+    // After refinement patches get added for all refinementSurfaces and
+    // all cells intersecting the surfaces get put into these patches. The
+    // section reachable from the locationInMesh is kept.
+    // NOTE: This point should never be on a face, always inside a cell, even
+    // after refinement.
+    locationsInMesh
+    (
+        (( 0.005 0.005  0.005) heater)
+        (( 0.05  0.005  0.005) rightSolid)
+        ((-0.05  0.005  0.005) leftSolid)
+        ((-0.05  0.015  0.005) topAir)
+        ((-0.05 -0.015  0.005) bottomAir)
+    );
+
+
+    // Whether any faceZones (as specified in the refinementSurfaces)
+    // are only on the boundary of corresponding cellZones or also allow
+    // free-standing zone faces. Not used if there are no faceZones.
+    allowFreeStandingZoneFaces false;
+}
+
+
+
+// Settings for the snapping.
+snapControls
+{
+    //- Number of patch smoothing iterations before finding correspondence
+    //  to surface
+    nSmoothPatch 3;
+
+    //- Relative distance for points to be attracted by surface feature point
+    //  or edge. True distance is this factor times local
+    //  maximum edge length.
+    tolerance 1.0;
+
+    //- Number of mesh displacement relaxation iterations.
+    nSolveIter 30;
+
+    //- Maximum number of snapping relaxation iterations. Should stop
+    //  before upon reaching a correct mesh.
+    nRelaxIter 5;
+
+    //- Highly experimental and wip: number of feature edge snapping
+    //  iterations. Leave out altogether to disable.
+    //  Of limited use in this case since faceZone faces not handled.
+    nFeatureSnapIter 10;
+}
+
+
+
+// Settings for the layer addition.
+addLayersControls
+{
+    relativeSizes true;
+
+    // Per final patch (so not geometry!) the layer information
+    layers
+    {
+        maxY
+        {
+            nSurfaceLayers 3;
+        }
+    }
+
+    // Expansion factor for layer mesh
+    expansionRatio 1.3;
+
+    // Wanted thickness of final added cell layer. If multiple layers
+    // is the thickness of the layer furthest away from the wall.
+    // Relative to undistorted size of cell outside layer.
+    // See relativeSizes parameter.
+    finalLayerThickness 1;
+
+    // Minimum thickness of cell layer. If for any reason layer
+    // cannot be above minThickness do not add layer.
+    // Relative to undistorted size of cell outside layer.
+    minThickness 0.1;
+
+    // If points get not extruded do nGrow layers of connected faces that are
+    // also not grown. This helps convergence of the layer addition process
+    // close to features.
+    // Note: changed(corrected) w.r.t 1.7.x! (didn't do anything in 1.7.x)
+    nGrow 0;
+
+    // Advanced settings
+
+    // When not to extrude surface. 0 is flat surface, 90 is when two faces
+    // are perpendicular
+    featureAngle 30;
+
+    // Maximum number of snapping relaxation iterations. Should stop
+    // before upon reaching a correct mesh.
+    nRelaxIter 3;
+
+    // Number of smoothing iterations of surface normals
+    nSmoothSurfaceNormals 1;
+
+    // Number of smoothing iterations of interior mesh movement direction
+    nSmoothNormals 3;
+
+    // Smooth layer thickness over surface patches
+    nSmoothThickness 2;
+
+    // Stop layer growth on highly warped cells
+    maxFaceThicknessRatio 0.5;
+
+    // Reduce layer growth where ratio thickness to medial
+    // distance is large
+    maxThicknessToMedialRatio 1;
+
+    // Angle used to pick up medial axis points
+    // Note: changed(corrected) w.r.t 1.7.x! 90 degrees corresponds to 130
+    // in 1.7.x.
+    minMedialAxisAngle 90;
+
+    // Create buffer region for new layer terminations
+    nBufferCellsNoExtrude 0;
+
+    // Overall max number of layer addition iterations. The mesher will exit
+    // if it reaches this number of iterations; possibly with an illegal
+    // mesh.
+    nLayerIter 50;
+}
+
+
+
+// Generic mesh quality settings. At any undoable phase these determine
+// where to undo.
+meshQualityControls
+{
+    #include "meshQualityDict"
+
+    // Advanced
+
+    //- Number of error distribution iterations
+    nSmoothScale 4;
+    //- Amount to scale back displacement at error points
+    errorReduction 0.75;
+}
+
+
+// Advanced
+
+// Merge tolerance. Is fraction of overall bounding box of initial mesh.
+// Note: the write tolerance needs to be higher than this.
+mergeTolerance 1e-6;
+
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/surfaceFeatureExtractDict b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/surfaceFeatureExtractDict
new file mode 100644
index 0000000000000000000000000000000000000000..4bb41293678bf8f7b11b152831a61f7c1ebcd767
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/surfaceFeatureExtractDict
@@ -0,0 +1,35 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      surfaceFeatureExtractDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+geom.stl
+{
+    extractionMethod    extractFromSurface;
+
+    // Mark edges whose adjacent surface normals are at an angle less
+    // than includedAngle as features
+    // - 0  : selects no edges
+    // - 180: selects all edges
+    includedAngle       150;
+
+    // Write options
+    writeFeatureEdgeMesh    yes;
+
+    // Write features to obj format for postprocessing
+    writeObj                yes;
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/topAir/changeDictionaryDict b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/topAir/changeDictionaryDict
new file mode 100644
index 0000000000000000000000000000000000000000..d8b5d162b9c37b0e7708040fa484ba2eaaf9c641
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/topAir/changeDictionaryDict
@@ -0,0 +1,192 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      changeDictionaryDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+U
+{
+    internalField   uniform (0.1 0 0);
+
+    boundaryField
+    {
+        ".*"
+        {
+            type            fixedValue;
+            value           uniform (0 0 0);
+        }
+        "procBoundary.*"
+        {
+            type            processor;
+        }
+        minX
+        {
+            type            fixedValue;
+            value           uniform (0.1 0 0);
+        }
+        maxX
+        {
+            type            inletOutlet;
+            inletValue      uniform (0 0 0);
+            value           uniform (0.1 0 0);
+        }
+    }
+}
+
+T
+{
+    internalField   uniform 300;
+
+    boundaryField
+    {
+        ".*"
+        {
+            type            zeroGradient;
+        }
+        "procBoundary.*"
+        {
+            type            processor;
+        }
+
+        minX
+        {
+            type            fixedValue;
+            value           uniform 300;
+        }
+        maxX
+        {
+            type            inletOutlet;
+            inletValue      uniform 300;
+            value           uniform 300;
+        }
+
+        "topAir_to_.*"
+        {
+            type            compressible::turbulentTemperatureRadCoupledMixed;
+            Tnbr            T;
+            kappaMethod     fluidThermo;
+            value           uniform 300;
+            useImplicit     true;
+        }
+    }
+}
+
+epsilon
+{
+    internalField   uniform 0.01;
+
+    boundaryField
+    {
+        ".*"
+        {
+            type            epsilonWallFunction;
+            value           uniform 0.01;
+        }
+        "procBoundary.*"
+        {
+            type            processor;
+        }
+
+        minX
+        {
+            type            fixedValue;
+            value           uniform 0.01;
+        }
+        maxX
+        {
+            type            inletOutlet;
+            inletValue      uniform 0.01;
+            value           uniform 0.01;
+        }
+    }
+}
+
+k
+{
+    internalField   uniform 0.1;
+
+    boundaryField
+    {
+        ".*"
+        {
+            type            kqRWallFunction;
+            value           uniform 0.1;
+        }
+        "procBoundary.*"
+        {
+            type            processor;
+        }
+
+        minX
+        {
+            type            fixedValue;
+            value           uniform 0.1;
+        }
+        maxX
+        {
+            type            inletOutlet;
+            inletValue      uniform 0.1;
+            value           uniform 0.1;
+        }
+    }
+}
+
+p_rgh
+{
+    internalField   uniform 1e5;
+
+    boundaryField
+    {
+        ".*"
+        {
+            type            fixedFluxPressure;
+            value           uniform 1e5;
+        }
+        "procBoundary.*"
+        {
+            type            processor;
+        }
+
+        maxX
+        {
+            type            fixedValue;
+            value           uniform 1e5;
+        }
+    }
+}
+
+p
+{
+    internalField   uniform 1e5;
+
+    boundaryField
+    {
+        ".*"
+        {
+            type            calculated;
+            value           uniform 1e5;
+        }
+        "procBoundary.*"
+        {
+            type            processor;
+        }
+
+        maxX
+        {
+            type            calculated;
+            value           uniform 1e5;
+        }
+    }
+}
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/topAir/decomposeParDict b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/topAir/decomposeParDict
new file mode 120000
index 0000000000000000000000000000000000000000..3523816fd8c788c5a2aa7e8d88445e06a904b3ff
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/topAir/decomposeParDict
@@ -0,0 +1 @@
+../bottomAir/decomposeParDict
\ No newline at end of file
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/topAir/fvSchemes b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/topAir/fvSchemes
new file mode 120000
index 0000000000000000000000000000000000000000..ff6aeb82d395e30f059d8a111d447f5dff18b137
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/topAir/fvSchemes
@@ -0,0 +1 @@
+../bottomAir/fvSchemes
\ No newline at end of file
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/topAir/fvSolution b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/topAir/fvSolution
new file mode 100644
index 0000000000000000000000000000000000000000..7afd8e4757abca470ac7f08f11ff6344a7e833d5
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/topAir/fvSolution
@@ -0,0 +1,76 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      fvSolution;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+solvers
+{
+    "(rho|rhoFinal)"
+    {
+        solver          PCG;
+        preconditioner  DIC;
+        tolerance       1e-7;
+        relTol          0;
+    }
+
+    p_rgh
+    {
+        solver          PCG;
+        preconditioner  DIC;
+        tolerance        1e-7;
+        relTol           0.01;
+    }
+
+    p_rghFinal
+    {
+        $p_rgh;
+        tolerance        1e-7;
+        relTol           0;
+    }
+
+    "(U|h|k|epsilon|R)"
+    {
+        solver           PBiCGStab;
+        preconditioner   DILU;
+        tolerance        1e-7;
+        relTol           0.1;
+    }
+
+    "(U|h|k|epsilon|R)Final"
+    {
+        $U;
+        tolerance        1e-07;
+        relTol           0;
+    }
+}
+
+PIMPLE
+{
+    momentumPredictor   yes;
+    nCorrectors         2;
+    nNonOrthogonalCorrectors 0;
+    pRefCell    0;
+    pRefValue   1e5;
+}
+
+relaxationFactors
+{
+    equations
+    {
+        "h.*"           1;
+        "U.*"           1;
+    }
+}
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/topoSetDict.f1 b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/topoSetDict.f1
new file mode 100755
index 0000000000000000000000000000000000000000..7b197f2ecbb22ec25026328624077cdd5a0f7cb9
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeaterImplicit/system/topoSetDict.f1
@@ -0,0 +1,105 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Web:      www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      topoSetDict;
+}
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+actions
+(
+    // 0. Create cell sets
+    {
+        name    c1;
+        type    cellSet;
+        action  new;
+        source  zoneToCell;
+	    zones	(bottomAir);
+    }
+    {
+        name    f1;
+        type    faceSet;
+        action  new;
+        source  cellToFace;
+        option  all;
+	    sets	(c1);
+    }
+
+    {
+        name    c2;
+        type    cellSet;
+        action  new;
+        source  zoneToCell;
+	    zones	(heater);
+    }
+    {
+        name    f2;
+        type    faceSet;
+        action  new;
+        source  cellToFace;
+        option  all;
+	    sets	(c2);
+    }
+
+    {
+        name    c3;
+        type    cellSet;
+        action  new;
+        source  zoneToCell;
+	    zones	(leftSolid);
+    }
+    {
+        name    f3;
+        type    faceSet;
+        action  new;
+        source  cellToFace;
+        option  all;
+	    sets	(c3);
+    }
+
+    {
+        name    c4;
+        type    cellSet;
+        action  new;
+        source  zoneToCell;
+	    zones	(rightSolid);
+
+    }
+    {
+        name    f4;
+        type    faceSet;
+        action  new;
+        source  cellToFace;
+        option  all;
+	    sets	(c4);
+    }
+
+    {
+        name    c5;
+        type    cellSet;
+        action  new;
+        source  zoneToCell;
+	    zones	(topAir);
+    }
+    {
+        name    f5;
+        type    faceSet;
+        action  new;
+        source  cellToFace;
+        option  all;
+	    sets	(c5);
+
+    }
+);
+
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/0.orig/domain0/T b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/0.orig/domain0/T
new file mode 100644
index 0000000000000000000000000000000000000000..f4040fdf552c0862422ba6c353da1571e483792f
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/0.orig/domain0/T
@@ -0,0 +1,140 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       volScalarField;
+    object      T;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+dimensions      [0 0 0 1 0 0 0];
+
+internalField   uniform 300;
+
+boundaryField
+{
+     #includeEtc "caseDicts/setConstraintTypes"
+
+    FAN_SHROUD
+    {
+        type            externalWallHeatFluxTemperature;
+        kappaMethod     fluidThermo;
+        mode            flux;
+        Ta              $internalField;
+        q               uniform 0;
+        kappaLayers     ( 0 );
+        thicknessLayers ( 0 );
+        value           $internalField;
+        kappaName       none;
+    }
+
+    CABINET
+    {
+        type            externalWallHeatFluxTemperature;
+        kappaMethod     fluidThermo;
+        mode            flux;
+        Ta              $internalField;
+        q               uniform 0;
+        kappaLayers     ( 0 );
+        thicknessLayers ( 0 );
+        value           $internalField;
+        kappaName       none;
+    }
+
+    FINS
+    {
+        type            externalWallHeatFluxTemperature;
+        kappaMethod     fluidThermo;
+        mode            flux;
+        Ta              $internalField;
+        q               uniform 0;
+        kappaLayers     ( 0 );
+        thicknessLayers ( 0 );
+        value           $internalField;
+        kappaName       none;
+    }
+
+    PROCESSOR
+    {
+        type            externalWallHeatFluxTemperature;
+        kappaMethod     fluidThermo;
+        mode            flux;
+        Ta              $internalField;
+        q               uniform 0;
+        kappaLayers     ( 0 );
+        thicknessLayers ( 0 );
+        value           $internalField;
+        kappaName       none;
+    }
+
+    FAN
+    {
+        type            externalWallHeatFluxTemperature;
+        kappaMethod     fluidThermo;
+        mode            flux;
+        Ta              $internalField;
+        q               uniform 0;
+        kappaLayers     ( 0 );
+        thicknessLayers ( 0 );
+        value           $internalField;
+        kappaName       none;
+    }
+
+    MRF_region
+    {
+        type            externalWallHeatFluxTemperature;
+        kappaMethod     fluidThermo;
+        mode            flux;
+        Ta              $internalField;
+        q               uniform 0;
+        kappaLayers     ( 0 );
+        thicknessLayers ( 0 );
+        value           $internalField;
+        kappaName       none;
+    }
+
+    OUTLET_01
+    {
+        type            inletOutlet;
+        inletValue      uniform 300;
+        value           uniform 300;
+    }
+
+    OUTLET_02
+    {
+        type            inletOutlet;
+        inletValue      uniform 300;
+        value           uniform 300;
+    }
+
+    domain0_to_v_CPU
+    {
+        type            compressible::turbulentTemperatureRadCoupledMixed;
+        qrNbr           none;
+        qr              none;
+        Tnbr            T;
+        kappaMethod     fluidThermo;
+        useImplicit     true;
+        value           $internalField;
+    }
+
+    domain0_to_v_fins
+    {
+        type            compressible::turbulentTemperatureRadCoupledMixed;
+        Tnbr            T;
+        kappaMethod     fluidThermo;
+        useImplicit     true;
+        qrNbr           none;
+        qr              none;
+        value           $internalField;
+    }
+}
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/0.orig/domain0/U b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/0.orig/domain0/U
new file mode 100644
index 0000000000000000000000000000000000000000..7bcb3579c61b469831d2e4a95465543510b23162
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/0.orig/domain0/U
@@ -0,0 +1,84 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       volVectorField;
+    object      U;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+dimensions      [0 1 -1 0 0 0 0];
+
+internalField   uniform (0 0 0);
+
+boundaryField
+{
+     #includeEtc "caseDicts/setConstraintTypes"
+
+    FAN_SHROUD
+    {
+        type            fixedValue;
+        value           uniform (0 0 0);
+    }
+
+    CABINET
+    {
+        type            fixedValue;
+        value           uniform (0 0 0);
+    }
+
+    FINS
+    {
+        type            fixedValue;
+        value           uniform (0 0 0);
+    }
+
+    PROCESSOR
+    {
+        type            fixedValue;
+        value           uniform (0 0 0);
+    }
+
+    FAN
+    {
+        type            fixedValue;
+        value           uniform (0 0 0);
+    }
+
+    MRF_region
+    {
+        type            fixedValue;
+        value           uniform (0 0 0);
+    }
+
+    OUTLET_01
+    {
+        type            zeroGradient;
+    }
+
+    OUTLET_02
+    {
+        type            zeroGradient;
+    }
+
+    domain0_to_v_CPU
+    {
+        type            fixedValue;
+        value           uniform (0 0 0);
+    }
+
+    domain0_to_v_fins
+    {
+        type            fixedValue;
+        value           uniform (0 0 0);
+    }
+}
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/0.orig/domain0/alphat b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/0.orig/domain0/alphat
new file mode 100644
index 0000000000000000000000000000000000000000..7864d9bc0eadda9df4a06125eef4d24d962fa038
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/0.orig/domain0/alphat
@@ -0,0 +1,87 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       volScalarField;
+    object      alphat;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+dimensions      [1 -1 -1 0 0 0 0];
+
+internalField   uniform 0.5;
+
+boundaryField
+{
+     #includeEtc "caseDicts/setConstraintTypes"
+    FAN_SHROUD
+    {
+        type            compressible::alphatWallFunction;
+        value           uniform 0;
+    }
+
+    CABINET
+    {
+        type            compressible::alphatWallFunction;
+        value           uniform 0;
+    }
+
+    FINS
+    {
+        type            compressible::alphatWallFunction;
+        value           uniform 0;
+    }
+
+    PROCESSOR
+    {
+        type            compressible::alphatWallFunction;
+        value           uniform 0;
+    }
+
+    FAN
+    {
+        type            compressible::alphatWallFunction;
+        value           uniform 0;
+    }
+
+    MRF_region
+    {
+        type            compressible::alphatWallFunction;
+        value           uniform 0;
+    }
+
+    OUTLET_01
+    {
+        type            calculated;
+        value           $internalField;
+    }
+
+    OUTLET_02
+    {
+        type            calculated;
+        value           $internalField;
+    }
+
+    domain0_to_v_CPU
+    {
+        type            compressible::alphatWallFunction;
+        Prt             0.85;
+        value           uniform 0;
+    }
+
+    domain0_to_v_fins
+    {
+        type            compressible::alphatWallFunction;
+        Prt             0.85;
+        value           uniform 0;
+    }
+}
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/0.orig/domain0/epsilon b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/0.orig/domain0/epsilon
new file mode 100644
index 0000000000000000000000000000000000000000..f172504593167047027751a9d864437b200e41fc
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/0.orig/domain0/epsilon
@@ -0,0 +1,87 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       volScalarField;
+    object      epsilon;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+dimensions      [0 2 -3 0 0 0 0];
+
+internalField   uniform 10;
+
+boundaryField
+{
+     #includeEtc "caseDicts/setConstraintTypes"
+    FAN_SHROUD
+    {
+        type            epsilonWallFunction;
+        value           $internalField;
+    }
+
+    CABINET
+    {
+        type            epsilonWallFunction;
+        value           $internalField;
+    }
+
+    FINS
+    {
+        type            epsilonWallFunction;
+        value           $internalField;
+    }
+
+    PROCESSOR
+    {
+        type            epsilonWallFunction;
+        value           $internalField;
+    }
+
+    FAN
+    {
+        type            epsilonWallFunction;
+        value           $internalField;
+    }
+
+    MRF_region
+    {
+        type            epsilonWallFunction;
+        value           $internalField;
+    }
+
+    OUTLET_01
+    {
+        type            inletOutlet;
+        inletValue      uniform 0.0377336;
+        value           uniform 0.0377336;
+    }
+
+    OUTLET_02
+    {
+        type            inletOutlet;
+        inletValue      uniform 0.0377336;
+        value           uniform 0.0377336;
+    }
+
+    domain0_to_v_CPU
+    {
+        type            epsilonWallFunction;
+        value           $internalField;
+    }
+
+    domain0_to_v_fins
+    {
+        type            epsilonWallFunction;
+        value           $internalField;
+    }
+}
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/0.orig/domain0/k b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/0.orig/domain0/k
new file mode 100644
index 0000000000000000000000000000000000000000..85e1c3da69beeb05fe4012ece351c0834617ef0a
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/0.orig/domain0/k
@@ -0,0 +1,87 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       volScalarField;
+    object      k;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+dimensions      [0 2 -2 0 0 0 0];
+
+internalField   uniform 0.5;
+
+boundaryField
+{
+     #includeEtc "caseDicts/setConstraintTypes"
+    FAN_SHROUD
+    {
+        type            kqRWallFunction;
+        value           $internalField;
+    }
+
+    CABINET
+    {
+        type            kqRWallFunction;
+        value           $internalField;
+    }
+
+    FINS
+    {
+        type            kqRWallFunction;
+        value           $internalField;
+    }
+
+    PROCESSOR
+    {
+        type            kqRWallFunction;
+        value           $internalField;
+    }
+
+    FAN
+    {
+        type            kqRWallFunction;
+        value           $internalField;
+    }
+
+    MRF_region
+    {
+        type            kqRWallFunction;
+        value           $internalField;
+    }
+
+    OUTLET_01
+    {
+        type            inletOutlet;
+        inletValue      uniform 0.00375;
+        value           uniform 0.00375;
+    }
+
+    OUTLET_02
+    {
+        type            inletOutlet;
+        inletValue      uniform 0.00375;
+        value           uniform 0.00375;
+    }
+
+    domain0_to_v_CPU
+    {
+        type            kqRWallFunction;
+        value           $internalField;
+    }
+
+    domain0_to_v_fins
+    {
+        type            kqRWallFunction;
+        value           $internalField;
+    }
+}
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/0.orig/domain0/nut b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/0.orig/domain0/nut
new file mode 100644
index 0000000000000000000000000000000000000000..aec3cd4de9420a0fcadba9df7386d34e9f0ce4df
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/0.orig/domain0/nut
@@ -0,0 +1,85 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       volScalarField;
+    object      nut;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+dimensions      [0 2 -1 0 0 0 0];
+
+internalField   uniform 0;
+
+boundaryField
+{
+     #includeEtc "caseDicts/setConstraintTypes"
+    FAN_SHROUD
+    {
+        type            nutkWallFunction;
+        value           $internalField;
+    }
+
+    CABINET
+    {
+        type            nutkWallFunction;
+        value           $internalField;
+    }
+
+    FINS
+    {
+        type            nutkWallFunction;
+        value           $internalField;
+    }
+
+    PROCESSOR
+    {
+        type            nutkWallFunction;
+        value           $internalField;
+    }
+
+    FAN
+    {
+        type            nutkWallFunction;
+        value           $internalField;
+    }
+
+    MRF_region
+    {
+        type            nutkWallFunction;
+        value           $internalField;
+    }
+
+    OUTLET_01
+    {
+        type            calculated;
+        value           $internalField;
+    }
+
+    OUTLET_02
+    {
+        type            calculated;
+        value           $internalField;
+    }
+
+    domain0_to_v_CPU
+    {
+        type            nutkWallFunction;
+        value           $internalField;
+    }
+
+    domain0_to_v_fins
+    {
+        type            nutkWallFunction;
+        value           $internalField;
+    }
+}
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/0.orig/domain0/p b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/0.orig/domain0/p
new file mode 100644
index 0000000000000000000000000000000000000000..da87f2e8d44817291946c1333f7132d7da56c050
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/0.orig/domain0/p
@@ -0,0 +1,77 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       volScalarField;
+    object      p;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+dimensions      [1 -1 -2 0 0 0 0];
+
+internalField   uniform 101325;
+
+boundaryField
+{
+    #includeEtc "caseDicts/setConstraintTypes"
+    FAN_SHROUD
+    {
+        type            zeroGradient;
+    }
+
+    CABINET
+    {
+        type            zeroGradient;
+    }
+
+    FINS
+    {
+        type            zeroGradient;
+    }
+
+    PROCESSOR
+    {
+        type            zeroGradient;
+    }
+
+    FAN
+    {
+        type            zeroGradient;
+    }
+
+    MRF_region
+    {
+        type            zeroGradient;
+    }
+
+    OUTLET_01
+    {
+        type            fixedValue;
+        value           uniform 101325;
+    }
+
+    OUTLET_02
+    {
+        type            fixedValue;
+        value           uniform 101325;
+    }
+
+    domain0_to_v_CPU
+    {
+        type            zeroGradient;
+    }
+
+    domain0_to_v_fins
+    {
+        type            zeroGradient;
+    }
+}
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/0.orig/domain0/p_rgh b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/0.orig/domain0/p_rgh
new file mode 100644
index 0000000000000000000000000000000000000000..4300f3cbd96f4855caf1f85d5d1d6b03b42a4460
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/0.orig/domain0/p_rgh
@@ -0,0 +1,85 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       volScalarField;
+    object      p_rgh;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+dimensions      [1 -1 -2 0 0 0 0];
+
+internalField   uniform 101325;
+
+boundaryField
+{
+     #includeEtc "caseDicts/setConstraintTypes"
+    FAN_SHROUD
+    {
+        type            fixedFluxPressure;
+        value           $internalField;
+    }
+
+    CABINET
+    {
+        type            fixedFluxPressure;
+        value           $internalField;
+    }
+
+    FINS
+    {
+        type            fixedFluxPressure;
+        value           $internalField;
+    }
+
+    PROCESSOR
+    {
+        type            fixedFluxPressure;
+        value           $internalField;
+    }
+
+    FAN
+    {
+        type            fixedFluxPressure;
+        value           $internalField;
+    }
+
+    MRF_region
+    {
+        type            fixedFluxPressure;
+        value           $internalField;
+    }
+
+    OUTLET_01
+    {
+        type            fixedValue;
+        value           $internalField;
+    }
+
+    OUTLET_02
+    {
+        type            fixedValue;
+        value           $internalField;
+    }
+
+    domain0_to_v_CPU
+    {
+        type            fixedFluxPressure;
+        value           $internalField;
+    }
+
+    domain0_to_v_fins
+    {
+        type            fixedFluxPressure;
+        value           $internalField;
+    }
+}
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/0.orig/v_CPU/T b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/0.orig/v_CPU/T
new file mode 100644
index 0000000000000000000000000000000000000000..b2ab9c4d1b07afb86d4fffcd09611bfa448c53c3
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/0.orig/v_CPU/T
@@ -0,0 +1,73 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       volScalarField;
+    object      T;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+dimensions      [0 0 0 1 0 0 0];
+
+internalField   uniform 300;
+
+boundaryField
+{
+     #includeEtc "caseDicts/setConstraintTypes"
+    PROCESSOR
+    {
+        type            externalWallHeatFluxTemperature;
+        kappaMethod     solidThermo;
+        mode            flux;
+        Ta              $internalField;
+        q               uniform 0;
+        kappaLayers     ( 0 );
+        thicknessLayers ( 0 );
+        value           $internalField;
+        kappaName       none;
+    }
+
+    v_CPU_to_domain0
+    {
+        type            compressible::turbulentTemperatureRadCoupledMixed;
+        qrNbr           none;
+        qr              none;
+        Tnbr            T;
+        kappaMethod     solidThermo;
+        useImplicit     true;
+        value           $internalField;
+    }
+
+    CABINET
+    {
+        type            externalWallHeatFluxTemperature;
+        kappaMethod     solidThermo;
+        mode            flux;
+        Ta              $internalField;
+        q               uniform 0;
+        kappaLayers     ( 0 );
+        thicknessLayers ( 0 );
+        value           $internalField;
+        kappaName       none;
+    }
+
+    v_CPU_to_v_fins
+    {
+        type            compressible::turbulentTemperatureRadCoupledMixed;
+        qrNbr           none;
+        qr              none;
+        Tnbr            T;
+        kappaMethod     solidThermo;
+        useImplicit     true;
+        value           $internalField;
+    }
+}
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/0.orig/v_CPU/p b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/0.orig/v_CPU/p
new file mode 100644
index 0000000000000000000000000000000000000000..4f77f63c0773a840fc5f29451705ac04f68d4dc6
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/0.orig/v_CPU/p
@@ -0,0 +1,45 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       volScalarField;
+    object      p;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+dimensions      [1 -1 -2 0 0 0 0];
+
+internalField   uniform 101325;
+
+boundaryField
+{
+     #includeEtc "caseDicts/setConstraintTypes"
+    PROCESSOR
+    {
+        type            zeroGradient;
+    }
+
+    v_CPU_to_domain0
+    {
+        type            zeroGradient;
+    }
+
+    CABINET
+    {
+        type            zeroGradient;
+    }
+
+    v_CPU_to_v_fins
+    {
+        type            zeroGradient;
+    }
+}
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/0.orig/v_fins/T b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/0.orig/v_fins/T
new file mode 100644
index 0000000000000000000000000000000000000000..a29a73c3277f425361f92fce8395a19d4a258f2b
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/0.orig/v_fins/T
@@ -0,0 +1,48 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       volScalarField;
+    object      T;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+dimensions      [0 0 0 1 0 0 0];
+
+internalField   uniform 300;
+
+boundaryField
+{
+    #includeEtc "caseDicts/setConstraintTypes"
+
+    v_fins_to_domain0
+    {
+        type            compressible::turbulentTemperatureRadCoupledMixed;
+        qrNbr           none;
+        qr              none;
+        Tnbr            T;
+        kappaMethod     solidThermo;
+        useImplicit     true;
+        value           $internalField;
+    }
+
+    v_fins_to_v_CPU
+    {
+        type            compressible::turbulentTemperatureRadCoupledMixed;
+        qrNbr           none;
+        qr              none;
+        Tnbr            T;
+        kappaMethod     solidThermo;
+        useImplicit     true;
+        value           $internalField;
+    }
+}
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/0.orig/v_fins/p b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/0.orig/v_fins/p
new file mode 100644
index 0000000000000000000000000000000000000000..1a8d5ef49fc049a1dec39312620b61d39378bc86
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/0.orig/v_fins/p
@@ -0,0 +1,35 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       volScalarField;
+    object      p;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+dimensions      [1 -1 -2 0 0 0 0];
+
+internalField   uniform 101325;
+
+boundaryField
+{
+     #includeEtc "caseDicts/setConstraintTypes"
+    v_fins_to_domain0
+    {
+        type            zeroGradient;
+    }
+
+    v_fins_to_v_CPU
+    {
+        type            zeroGradient;
+    }
+}
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/Allclean b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/Allclean
new file mode 100755
index 0000000000000000000000000000000000000000..b7b08b1052100d3e593cc8a524fde5741c0ffa10
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/Allclean
@@ -0,0 +1,19 @@
+#!/bin/sh
+cd "${0%/*}" || exit                                # Run from this directory
+. ${WM_PROJECT_DIR:?}/bin/tools/CleanFunctions      # Tutorial run functions
+#------------------------------------------------------------------------------
+
+cleanCase0
+
+foamCleanPolyMesh -region domain0
+foamCleanPolyMesh -region v_CPU
+foamCleanPolyMesh -region v_fins
+
+# Remove surfaces and features
+rm -rf constant/triSurface
+rm -rf constant/extendedFeatureEdgeMesh > /dev/null 2>&1
+
+rm -rf constant/cellToRegion
+rm -rf constant/*/polyMesh  # region meshes
+
+#------------------------------------------------------------------------------
diff --git a/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/Allrun-parallel b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/Allrun-parallel
new file mode 100755
index 0000000000000000000000000000000000000000..67a4ee51a281b77a35f95eb05add4534f7f55b1c
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/Allrun-parallel
@@ -0,0 +1,26 @@
+#!/bin/sh
+cd "${0%/*}" || exit                                # Run from this directory
+. ${WM_PROJECT_DIR:?}/bin/tools/RunFunctions        # Tutorial run functions
+#------------------------------------------------------------------------------
+
+./Allrun.pre
+
+# Run
+runParallel $(getApplication)
+
+# Reconstruct
+reconstructParMesh -allRegions -constant
+reconstructPar -allRegions
+
+# Reconstruct
+#for region in $(foamListRegions)
+#do
+#    runParallel -s reconstruct-$region \
+#        redistributePar -reconstruct -region $region
+#done
+
+echo
+echo "Use paraFoam -touch-all to create files for paraview post-processing"
+echo
+
+#------------------------------------------------------------------------------
diff --git a/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/Allrun.pre b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/Allrun.pre
new file mode 100755
index 0000000000000000000000000000000000000000..02a2e9e66767c7a7a55b3fc0feb07c53a3d4d5c0
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/Allrun.pre
@@ -0,0 +1,20 @@
+#!/bin/sh
+cd "${0%/*}" || exit                                # Run from this directory
+. ${WM_PROJECT_DIR:?}/bin/tools/RunFunctions        # Tutorial run functions
+#------------------------------------------------------------------------------
+
+# copy cpu surface from resources directory
+cp -rf \
+    "$FOAM_TUTORIALS"/resources/geometry/cpuCabinet \
+    constant/triSurface
+
+runApplication blockMesh
+runApplication surfaceFeatureExtract
+runApplication snappyHexMesh -overwrite
+runApplication $decompDict decomposePar
+restore0Dir -processor
+
+runParallel splitMeshRegions -cellZones -overwrite
+runParallel topoSet -region domain0
+
+#------------------------------------------------------------------------------
diff --git a/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/constant/domain0/MRFProperties b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/constant/domain0/MRFProperties
new file mode 100644
index 0000000000000000000000000000000000000000..43f54e1382ba754f95809acdfea99f71bfd0aef9
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/constant/domain0/MRFProperties
@@ -0,0 +1,29 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "constant";
+    object      MRFProperties;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+VC_1
+{
+    cellZone        v_MRF;
+    active          true;
+    nonRotatingPatches ();
+    origin          (-0.01 0.04 -0.06);
+    axis            (1 0 0);
+    omega           209.44;
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/constant/domain0/thermophysicalProperties b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/constant/domain0/thermophysicalProperties
new file mode 100644
index 0000000000000000000000000000000000000000..55a209089fe822c0ab5e38d7ce4f6285fb477c84
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/constant/domain0/thermophysicalProperties
@@ -0,0 +1,50 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "constant";
+    object      thermophysicalProperties;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+thermoType
+{
+    type            heRhoThermo;
+    mixture         pureMixture;
+    transport       const;
+    thermo          hConst;
+    equationOfState perfectGas;
+    specie          specie;
+    energy          sensibleEnthalpy;
+}
+
+mixture
+{
+    specie
+    {
+        nMoles          1;
+        molWeight       28.966;
+    }
+
+    thermodynamics
+    {
+        Cp              1006.43;
+        Hf              0;
+    }
+
+    transport
+    {
+        mu              1.846e-05;
+        Pr              0.706414;
+    }
+}
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/constant/domain0/turbulenceProperties b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/constant/domain0/turbulenceProperties
new file mode 100644
index 0000000000000000000000000000000000000000..cb92da1b05ab0f3239581c668cbbe469aa3cde05
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/constant/domain0/turbulenceProperties
@@ -0,0 +1,27 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "constant";
+    object      turbulenceProperties;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+simulationType  RAS;
+
+RAS
+{
+    RASModel        realizableKE;
+    turbulence      on;
+    printCoeffs     on;
+}
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/constant/g b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/constant/g
new file mode 100644
index 0000000000000000000000000000000000000000..87db885d9c10bfed543cd2a648da2f197e98d5db
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/constant/g
@@ -0,0 +1,23 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       uniformDimensionedVectorField;
+    location    "constant";
+    object      g;
+}
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+dimensions      [0 1 -2 0 0 0 0];
+
+value           (0 -9.81 0);
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/constant/regionProperties b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/constant/regionProperties
new file mode 100644
index 0000000000000000000000000000000000000000..ebdf599a2c7ad9769ba02ce2ab360b656197a8b2
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/constant/regionProperties
@@ -0,0 +1,24 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      regionProperties;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+regions
+(
+    solid ( v_CPU v_fins  )
+    fluid ( domain0  )
+);
+
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/constant/v_CPU/thermophysicalProperties b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/constant/v_CPU/thermophysicalProperties
new file mode 100644
index 0000000000000000000000000000000000000000..e35bcfbe5218605672d045b782e53a47eda26625
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/constant/v_CPU/thermophysicalProperties
@@ -0,0 +1,55 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "constant";
+    object      thermophysicalProperties;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+thermoType
+{
+    type            heSolidThermo;
+    mixture         pureMixture;
+    transport       constIso;
+    thermo          hConst;
+    equationOfState rhoConst;
+    specie          specie;
+    energy          sensibleEnthalpy;
+}
+
+mixture
+{
+    specie
+    {
+        nMoles          1;
+        molWeight       26.98;
+    }
+
+    thermodynamics
+    {
+        Hf              0;
+        Sf              0;
+        Cp              871;
+    }
+
+    transport
+    {
+        kappa           202.4;
+    }
+
+    equationOfState
+    {
+        rho             2719;
+    }
+}
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/constant/v_fins/thermophysicalProperties b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/constant/v_fins/thermophysicalProperties
new file mode 100644
index 0000000000000000000000000000000000000000..e35bcfbe5218605672d045b782e53a47eda26625
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/constant/v_fins/thermophysicalProperties
@@ -0,0 +1,55 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "constant";
+    object      thermophysicalProperties;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+thermoType
+{
+    type            heSolidThermo;
+    mixture         pureMixture;
+    transport       constIso;
+    thermo          hConst;
+    equationOfState rhoConst;
+    specie          specie;
+    energy          sensibleEnthalpy;
+}
+
+mixture
+{
+    specie
+    {
+        nMoles          1;
+        molWeight       26.98;
+    }
+
+    thermodynamics
+    {
+        Hf              0;
+        Sf              0;
+        Cp              871;
+    }
+
+    transport
+    {
+        kappa           202.4;
+    }
+
+    equationOfState
+    {
+        rho             2719;
+    }
+}
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/blockMeshDict b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/blockMeshDict
new file mode 100644
index 0000000000000000000000000000000000000000..8fc602928f6796ca79045ae43266d318621a816a
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/blockMeshDict
@@ -0,0 +1,93 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      blockMeshDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+scale   1;
+
+vertices
+(
+    ( -0.04478 -0.00550502 -0.29 )
+    ( 0.27928 -0.00550502 -0.29 )
+    ( 0.27928 0.0845552 -0.29 )
+    ( -0.04478 0.0845552 -0.29 )
+    ( -0.04478 -0.00550502 0.04 )
+    ( 0.27928 -0.00550502 0.04 )
+    ( 0.27928 0.0845552 0.04 )
+    ( -0.04478 0.0845552 0.04 )
+);
+
+blocks
+(
+    hex (0 1 2 3 4 5 6 7) ( 108 30 110 ) simpleGrading ( 1 1 1 )
+);
+
+edges
+(
+);
+
+boundary
+(
+    XMin
+    {
+        type wall;
+        faces
+        (
+            (0 4 7 3)
+        );
+    }
+    XMax
+    {
+        type wall;
+        faces
+        (
+            (1 2 6 5)
+        );
+    }
+    YMin
+    {
+        type wall;
+        faces
+        (
+            (0 1 5 4)
+        );
+    }
+    YMax
+    {
+        type wall;
+        faces
+        (
+            (3 7 6 2)
+        );
+    }
+    ZMin
+    {
+        type wall;
+        faces
+        (
+            (0 3 2 1)
+        );
+    }
+    ZMax
+    {
+        type wall;
+        faces
+        (
+            (4 5 6 7)
+        );
+    }
+);
+
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/controlDict b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/controlDict
new file mode 100644
index 0000000000000000000000000000000000000000..a93b069382f5ea82509bc380b226d9821f146d1e
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/controlDict
@@ -0,0 +1,53 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      fvSolution;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+application     chtMultiRegionSimpleFoam;
+
+startFrom       startTime;
+
+startTime       0;
+
+stopAt          endTime;
+
+endTime         200;
+
+deltaT          1;
+
+writeControl    timeStep;
+
+writeInterval   10;
+
+purgeWrite      0;
+
+writeFormat     binary;
+
+writePrecision  8;
+
+writeCompression off;
+
+timeFormat      general;
+
+timePrecision   8;
+
+runTimeModifiable true;
+
+functions
+{
+    #include    "probes"
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/createBafflesDict b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/createBafflesDict
new file mode 100644
index 0000000000000000000000000000000000000000..01a57b46da4c7c07049b9972bbbc641d564f7426
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/createBafflesDict
@@ -0,0 +1,24 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "system";
+    object      createBafflesDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+internalFacesOnly true;
+
+baffles
+{
+}
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/decomposeParDict b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/decomposeParDict
new file mode 100644
index 0000000000000000000000000000000000000000..1c0863a2654d83ccdae2deb6bbba9fb60d6a039f
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/decomposeParDict
@@ -0,0 +1,36 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Web:      www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      decomposeParDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+numberOfSubdomains  10;
+
+//method          assembleDecomp;
+// method          hierarchical;
+// method          simple;
+// method          manual;
+method  scotch;
+
+constraints
+{
+    faces
+    {
+        type    preserveFaceZones;
+        //zones   (f1 f2 f3);
+        zones (domain0_to_v_CPU domain0_to_v_fins v_CPU_to_v_fins);
+        enabled true;
+    }
+}
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/domain0/decomposeParDict b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/domain0/decomposeParDict
new file mode 100644
index 0000000000000000000000000000000000000000..a28797127cc0479f280cea4d0ca1688efe1f9693
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/domain0/decomposeParDict
@@ -0,0 +1,30 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "system";
+    object      decomposeParDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+numberOfSubdomains 4;
+
+method  assembly;
+
+coeffs
+{
+    numberOfSubdomains 4;
+    method      scotch;
+    dataFile    "cellDecompose.dat";
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/domain0/fvSchemes b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/domain0/fvSchemes
new file mode 100644
index 0000000000000000000000000000000000000000..7ee82964973c4a76109a71bc1c3509457c020564
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/domain0/fvSchemes
@@ -0,0 +1,68 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "system";
+    object      fvSchemes;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+ddtSchemes
+{
+    default         steadyState;
+}
+
+divSchemes
+{
+    div(phi,U)      bounded Gauss upwind;
+    div(phi,k)      bounded Gauss linearUpwind grad(k);
+    div(phi,epsilon) bounded Gauss linearUpwind grad(epsilon);
+    div((muEff*dev2(T(grad(U))))) Gauss linear;
+    div(((rho*nuEff)*dev2(T(grad(U))))) Gauss linear;
+    div(phi,K)      bounded Gauss linearUpwind default;
+    div(phi,h)      bounded Gauss upwind;
+    div(phid,p)     bounded Gauss upwind;
+}
+
+laplacianSchemes
+{
+    default         Gauss linear limited 0.333;
+}
+
+interpolationSchemes
+{
+    default         linear;
+}
+
+snGradSchemes
+{
+    default         limited 0.333;
+}
+
+gradSchemes
+{
+    default         Gauss linear;
+}
+
+fluxRequired
+{
+    default         no;
+    pCorr           ;
+    p_rgh           ;
+}
+
+wallDist
+{
+    method          meshWave;
+    nRequired       false;
+}
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/domain0/fvSolution b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/domain0/fvSolution
new file mode 100644
index 0000000000000000000000000000000000000000..5342112d6f061ee3f014fb67b2e8dfe31be45bf8
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/domain0/fvSolution
@@ -0,0 +1,77 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "system";
+    object      fvSolution;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+solvers
+{
+    rho
+    {
+        solver          PCG
+        preconditioner  DIC;
+        tolerance       1e-7;
+        relTol          0;
+    }
+
+    p_rgh
+    {
+        solver           PBiCGStab;
+        preconditioner   FDIC;
+        tolerance        1e-7;
+        relTol           0.01;
+        smoother         GaussSeidel;
+        cacheAgglomeration true;
+    }
+
+
+   "(U|k|h|epsilon|)"
+    {
+        solver           PBiCGStab;
+        preconditioner   DILU;
+        tolerance        1e-6;
+        relTol           0.05;
+    }
+}
+
+SIMPLE
+{
+    momentumPredictor true;
+    nNonOrthogonalCorrectors 0;
+    frozenFlow      false;
+
+    residualControl
+    {
+        default         1e-7;
+    }
+}
+
+relaxationFactors
+{
+    fields
+    {
+        p_rgh           0.7;
+        rho             1;
+    }
+
+    equations
+    {
+        U               0.4;
+        h               0.9;
+        k               0.7;
+        epsilon         0.7;
+    }
+}
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/domain0/topoSetDict b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/domain0/topoSetDict
new file mode 100644
index 0000000000000000000000000000000000000000..a66e95b0de1026039848480b0d53d87ac26dead5
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/domain0/topoSetDict
@@ -0,0 +1,40 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "system";
+    object      topoSetDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+actions
+(
+    {
+        name            v_MRF_set;
+        type            cellSet;
+        action          new;
+        source          searchableSurfaceToCell;
+        surfaceType     searchableCylinder;
+        point1          (-0.0032 0.037517 -0.058);
+        point2          (-0.015 0.037517 -0.058);
+        radius          0.021;
+    }
+
+    {
+        name            v_MRF;
+        type            cellZoneSet;
+        action          new;
+        source          setToCellZone;
+        set             v_MRF_set;
+    }
+);
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/fvSchemes b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/fvSchemes
new file mode 100644
index 0000000000000000000000000000000000000000..1f12348779745308b335db350b673cd79bc11d19
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/fvSchemes
@@ -0,0 +1,43 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "system";
+    object      fvSchemes;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+ddtSchemes
+{
+}
+
+divSchemes
+{
+}
+
+laplacianSchemes
+{
+}
+
+interpolationSchemes
+{
+}
+
+snGradSchemes
+{
+}
+
+gradSchemes
+{
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/fvSolution b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/fvSolution
new file mode 100644
index 0000000000000000000000000000000000000000..39f6c38067ae8455b73b624280e911b384a1e805
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/fvSolution
@@ -0,0 +1,17 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      fvSolution;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/meshQualityDict b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/meshQualityDict
new file mode 100644
index 0000000000000000000000000000000000000000..ecb05817cb750f708319aeb97a8c0b6e73693cb1
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/meshQualityDict
@@ -0,0 +1,54 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      snappyHexMeshDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+
+minVol          1e-13;
+minTetQuality   1e-16;
+minArea         1e-13;
+minTwist        0.05;
+minDeterminant  1e-06;
+minFaceWeight   0.02;
+minVolRatio     0.01;
+minTriangleTwist -1;
+minFlatness     0.5;
+maxNonOrtho     70;
+maxBoundarySkewness 20;
+maxInternalSkewness 4;
+maxConcave      80;
+nSmoothScale    4;
+errorReduction  0.75;
+
+relaxed
+{
+    minVol          1e-30;
+    minTetQuality   1e-30;
+    minArea         1e-30;
+    minTwist        0.001;
+    minDeterminant  1e-06;
+    minFaceWeight   1e-06;
+    minVolRatio     0.01;
+    minTriangleTwist -1;
+    minFlatness     0.5;
+    maxNonOrtho     75;
+    maxBoundarySkewness 20;
+    maxInternalSkewness 8;
+    maxConcave      80;
+    nSmoothScale    4;
+    errorReduction  0.75;
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/probes b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/probes
new file mode 100644
index 0000000000000000000000000000000000000000..371870a92906246dc32bc2308d200a92498542c6
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/probes
@@ -0,0 +1,82 @@
+// -*- C++ -*-
+
+_volFieldValue
+{
+    type            volFieldValue;
+    libs            (fieldFunctionObjects);
+    enabled         true;
+    writeControl    timeStep;
+    writeInterval   1;
+    log             true;
+    valueOutput     false;
+    writeFields     false;
+}
+
+Volume1_v_CPU
+{
+    ${_volFieldValue}
+
+    regionType      cellZone;
+    name            v_CPU;
+    region          v_CPU;
+    operation       volAverage;
+    fields          ( T );
+}
+
+Volume3_v_fins
+{
+    ${_volFieldValue}
+
+    regionType      cellZone;
+    name            v_fins;
+    region          v_fins;
+    operation       volAverage;
+    fields          ( T );
+}
+
+probesFins
+{
+    type 	    probes;
+    libs            (sampling);
+    writeControl    timeStep;
+    writeInterval   1;
+    interpolationScheme cell;
+    region	        v_fins;
+    setFormat          raw;
+    log             true;
+    valueOutput     false;
+    writeFields     false;
+
+    probeLocations
+    (
+        (0.118 0.01 -0.125)
+        (0.118 0.03 -0.125)
+    );
+
+    fields          ( T );
+}
+
+probesFluid
+{
+    type 	    probes;
+    libs            (sampling);
+    writeControl    timeStep;
+    writeInterval   1;
+    interpolationScheme cell;
+    region	        domain0;
+    setFormat          raw;
+    log             true;
+    valueOutput     false;
+    writeFields     false;
+
+    probeLocations
+    (
+        (0.118 0.035 -0.125)
+        (0.118 0.07 -0.125)
+    );
+
+    fields          ( T U);
+}
+#remove (_volFieldValue _surfaceFieldValue)
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/snappyHexMeshDict b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/snappyHexMeshDict
new file mode 100644
index 0000000000000000000000000000000000000000..31783691d5749b71d2877d5fc6074adf5a21b2b2
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/snappyHexMeshDict
@@ -0,0 +1,205 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      snappyHexMeshDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+// Which of the steps to run
+castellatedMesh true;
+snap            true;
+addLayers       false;
+
+
+geometry
+{
+    Cabinet_withMesh.obj
+    {
+        type    triSurfaceMesh;
+        name    Cabinet_withMesh;
+        regions
+        {
+            FAN_SHROUD
+            {
+                name    FAN_SHROUD;
+            }
+            OUTLET_01
+            {
+                name    OUTLET_01;
+            }
+            OUTLET_02
+            {
+                name    OUTLET_02;
+            }
+            CABINET
+            {
+                name    CABINET;
+            }
+            FINS
+            {
+                name    FINS;
+            }
+            PROCESSOR
+            {
+                name    PROCESSOR;
+            }
+            FAN
+            {
+                name    FAN;
+            }
+        }
+    }
+};
+
+castellatedMeshControls
+{
+    maxLocalCells   200000000;
+    maxGlobalCells  300000000;
+    minRefinementCells 20;
+    nCellsBetweenLevels 4;
+    maxLoadUnbalance 0.1;
+    allowFreeStandingZoneFaces true;
+    resolveFeatureAngle      30;
+    features
+    (
+        {
+            file "MRF_region.eMesh";
+            level 0;
+        }
+    );
+
+    refinementSurfaces
+    {
+        Cabinet_withMesh
+        {
+            level (0 0);
+            regions
+            {
+                FAN_SHROUD
+                {
+                    level (2 2);
+                    status 1;
+                }
+                OUTLET_01
+                {
+                    level (0 0);
+                    status 1;
+                }
+                OUTLET_02
+                {
+                    level (0 0);
+                    status 1;
+                }
+                CABINET
+                {
+                    level (0 0);
+                    status 1;
+                }
+                FINS
+                {
+                    level (3 3);
+                    status 1;
+                }
+                PROCESSOR
+                {
+                    level (3 3);
+                    status 1;
+                }
+                FAN
+                {
+                    level (3 3);
+                    status 1;
+                }
+            }
+        }
+
+        MRF_region
+        {
+            level (0 0);
+            regions
+            {
+                MRF_region
+                {
+                    level (2 2);
+                    status 1;
+                }
+            }
+        }
+    }
+
+    refinementRegions
+    {
+    }
+
+    locationsInMesh
+    (
+        (( 0.11725 0.0395251 -0.21545548 ) domain0 )
+        (( 0.1063594 0.0040546151 -0.12500001 ) v_CPU )
+        (( 0.1055988 0.0081817387 -0.11700001 ) v_fins )
+        //(( -0.0041739814 0.029459859 -0.038183494 ) v_MRF )
+    );
+}
+
+
+snapControls
+{
+    tolerance       2;
+    implicitFeatureSnap true;
+    explicitFeatureSnap false;
+    multiRegionFeatureSnap true;
+    detectNearSurfacesSnap true;
+    nSmoothPatch    3;
+    nSolveIter      50;
+    nRelaxIter      5;
+    nFeatureSnapIter 10;
+    nSmoothInternal 3;
+    nFaceSplitInterval -1;
+}
+
+
+addLayersControls
+{
+    layers
+    {
+    }
+    relativeSizes    true;
+    expansionRatio    1.2;
+    firstLayerThickness   0.1;
+    featureAngle    85;
+    slipFeatureAngle 30;
+    nGrow           0;
+    nBufferCellsNoExtrude 0;
+    minMedianAxisAngle 90;
+    maxFaceThicknessRatio 0.2;
+    maxThicknessToMedialRatio 0.3;
+    minThickness    1e-06;
+    nLayerIter      50;
+    nRelaxIter      5;
+    nSmoothSurfaceNormals 10;
+    nSmoothNormals  3;
+    nSmoothThickness 10;
+    nRelaxedIter    10;
+    nMedialAxisIter 10;
+}
+
+
+meshQualityControls
+{
+    #include "meshQualityDict"
+}
+
+
+debug           0;
+
+mergeTolerance  1e-08;
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/surfaceFeatureExtractDict b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/surfaceFeatureExtractDict
new file mode 100644
index 0000000000000000000000000000000000000000..4cd6552cfc498382959a5f7e0b249463206417a1
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/surfaceFeatureExtractDict
@@ -0,0 +1,29 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      surfaceFeatureExtractDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+MRF_region.obj
+{
+    extractionMethod extractFromSurface;
+    writeObj        yes;
+
+    extractFromSurfaceCoeffs
+    {
+        includedAngle   150;
+    }
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/topoSetDict.f1 b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/topoSetDict.f1
new file mode 100755
index 0000000000000000000000000000000000000000..249e3e89daf91de68b2984dce3a4b1ce40e46b5f
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/topoSetDict.f1
@@ -0,0 +1,85 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Web:      www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      topoSetDict;
+}
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+actions
+(
+    // 0. Create cell sets
+//     {
+//         name    c1;
+//         type    cellSet;
+//         action  new;
+//         source  zoneToCell;
+// 	    zones	(domain0);
+//
+//     }
+     {
+        name    c1;
+        type    cellSet;
+        action  new;
+        source  faceZoneToCell;//zoneToCel;
+        option  master;
+	    zones	(domain0_to_v_CPU);
+    }
+
+     {
+        name    c1;
+        type    cellSet;
+        action  add;
+        source  faceZoneToCell;//zoneToCel;
+        option  slave;
+	    zones	(domain0_to_v_CPU);
+    }
+
+//      {
+//         name    c2;
+//         type    cellSet;
+//         action  new;
+//         source  zoneToCell;
+// 	    zones	(v_CPU);
+//
+//     }
+//      {
+//         name    f2;
+//         type    faceSet;
+//         action  new;
+//         source  cellToFace;
+//         option  all;
+// 	    sets	(c2);
+//
+//     }
+//
+//      {
+//         name    c3;
+//         type    cellSet;
+//         action  new;
+//         source  zoneToCell;
+// 	    zones	(v_fins);
+//
+//     }
+//      {
+//         name    f3;
+//         type    faceSet;
+//         action  new;
+//         source  cellToFace;
+//         option  all;
+// 	    sets	(c3);
+//
+//     }
+);
+
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/v_CPU/decomposeParDict b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/v_CPU/decomposeParDict
new file mode 100644
index 0000000000000000000000000000000000000000..5705647dde4a8be511a8b099751110b43d30ca48
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/v_CPU/decomposeParDict
@@ -0,0 +1,28 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "system";
+    object      decomposeParDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+numberOfSubdomains  4;
+
+method          manual;
+
+coeffs
+{
+    numberOfSubdomains 4;
+    dataFile    "cellDecompose.dat";
+}
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/v_CPU/fvOptions b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/v_CPU/fvOptions
new file mode 100644
index 0000000000000000000000000000000000000000..2ef58c692c005f5dc3a139e1075f1bcab175a806
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/v_CPU/fvOptions
@@ -0,0 +1,36 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "system";
+    object      fvOptions;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+v_CPU_AbsoluteEnergySource
+{
+    type            scalarSemiImplicitSource;
+    active          true;
+
+    scalarSemiImplicitSourceCoeffs
+    {
+        selectionMode   cellZone;
+        cellZone        v_CPU;
+        volumeMode      absolute;
+
+        injectionRateSuSp
+        {
+            h           ( 100 0 );
+        }
+    }
+}
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/v_CPU/fvSchemes b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/v_CPU/fvSchemes
new file mode 100644
index 0000000000000000000000000000000000000000..f7d71ca9ba9bcf80566fe88f274415b55fb1eeda
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/v_CPU/fvSchemes
@@ -0,0 +1,49 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "system";
+    object      fvSchemes;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+ddtSchemes
+{
+    default         steadyState;
+}
+
+divSchemes
+{
+    default         Gauss linear;
+}
+
+laplacianSchemes
+{
+    default         Gauss linear limited 0.33;
+}
+
+interpolationSchemes
+{
+    default         linear;
+}
+
+snGradSchemes
+{
+    default         limited 0.33;
+}
+
+gradSchemes
+{
+    default         Gauss linear;
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/v_CPU/fvSolution b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/v_CPU/fvSolution
new file mode 100644
index 0000000000000000000000000000000000000000..b2148a1fd504b8039f64a84fbbdc5b01bdc6d815
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/v_CPU/fvSolution
@@ -0,0 +1,46 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "system";
+    object      fvSolution;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+solvers
+{
+    h
+    {
+        solver          PCG;
+        preconditioner  DIC;
+        nSweeps         2;
+        tolerance       1e-8;
+        relTol          0.05;
+    }
+}
+
+SIMPLE
+{
+    residualControl
+    {
+        default         1e-20;
+    }
+}
+
+relaxationFactors
+{
+    equations
+    {
+        h               1;
+    }
+}
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/v_fins/decomposeParDict b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/v_fins/decomposeParDict
new file mode 100644
index 0000000000000000000000000000000000000000..5705647dde4a8be511a8b099751110b43d30ca48
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/v_fins/decomposeParDict
@@ -0,0 +1,28 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "system";
+    object      decomposeParDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+numberOfSubdomains  4;
+
+method          manual;
+
+coeffs
+{
+    numberOfSubdomains 4;
+    dataFile    "cellDecompose.dat";
+}
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/v_fins/fvSchemes b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/v_fins/fvSchemes
new file mode 100644
index 0000000000000000000000000000000000000000..cba7ed9b8d0380aa26c94660b0064a77cdfb6978
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/v_fins/fvSchemes
@@ -0,0 +1,47 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "system";
+    object      fvSchemes;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+ddtSchemes
+{
+    default         steadyState;
+}
+
+divSchemes
+{
+    default         Gauss linear;
+}
+
+laplacianSchemes
+{
+    default         Gauss linear limited 0.333;
+}
+
+interpolationSchemes
+{
+    default         linear;
+}
+
+snGradSchemes
+{
+    default         limited 0.333;
+}
+
+gradSchemes
+{
+    default         Gauss linear;
+}
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/v_fins/fvSolution b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/v_fins/fvSolution
new file mode 100644
index 0000000000000000000000000000000000000000..3585ab8d61931a50decb8275fc10303b1a29be4a
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionSimpleFoam/cpuCabinet/system/v_fins/fvSolution
@@ -0,0 +1,51 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "system";
+    object      fvSolution;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+solvers
+{
+    h
+    {
+        solver          PCG;
+        preconditioner  DIC;
+        nSweeps         2;
+        tolerance       1e-8;
+        relTol          0.05;
+    }
+}
+
+SIMPLE
+{
+    residualControl
+    {
+        default         1e-20;
+    }
+}
+
+relaxationFactors
+{
+
+    fields
+    {
+    }
+
+    equations
+    {
+        h               1;
+    }
+}
+
+// ************************************************************************* //
diff --git a/tutorials/resources/geometry/cpuCabinet/Cabinet_withMesh.obj.gz b/tutorials/resources/geometry/cpuCabinet/Cabinet_withMesh.obj.gz
new file mode 100644
index 0000000000000000000000000000000000000000..81e2fb2be2cbb5d711e701ac2a28fef878a91e20
Binary files /dev/null and b/tutorials/resources/geometry/cpuCabinet/Cabinet_withMesh.obj.gz differ
diff --git a/tutorials/resources/geometry/cpuCabinet/MRF_region.obj.gz b/tutorials/resources/geometry/cpuCabinet/MRF_region.obj.gz
new file mode 100644
index 0000000000000000000000000000000000000000..e2463affa4264a370ee0a172a9db22f18c87ee32
Binary files /dev/null and b/tutorials/resources/geometry/cpuCabinet/MRF_region.obj.gz differ