From 341f2e0b991a6f93b9a400c0e8fed328504a3811 Mon Sep 17 00:00:00 2001
From: william <william@opencfd.co.uk>
Date: Fri, 6 Nov 2015 16:40:51 +0000
Subject: [PATCH] ENH: Added support for periodic AMI patches. When these
 patches do not fully overlap, the geometry will be replicated according to
 the transfomation of another coupled patch until full-overlap is achieved.

---
 .../constraint/cyclicAMI/cyclicAMIFvPatch.C   |   9 +-
 .../AMIInterpolation/AMIInterpolation.C       | 125 +++---
 .../AMIInterpolation/AMIInterpolation.H       |  12 +-
 .../cyclicAMIPointPatch/cyclicAMIPointPatch.C |   9 +-
 .../cyclicPeriodicAMIPolyPatch.C              | 391 ++++++++++++++++++
 .../cyclicPeriodicAMIPolyPatch.H              | 225 ++++++++++
 src/meshTools/Make/files                      |   3 +
 .../oscillatingInletPeriodicAMI2D/0/U         |  44 ++
 .../oscillatingInletPeriodicAMI2D/0/epsilon   |  45 ++
 .../oscillatingInletPeriodicAMI2D/0/k         |  45 ++
 .../oscillatingInletPeriodicAMI2D/0/nut       |  45 ++
 .../oscillatingInletPeriodicAMI2D/0/p         |  42 ++
 .../constant/dynamicMeshDict                  |  36 ++
 .../constant/polyMesh/blockMeshDict           | 158 +++++++
 .../constant/transportProperties              |  22 +
 .../constant/turbulenceProperties             |  30 ++
 .../system/controlDict                        |  53 +++
 .../system/fvSchemes                          |  63 +++
 .../system/fvSolution                         |  80 ++++
 19 files changed, 1386 insertions(+), 51 deletions(-)
 create mode 100644 src/meshTools/AMIInterpolation/patches/cyclicPeriodicAMI/cyclicPeriodicAMIPolyPatch/cyclicPeriodicAMIPolyPatch.C
 create mode 100644 src/meshTools/AMIInterpolation/patches/cyclicPeriodicAMI/cyclicPeriodicAMIPolyPatch/cyclicPeriodicAMIPolyPatch.H
 create mode 100644 tutorials/incompressible/pimpleDyMFoam/oscillatingInletPeriodicAMI2D/0/U
 create mode 100644 tutorials/incompressible/pimpleDyMFoam/oscillatingInletPeriodicAMI2D/0/epsilon
 create mode 100644 tutorials/incompressible/pimpleDyMFoam/oscillatingInletPeriodicAMI2D/0/k
 create mode 100644 tutorials/incompressible/pimpleDyMFoam/oscillatingInletPeriodicAMI2D/0/nut
 create mode 100644 tutorials/incompressible/pimpleDyMFoam/oscillatingInletPeriodicAMI2D/0/p
 create mode 100644 tutorials/incompressible/pimpleDyMFoam/oscillatingInletPeriodicAMI2D/constant/dynamicMeshDict
 create mode 100644 tutorials/incompressible/pimpleDyMFoam/oscillatingInletPeriodicAMI2D/constant/polyMesh/blockMeshDict
 create mode 100644 tutorials/incompressible/pimpleDyMFoam/oscillatingInletPeriodicAMI2D/constant/transportProperties
 create mode 100644 tutorials/incompressible/pimpleDyMFoam/oscillatingInletPeriodicAMI2D/constant/turbulenceProperties
 create mode 100644 tutorials/incompressible/pimpleDyMFoam/oscillatingInletPeriodicAMI2D/system/controlDict
 create mode 100644 tutorials/incompressible/pimpleDyMFoam/oscillatingInletPeriodicAMI2D/system/fvSchemes
 create mode 100644 tutorials/incompressible/pimpleDyMFoam/oscillatingInletPeriodicAMI2D/system/fvSolution

diff --git a/src/finiteVolume/fvMesh/fvPatches/constraint/cyclicAMI/cyclicAMIFvPatch.C b/src/finiteVolume/fvMesh/fvPatches/constraint/cyclicAMI/cyclicAMIFvPatch.C
index 5d8935139df..0f6064471f8 100644
--- a/src/finiteVolume/fvMesh/fvPatches/constraint/cyclicAMI/cyclicAMIFvPatch.C
+++ b/src/finiteVolume/fvMesh/fvPatches/constraint/cyclicAMI/cyclicAMIFvPatch.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2014 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2015 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -34,6 +34,13 @@ namespace Foam
 {
     defineTypeNameAndDebug(cyclicAMIFvPatch, 0);
     addToRunTimeSelectionTable(fvPatch, cyclicAMIFvPatch, polyPatch);
+    addNamedToRunTimeSelectionTable
+    (
+        fvPatch,
+        cyclicAMIFvPatch,
+        polyPatch,
+        cyclicPeriodicAMI
+    );
 }
 
 
diff --git a/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolation.C b/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolation.C
index 70372fc7244..192236ab293 100644
--- a/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolation.C
+++ b/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolation.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2014 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2015 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -604,7 +604,6 @@ void Foam::AMIInterpolation<SourcePatch, TargetPatch>::constructFromSurface
     }
 }
 
-
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
 template<class SourcePatch, class TargetPatch>
@@ -965,7 +964,7 @@ void Foam::AMIInterpolation<SourcePatch, TargetPatch>::update
                 tgtMagSf_,
                 triMode_,
                 reverseTarget_,
-                requireMatch_
+                requireMatch_ && (lowWeightCorrection_ < 0)
             )
         );
 
@@ -1035,28 +1034,7 @@ void Foam::AMIInterpolation<SourcePatch, TargetPatch>::update
         );
 
         // weights normalisation
-        normaliseWeights
-        (
-            srcMagSf_,
-            "source",
-            srcAddress_,
-            srcWeights_,
-            srcWeightsSum_,
-            AMIPtr->conformal(),
-            true,
-            lowWeightCorrection_
-        );
-        normaliseWeights
-        (
-            tgtMagSf_,
-            "target",
-            tgtAddress_,
-            tgtWeights_,
-            tgtWeightsSum_,
-            AMIPtr->conformal(),
-            true,
-            lowWeightCorrection_
-        );
+        normaliseWeights(AMIPtr->conformal(), true);
 
         // cache maps and reset addresses
         List<Map<label> > cMap;
@@ -1082,7 +1060,7 @@ void Foam::AMIInterpolation<SourcePatch, TargetPatch>::update
                 tgtMagSf_,
                 triMode_,
                 reverseTarget_,
-                requireMatch_
+                requireMatch_ && (lowWeightCorrection_ < 0)
             )
         );
 
@@ -1094,28 +1072,7 @@ void Foam::AMIInterpolation<SourcePatch, TargetPatch>::update
             tgtWeights_
         );
 
-        normaliseWeights
-        (
-            srcMagSf_,
-            "source",
-            srcAddress_,
-            srcWeights_,
-            srcWeightsSum_,
-            AMIPtr->conformal(),
-            true,
-            lowWeightCorrection_
-        );
-        normaliseWeights
-        (
-            tgtMagSf_,
-            "target",
-            tgtAddress_,
-            tgtWeights_,
-            tgtWeightsSum_,
-            AMIPtr->conformal(),
-            true,
-            lowWeightCorrection_
-        );
+        normaliseWeights(AMIPtr->conformal(), true);
     }
 
     if (debug)
@@ -1131,6 +1088,78 @@ void Foam::AMIInterpolation<SourcePatch, TargetPatch>::update
 }
 
 
+template<class SourcePatch, class TargetPatch>
+void Foam::AMIInterpolation<SourcePatch, TargetPatch>::append
+(
+    const SourcePatch& srcPatch,
+    const TargetPatch& tgtPatch
+)
+{
+    // create a new interpolation
+    autoPtr<AMIInterpolation<SourcePatch, TargetPatch> > newPtr
+    (
+        new AMIInterpolation<SourcePatch, TargetPatch>
+        (
+            srcPatch,
+            tgtPatch,
+            triMode_,
+            requireMatch_,
+            methodName_,
+            lowWeightCorrection_,
+            reverseTarget_
+        )
+    );
+
+    // combine new and current data
+    forAll(srcMagSf_, srcFaceI)
+    {
+        srcAddress_[srcFaceI].append(newPtr->srcAddress()[srcFaceI]);
+        srcWeights_[srcFaceI].append(newPtr->srcWeights()[srcFaceI]);
+        srcWeightsSum_[srcFaceI] += newPtr->srcWeightsSum()[srcFaceI];
+    }
+
+    forAll(tgtMagSf_, tgtFaceI)
+    {
+        tgtAddress_[tgtFaceI].append(newPtr->tgtAddress()[tgtFaceI]);
+        tgtWeights_[tgtFaceI].append(newPtr->tgtWeights()[tgtFaceI]);
+        tgtWeightsSum_[tgtFaceI] += newPtr->tgtWeightsSum()[tgtFaceI];
+    }
+}
+
+
+template<class SourcePatch, class TargetPatch>
+void Foam::AMIInterpolation<SourcePatch, TargetPatch>::normaliseWeights
+(
+    const bool conformal,
+    const bool output
+)
+{
+    normaliseWeights
+    (
+        srcMagSf_,
+        "source",
+        srcAddress_,
+        srcWeights_,
+        srcWeightsSum_,
+        conformal,
+        output,
+        lowWeightCorrection_
+    );
+
+    normaliseWeights
+    (
+        tgtMagSf_,
+        "target",
+        tgtAddress_,
+        tgtWeights_,
+        tgtWeightsSum_,
+        conformal,
+        output,
+        lowWeightCorrection_
+    );
+}
+
+
 template<class SourcePatch, class TargetPatch>
 template<class Type, class CombineOp>
 void Foam::AMIInterpolation<SourcePatch, TargetPatch>::interpolateToTarget
diff --git a/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolation.H b/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolation.H
index 27d077f1266..67205b69a78 100644
--- a/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolation.H
+++ b/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolation.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2014 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2015 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -418,6 +418,16 @@ public:
                 const TargetPatch& tgtPatch
             );
 
+            //- Append additional addressing and weights
+            void append
+            (
+                const SourcePatch& srcPatch,
+                const TargetPatch& tgtPatch
+            );
+
+            //- Normalise the weights
+            void normaliseWeights(const bool conformal, const bool output);
+
 
         // Evaluation
 
diff --git a/src/meshTools/AMIInterpolation/patches/cyclicAMI/cyclicAMIPointPatch/cyclicAMIPointPatch.C b/src/meshTools/AMIInterpolation/patches/cyclicAMI/cyclicAMIPointPatch/cyclicAMIPointPatch.C
index 2b4e6b8ad3b..98fe75a0b7c 100644
--- a/src/meshTools/AMIInterpolation/patches/cyclicAMI/cyclicAMIPointPatch/cyclicAMIPointPatch.C
+++ b/src/meshTools/AMIInterpolation/patches/cyclicAMI/cyclicAMIPointPatch/cyclicAMIPointPatch.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2013 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2015 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -38,6 +38,13 @@ namespace Foam
         cyclicAMIPointPatch,
         polyPatch
     );
+    addNamedToRunTimeSelectionTable
+    (
+        facePointPatch,
+        cyclicAMIPointPatch,
+        polyPatch,
+        cyclicPeriodicAMI
+    );
 }
 
 
diff --git a/src/meshTools/AMIInterpolation/patches/cyclicPeriodicAMI/cyclicPeriodicAMIPolyPatch/cyclicPeriodicAMIPolyPatch.C b/src/meshTools/AMIInterpolation/patches/cyclicPeriodicAMI/cyclicPeriodicAMIPolyPatch/cyclicPeriodicAMIPolyPatch.C
new file mode 100644
index 00000000000..751cca2f7de
--- /dev/null
+++ b/src/meshTools/AMIInterpolation/patches/cyclicPeriodicAMI/cyclicPeriodicAMIPolyPatch/cyclicPeriodicAMIPolyPatch.C
@@ -0,0 +1,391 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2015 OpenCFD Ltd.
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+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 "cyclicPeriodicAMIPolyPatch.H"
+#include "addToRunTimeSelectionTable.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+    defineTypeNameAndDebug(cyclicPeriodicAMIPolyPatch, 0);
+
+    addToRunTimeSelectionTable(polyPatch, cyclicPeriodicAMIPolyPatch, word);
+    addToRunTimeSelectionTable
+    (
+        polyPatch,
+        cyclicPeriodicAMIPolyPatch,
+        dictionary
+    );
+}
+
+
+// * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * * //
+
+void Foam::cyclicPeriodicAMIPolyPatch::resetAMI
+(
+    const AMIPatchToPatchInterpolation::interpolationMethod& AMIMethod
+) const
+{
+    if (owner())
+    {
+        // Get the periodic patch
+        const coupledPolyPatch& periodicPatch
+        (
+            refCast<const coupledPolyPatch>
+            (
+                boundaryMesh()[periodicPatchID()]
+            )
+        );
+
+        // Create copies of both patches' points, transformed to the owner
+        pointField thisPoints0(localPoints());
+        pointField nbrPoints0(neighbPatch().localPoints());
+        transformPosition(nbrPoints0);
+
+        // Reset the stored number of periodic transformations to a lower
+        // absolute value if possible
+        if (nSectors_ > 0)
+        {
+            if (nTransforms_ > nSectors_/2)
+            {
+                nTransforms_ -= nSectors_;
+            }
+            else if (nTransforms_ < - nSectors_/2)
+            {
+                nTransforms_ += nSectors_;
+            }
+        }
+
+        // Apply the stored number of periodic transforms
+        for (label i = 0; i < nTransforms_; ++ i)
+        {
+            periodicPatch.transformPosition(thisPoints0);
+        }
+        for (label i = 0; i > nTransforms_; -- i)
+        {
+            periodicPatch.transformPosition(nbrPoints0);
+        }
+
+        // Create another copy
+        pointField thisPoints(thisPoints0);
+        pointField nbrPoints(nbrPoints0);
+
+        // Create patches for all the points
+        primitivePatch thisPatch0
+        (
+            SubList<face>(localFaces(), size()),
+            thisPoints0
+        );
+        primitivePatch thisPatch
+        (
+            SubList<face>(localFaces(), size()),
+            thisPoints
+        );
+        primitivePatch nbrPatch0
+        (
+            SubList<face>(neighbPatch().localFaces(), neighbPatch().size()),
+            nbrPoints0
+        );
+        primitivePatch nbrPatch
+        (
+            SubList<face>(neighbPatch().localFaces(), neighbPatch().size()),
+            nbrPoints
+        );
+
+        // Construct a new AMI interpolation between the initial patch locations
+        AMIPtr_.reset
+        (
+            new AMIPatchToPatchInterpolation
+            (
+                thisPatch0,
+                nbrPatch0,
+                surfPtr(),
+                faceAreaIntersect::tmMesh,
+                false,
+                AMIPatchToPatchInterpolation::imPartialFaceAreaWeight,
+                AMILowWeightCorrection_,
+                AMIReverse_
+            )
+        );
+
+        // Number of geometry replications
+        label iter(0);
+        label nTransformsOld(nTransforms_);
+
+        // Weight sum averages
+        scalar srcSum(gAverage(AMIPtr_->srcWeightsSum()));
+        scalar tgtSum(gAverage(AMIPtr_->tgtWeightsSum()));
+
+        // Direction of geometry replication
+        bool direction = nTransforms_ >= 0;
+
+        // Increase in the source weight sum for the last iteration in the
+        // opposite direction. If the current increase is less than this, the
+        // direction is reversed.
+        scalar srcSumDiff = 0;
+
+        // Loop, replicating the geometry
+        while
+        (
+            (iter < maxIter_)
+         && (
+                (1 - srcSum > matchTolerance())
+             || (1 - tgtSum > matchTolerance())
+            )
+        )
+        {
+            if (direction)
+            {
+                periodicPatch.transformPosition(thisPoints);
+
+                thisPatch.movePoints(thisPoints);
+
+                AMIPtr_->append(thisPatch, nbrPatch0);
+            }
+            else
+            {
+                periodicPatch.transformPosition(nbrPoints);
+
+                nbrPatch.movePoints(nbrPoints);
+
+                AMIPtr_->append(thisPatch0, nbrPatch);
+            }
+
+            const scalar srcSumNew = gAverage(AMIPtr_->srcWeightsSum());
+            const scalar srcSumDiffNew = srcSumNew - srcSum;
+
+            if (srcSumDiffNew < srcSumDiff || srcSumDiffNew < SMALL)
+            {
+                direction = !direction;
+
+                srcSumDiff = srcSumDiffNew;
+            }
+
+            srcSum = srcSumNew;
+            tgtSum = gAverage(AMIPtr_->tgtWeightsSum());
+
+            nTransforms_ += direction ? +1 : -1;
+
+            ++ iter;
+        }
+
+        // Average the number of transformstions
+        nTransforms_ = (nTransforms_ + nTransformsOld)/2;
+
+        // Check that the match is complete
+        if (iter == maxIter_)
+        {
+            FatalErrorIn
+            (
+                "void Foam::cyclicPeriodicAMIPolyPatch::resetPeriodicAMI"
+                "("
+                    "const AMIPatchToPatchInterpolation::interpolationMethod&"
+                ") const"
+            )
+                << "Patches " << name() << " and " << neighbPatch().name()
+                << " do not couple to within a tolerance of "
+                << matchTolerance()
+                << " when transformed according to the periodic patch "
+                << periodicPatch.name() << "." << exit(FatalError);
+        }
+
+        // Check that at least one patch has a weight sum of one
+        if
+        (
+            mag(1 - srcSum) > matchTolerance()
+         && mag(1 - tgtSum) > matchTolerance()
+        )
+        {
+            FatalErrorIn
+            (
+                "void Foam::cyclicPeriodicAMIPolyPatch::resetPeriodicAMI"
+                "("
+                    "const AMIPatchToPatchInterpolation::interpolationMethod&"
+                ") const"
+            )
+                << "Patches " << name() << " and " << neighbPatch().name()
+                << " do not overlap an integer number of times when transformed"
+                << " according to the periodic patch "
+                << periodicPatch.name() << "." << exit(FatalError);
+        }
+
+        // Normalise the weights
+        AMIPtr_->normaliseWeights(true, false);
+    }
+}
+
+
+// * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * * * //
+
+Foam::cyclicPeriodicAMIPolyPatch::cyclicPeriodicAMIPolyPatch
+(
+    const word& name,
+    const label size,
+    const label start,
+    const label index,
+    const polyBoundaryMesh& bm,
+    const word& patchType,
+    const transformType transform
+)
+:
+    cyclicAMIPolyPatch(name, size, start, index, bm, patchType, transform),
+    periodicPatchName_(word::null),
+    periodicPatchID_(-1),
+    nTransforms_(0),
+    nSectors_(-1),
+    maxIter_(36)
+{}
+
+
+Foam::cyclicPeriodicAMIPolyPatch::cyclicPeriodicAMIPolyPatch
+(
+    const word& name,
+    const dictionary& dict,
+    const label index,
+    const polyBoundaryMesh& bm,
+    const word& patchType
+)
+:
+    cyclicAMIPolyPatch(name, dict, index, bm, patchType),
+    periodicPatchName_(dict.lookup("periodicPatch")),
+    periodicPatchID_(-1),
+    nTransforms_(dict.lookupOrDefault<label>("nTransforms", 0)),
+    nSectors_(dict.lookupOrDefault<label>("nSectors", 0)),
+    maxIter_(dict.lookupOrDefault<label>("maxIter", 36))
+{}
+
+
+Foam::cyclicPeriodicAMIPolyPatch::cyclicPeriodicAMIPolyPatch
+(
+    const cyclicPeriodicAMIPolyPatch& pp,
+    const polyBoundaryMesh& bm
+)
+:
+    cyclicAMIPolyPatch(pp, bm),
+    periodicPatchName_(pp.periodicPatchName_),
+    periodicPatchID_(-1),
+    nTransforms_(pp.nTransforms_),
+    nSectors_(pp.nSectors_),
+    maxIter_(pp.maxIter_)
+{}
+
+
+Foam::cyclicPeriodicAMIPolyPatch::cyclicPeriodicAMIPolyPatch
+(
+    const cyclicPeriodicAMIPolyPatch& pp,
+    const polyBoundaryMesh& bm,
+    const label index,
+    const label newSize,
+    const label newStart,
+    const word& nbrPatchName
+)
+:
+    cyclicAMIPolyPatch(pp, bm, index, newSize, newStart, nbrPatchName),
+    periodicPatchName_(pp.periodicPatchName_),
+    periodicPatchID_(-1),
+    nTransforms_(pp.nTransforms_),
+    nSectors_(pp.nSectors_),
+    maxIter_(pp.maxIter_)
+{}
+
+
+Foam::cyclicPeriodicAMIPolyPatch::cyclicPeriodicAMIPolyPatch
+(
+    const cyclicPeriodicAMIPolyPatch& pp,
+    const polyBoundaryMesh& bm,
+    const label index,
+    const labelUList& mapAddressing,
+    const label newStart
+)
+:
+    cyclicAMIPolyPatch(pp, bm, index, mapAddressing, newStart),
+    periodicPatchName_(pp.periodicPatchName_),
+    periodicPatchID_(-1),
+    nTransforms_(pp.nTransforms_),
+    nSectors_(pp.nSectors_),
+    maxIter_(pp.maxIter_)
+{}
+
+
+// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
+
+Foam::cyclicPeriodicAMIPolyPatch::~cyclicPeriodicAMIPolyPatch()
+{}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+Foam::label Foam::cyclicPeriodicAMIPolyPatch::periodicPatchID() const
+{
+    if (periodicPatchName_ == word::null)
+    {
+        periodicPatchID_ = -1;
+
+        return periodicPatchID_;
+    }
+
+    if (periodicPatchID_ == -1)
+    {
+        periodicPatchID_ = this->boundaryMesh().findPatchID(periodicPatchName_);
+
+        if (periodicPatchID_ == -1)
+        {
+            FatalErrorIn("cyclicPolyAMIPatch::periodicPatchID() const")
+                << "Illegal periodicPatch name " << periodicPatchName_
+                << nl << "Valid patch names are "
+                << this->boundaryMesh().names()
+                << exit(FatalError);
+        }
+
+        // Check that it is a coupled patch
+        refCast<const coupledPolyPatch>
+        (
+            this->boundaryMesh()[periodicPatchID_]
+        );
+    }
+
+    return periodicPatchID_;
+}
+
+
+void Foam::cyclicPeriodicAMIPolyPatch::write(Ostream& os) const
+{
+    cyclicAMIPolyPatch::write(os);
+
+    os.writeKeyword("periodicPatch") << periodicPatchName_
+        << token::END_STATEMENT << nl;
+
+    os.writeKeyword("nTransforms") << nTransforms_ <<
+        token::END_STATEMENT << nl;
+
+    os.writeKeyword("nSectors") << nSectors_ <<
+        token::END_STATEMENT << nl;
+
+    os.writeKeyword("maxIter") << maxIter_ << token::END_STATEMENT << nl;
+}
+
+
+// ************************************************************************* //
diff --git a/src/meshTools/AMIInterpolation/patches/cyclicPeriodicAMI/cyclicPeriodicAMIPolyPatch/cyclicPeriodicAMIPolyPatch.H b/src/meshTools/AMIInterpolation/patches/cyclicPeriodicAMI/cyclicPeriodicAMIPolyPatch/cyclicPeriodicAMIPolyPatch.H
new file mode 100644
index 00000000000..715cc5429d6
--- /dev/null
+++ b/src/meshTools/AMIInterpolation/patches/cyclicPeriodicAMI/cyclicPeriodicAMIPolyPatch/cyclicPeriodicAMIPolyPatch.H
@@ -0,0 +1,225 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2015 OpenCFD Ltd.
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+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::cyclicPeriodicAMIPolyPatch
+
+Description
+    Cyclic patch for periodic Arbitrary Mesh Interface (AMI)
+
+SourceFiles
+    cyclicPeriodicAMIPolyPatch.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef cyclicPeriodicAMIPolyPatch_H
+#define cyclicPeriodicAMIPolyPatch_H
+
+#include "cyclicAMIPolyPatch.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+/*---------------------------------------------------------------------------*\
+                    Class cyclicPeriodicAMIPolyPatch Declaration
+\*---------------------------------------------------------------------------*/
+
+class cyclicPeriodicAMIPolyPatch
+:
+    public cyclicAMIPolyPatch
+{
+private:
+
+    // Private data
+
+        //- Periodic patch name
+        mutable word periodicPatchName_;
+
+        //- Periodic patch ID
+        mutable label periodicPatchID_;
+
+        //- Current number of transformations (+ve forward, -ve backward)
+        mutable label nTransforms_;
+
+        //- Number of sectors in a rotationally periodic geometry (optional)
+        const label nSectors_;
+
+        //- Maximum number of attempts to match the AMI geometry
+        const label maxIter_;
+
+
+    // Private Member Functions
+
+        //- Reset the AMI interpolator
+        virtual void resetAMI
+        (
+            const AMIPatchToPatchInterpolation::interpolationMethod& AMIMethod =
+                AMIPatchToPatchInterpolation::imFaceAreaWeight
+        ) const;
+
+
+public:
+
+    //- Runtime type information
+    TypeName("cyclicPeriodicAMI");
+
+
+    // Constructors
+
+        //- Construct from (base couped patch) components
+        cyclicPeriodicAMIPolyPatch
+        (
+            const word& name,
+            const label size,
+            const label start,
+            const label index,
+            const polyBoundaryMesh& bm,
+            const word& patchType,
+            const transformType transform = UNKNOWN
+        );
+
+        //- Construct from dictionary
+        cyclicPeriodicAMIPolyPatch
+        (
+            const word& name,
+            const dictionary& dict,
+            const label index,
+            const polyBoundaryMesh& bm,
+            const word& patchType
+        );
+
+        //- Construct as copy, resetting the boundary mesh
+        cyclicPeriodicAMIPolyPatch
+        (
+            const cyclicPeriodicAMIPolyPatch&,
+            const polyBoundaryMesh&
+        );
+
+        //- Construct given the original patch and resetting the
+        //  face list and boundary mesh information
+        cyclicPeriodicAMIPolyPatch
+        (
+            const cyclicPeriodicAMIPolyPatch& pp,
+            const polyBoundaryMesh& bm,
+            const label index,
+            const label newSize,
+            const label newStart,
+            const word& nbrPatchName
+        );
+
+        //- Construct given the original patch and a map
+        cyclicPeriodicAMIPolyPatch
+        (
+            const cyclicPeriodicAMIPolyPatch& pp,
+            const polyBoundaryMesh& bm,
+            const label index,
+            const labelUList& mapAddressing,
+            const label newStart
+        );
+
+
+        //- Construct and return a clone, resetting the boundary mesh
+        virtual autoPtr<polyPatch> clone(const polyBoundaryMesh& bm) const
+        {
+            return autoPtr<polyPatch>
+            (
+                new cyclicPeriodicAMIPolyPatch(*this, bm)
+            );
+        }
+
+        //- Construct and return a clone, resetting the face list
+        //  and boundary mesh
+        virtual autoPtr<polyPatch> clone
+        (
+            const polyBoundaryMesh& bm,
+            const label index,
+            const label newSize,
+            const label newStart
+        ) const
+        {
+            return autoPtr<polyPatch>
+            (
+                new cyclicPeriodicAMIPolyPatch
+                (
+                    *this,
+                    bm,
+                    index,
+                    newSize,
+                    newStart,
+                    nbrPatchName_
+                )
+            );
+        }
+
+        //- Construct and return a clone, resetting the face list
+        //  and boundary mesh
+        virtual autoPtr<polyPatch> clone
+        (
+            const polyBoundaryMesh& bm,
+            const label index,
+            const labelUList& mapAddressing,
+            const label newStart
+        ) const
+        {
+            return autoPtr<polyPatch>
+            (
+                new cyclicPeriodicAMIPolyPatch
+                (
+                    *this,
+                    bm,
+                    index,
+                    mapAddressing,
+                    newStart
+                )
+            );
+        }
+
+
+    //- Destructor
+    virtual ~cyclicPeriodicAMIPolyPatch();
+
+
+    // Member Functions
+
+        //- Periodic patch ID
+        virtual label periodicPatchID() const;
+
+        //- Write the polyPatch data as a dictionary
+        virtual void write(Ostream&) const;
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/meshTools/Make/files b/src/meshTools/Make/files
index 0c1b794f7c6..fc02ae4407e 100644
--- a/src/meshTools/Make/files
+++ b/src/meshTools/Make/files
@@ -196,6 +196,9 @@ $(ACMICycPatches)/cyclicACMIPolyPatch/cyclicACMIPolyPatch.C
 $(ACMICycPatches)/cyclicACMIPointPatch/cyclicACMIPointPatch.C
 $(ACMICycPatches)/cyclicACMIPointPatchField/cyclicACMIPointPatchFields.C
 
+PeriodicAMICycPatches=$(AMI)/patches/cyclicPeriodicAMI
+$(PeriodicAMICycPatches)/cyclicPeriodicAMIPolyPatch/cyclicPeriodicAMIPolyPatch.C
+
 mappedPatches/mappedPolyPatch/mappedPatchBase.C
 mappedPatches/mappedPolyPatch/mappedPolyPatch.C
 mappedPatches/mappedPolyPatch/mappedWallPolyPatch.C
diff --git a/tutorials/incompressible/pimpleDyMFoam/oscillatingInletPeriodicAMI2D/0/U b/tutorials/incompressible/pimpleDyMFoam/oscillatingInletPeriodicAMI2D/0/U
new file mode 100644
index 00000000000..6c3146afd10
--- /dev/null
+++ b/tutorials/incompressible/pimpleDyMFoam/oscillatingInletPeriodicAMI2D/0/U
@@ -0,0 +1,44 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  dev                                   |
+|   \\  /    A nd           | Web:      www.OpenFOAM.org                      |
+|    \\/     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
+{
+    #include "${WM_PROJECT_DIR}/etc/caseDicts/setConstraintTypes"
+
+    inlet
+    {
+        type            fixedValue;
+        value           uniform (1 0 0);
+    }
+    outlet
+    {
+        type            pressureInletOutletVelocity;
+        value           $internalField;
+    }
+    walls
+    {
+        type            movingWallVelocity;
+        value           uniform (0 0 0);
+    }
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/incompressible/pimpleDyMFoam/oscillatingInletPeriodicAMI2D/0/epsilon b/tutorials/incompressible/pimpleDyMFoam/oscillatingInletPeriodicAMI2D/0/epsilon
new file mode 100644
index 00000000000..75a386fbab0
--- /dev/null
+++ b/tutorials/incompressible/pimpleDyMFoam/oscillatingInletPeriodicAMI2D/0/epsilon
@@ -0,0 +1,45 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  dev                                   |
+|   \\  /    A nd           | Web:      www.OpenFOAM.org                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       volScalarField;
+    location    "0";
+    object      epsilon;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+dimensions      [0 2 -3 0 0 0 0];
+
+internalField   uniform 1.8e-3;
+
+boundaryField
+{
+    #include "${WM_PROJECT_DIR}/etc/caseDicts/setConstraintTypes"
+
+    inlet
+    {
+        type            fixedValue;
+        value           $internalField;
+    }
+    outlet
+    {
+        type            inletOutlet;
+        inletValue      $internalField;
+        value           $internalField;
+    }
+    walls
+    {
+        type            epsilonWallFunction;
+        value           $internalField;
+    }
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/incompressible/pimpleDyMFoam/oscillatingInletPeriodicAMI2D/0/k b/tutorials/incompressible/pimpleDyMFoam/oscillatingInletPeriodicAMI2D/0/k
new file mode 100644
index 00000000000..ab18cfd794d
--- /dev/null
+++ b/tutorials/incompressible/pimpleDyMFoam/oscillatingInletPeriodicAMI2D/0/k
@@ -0,0 +1,45 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  dev                                   |
+|   \\  /    A nd           | Web:      www.OpenFOAM.org                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       volScalarField;
+    location    "0";
+    object      k;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+dimensions      [0 2 -2 0 0 0 0];
+
+internalField   uniform 3.75e-3;
+
+boundaryField
+{
+    #include "${WM_PROJECT_DIR}/etc/caseDicts/setConstraintTypes"
+
+    inlet
+    {
+        type            fixedValue;
+        value           $internalField;
+    }
+    outlet
+    {
+        type            inletOutlet;
+        inletValue      $internalField;
+        value           $internalField;
+    }
+    walls
+    {
+        type            kqRWallFunction;
+        value           $internalField;
+    }
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/incompressible/pimpleDyMFoam/oscillatingInletPeriodicAMI2D/0/nut b/tutorials/incompressible/pimpleDyMFoam/oscillatingInletPeriodicAMI2D/0/nut
new file mode 100644
index 00000000000..09c51bfa1cb
--- /dev/null
+++ b/tutorials/incompressible/pimpleDyMFoam/oscillatingInletPeriodicAMI2D/0/nut
@@ -0,0 +1,45 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  dev                                   |
+|   \\  /    A nd           | Web:      www.OpenFOAM.org                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       volScalarField;
+    location    "0";
+    object      nut;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+dimensions      [0 2 -1 0 0 0 0];
+
+internalField   uniform 0;
+
+boundaryField
+{
+    #include "${WM_PROJECT_DIR}/etc/caseDicts/setConstraintTypes"
+
+    inlet
+    {
+        type            fixedValue;
+        value           $internalField;
+    }
+    outlet
+    {
+        type            inletOutlet;
+        inletValue      $internalField;
+        value           $internalField;
+    }
+    walls
+    {
+        type            nutkWallFunction;
+        value           $internalField;
+    }
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/incompressible/pimpleDyMFoam/oscillatingInletPeriodicAMI2D/0/p b/tutorials/incompressible/pimpleDyMFoam/oscillatingInletPeriodicAMI2D/0/p
new file mode 100644
index 00000000000..ca001397147
--- /dev/null
+++ b/tutorials/incompressible/pimpleDyMFoam/oscillatingInletPeriodicAMI2D/0/p
@@ -0,0 +1,42 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  dev                                   |
+|   \\  /    A nd           | Web:      www.OpenFOAM.org                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       volScalarField;
+    location    "0";
+    object      p;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+dimensions      [0 2 -2 0 0 0 0];
+
+internalField   uniform 0;
+
+boundaryField
+{
+    #include "${WM_PROJECT_DIR}/etc/caseDicts/setConstraintTypes"
+
+    inlet
+    {
+        type            zeroGradient;
+    }
+    outlet
+    {
+        type            fixedValue;
+        value           uniform 0;
+    }
+    walls
+    {
+        type            zeroGradient;
+    }
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/incompressible/pimpleDyMFoam/oscillatingInletPeriodicAMI2D/constant/dynamicMeshDict b/tutorials/incompressible/pimpleDyMFoam/oscillatingInletPeriodicAMI2D/constant/dynamicMeshDict
new file mode 100644
index 00000000000..ae204c40bcb
--- /dev/null
+++ b/tutorials/incompressible/pimpleDyMFoam/oscillatingInletPeriodicAMI2D/constant/dynamicMeshDict
@@ -0,0 +1,36 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  dev                                   |
+|   \\  /    A nd           | Web:      www.OpenFOAM.org                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "constant";
+    object      dynamicMeshDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+dynamicFvMesh   solidBodyMotionFvMesh;
+
+motionSolverLibs ( "libfvMotionSolvers.so" );
+
+solidBodyMotionFvMeshCoeffs
+{
+    cellZone        inletChannel;
+
+    solidBodyMotionFunction  oscillatingLinearMotion;
+
+    oscillatingLinearMotionCoeffs
+    {
+        amplitude       (0 0.5 0);
+        omega           3.14; // rad/s  (.5 rps)
+    }
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/incompressible/pimpleDyMFoam/oscillatingInletPeriodicAMI2D/constant/polyMesh/blockMeshDict b/tutorials/incompressible/pimpleDyMFoam/oscillatingInletPeriodicAMI2D/constant/polyMesh/blockMeshDict
new file mode 100644
index 00000000000..0e58afae912
--- /dev/null
+++ b/tutorials/incompressible/pimpleDyMFoam/oscillatingInletPeriodicAMI2D/constant/polyMesh/blockMeshDict
@@ -0,0 +1,158 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  dev                                   |
+|   \\  /    A nd           | Web:      www.OpenFOAM.org                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      blockMeshDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+convertToMeters 1;
+
+vertices
+(
+    (0   0.3 0  )
+    (0   0.7 0  )
+    (0   0.7 0.1)
+    (0   0.3 0.1)
+
+    (0.8 0.3 0  )
+    (0.8 0.7 0  )
+    (0.8 0.7 0.1)
+    (0.8 0.3 0.1)
+
+    (1   0.3 0  )
+    (1   0.7 0  )
+    (1   0.7 0.1)
+    (1   0.3 0.1)
+
+    (1   0   0  )
+    (1   1   0  )
+    (1   1   0.1)
+    (1   0   0.1)
+
+    (1.2 0   0  )
+    (1.2 1   0  )
+    (1.2 1   0.1)
+    (1.2 0   0.1)
+
+    (3   0   0  )
+    (3   1   0  )
+    (3   1   0.1)
+    (3   0   0.1)
+);
+
+blocks
+(
+    hex (0 1 2 3 4 5 6 7) inletChannel (40 1 64) simpleGrading (1 1 1)
+    hex (4 5 6 7 8 9 10 11 12) inletChannel (40 1 16) simpleGrading (1 1 1)
+
+    hex (12 13 14 15 16 17 18 19) (96 1  8) simpleGrading (1 1 1)
+    hex (16 17 18 19 20 21 22 23) (96 1 72) simpleGrading (1 1 1)
+);
+
+edges
+(
+);
+
+boundary
+(
+    inlet
+    {
+        type patch;
+        faces
+        (
+            (0 1 2 3)
+        );
+    }
+    outlet
+    {
+        type patch;
+        faces
+        (
+            (20 21 22 23)
+        );
+    }
+    walls
+    {
+        type wall;
+        faces
+        (
+            (0 3 7 4)
+            (16 19 23 20)
+            (1 2 6 5)
+            (17 18 22 21)
+        );
+    }
+    cyclicMoving1
+    {
+        type cyclic;
+        neighbourPatch cyclicMoving2;
+        faces
+        (
+            (4 7 11 8)
+        );
+    }
+    cyclicMoving2
+    {
+        type cyclic;
+        neighbourPatch cyclicMoving1;
+        faces
+        (
+            (5 6 10 9)
+        );
+    }
+    cyclicStationary1
+    {
+        type cyclic;
+        neighbourPatch cyclicStationary2;
+        faces
+        (
+            (12 15 19 16)
+        );
+    }
+    cyclicStationary2
+    {
+        type cyclic;
+        neighbourPatch cyclicStationary1;
+        faces
+        (
+            (13 14 18 17)
+        );
+    }
+    ami1
+    {
+        type cyclicPeriodicAMI;
+        inGroups 1(cyclicAMI);
+        neighbourPatch ami2;
+        periodicPatch cyclicMoving1;
+        faces
+        (
+            (8 9 10 11)
+        );
+    }
+    ami2
+    {
+        type cyclicPeriodicAMI;
+        inGroups 1(cyclicAMI);
+        neighbourPatch ami1;
+        periodicPatch cyclicMoving1;
+        faces
+        (
+            (12 13 14 15)
+        );
+    }
+);
+
+mergePatchPairs
+(
+);
+
+// ************************************************************************* //
diff --git a/tutorials/incompressible/pimpleDyMFoam/oscillatingInletPeriodicAMI2D/constant/transportProperties b/tutorials/incompressible/pimpleDyMFoam/oscillatingInletPeriodicAMI2D/constant/transportProperties
new file mode 100644
index 00000000000..5f2e87ebefb
--- /dev/null
+++ b/tutorials/incompressible/pimpleDyMFoam/oscillatingInletPeriodicAMI2D/constant/transportProperties
@@ -0,0 +1,22 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  dev                                   |
+|   \\  /    A nd           | Web:      www.OpenFOAM.org                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "constant";
+    object      transportProperties;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+transportModel  Newtonian;
+
+nu              nu [ 0 2 -1 0 0 0 0 ] 1e-6;
+
+// ************************************************************************* //
diff --git a/tutorials/incompressible/pimpleDyMFoam/oscillatingInletPeriodicAMI2D/constant/turbulenceProperties b/tutorials/incompressible/pimpleDyMFoam/oscillatingInletPeriodicAMI2D/constant/turbulenceProperties
new file mode 100644
index 00000000000..cd2daf8229b
--- /dev/null
+++ b/tutorials/incompressible/pimpleDyMFoam/oscillatingInletPeriodicAMI2D/constant/turbulenceProperties
@@ -0,0 +1,30 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  dev                                   |
+|   \\  /    A nd           | Web:      www.OpenFOAM.org                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "constant";
+    object      turbulenceProperties;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+simulationType  RAS;
+
+RAS
+{
+    RASModel        kEpsilon;
+
+    turbulence      on;
+
+    printCoeffs     on;
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/incompressible/pimpleDyMFoam/oscillatingInletPeriodicAMI2D/system/controlDict b/tutorials/incompressible/pimpleDyMFoam/oscillatingInletPeriodicAMI2D/system/controlDict
new file mode 100644
index 00000000000..3521d07583e
--- /dev/null
+++ b/tutorials/incompressible/pimpleDyMFoam/oscillatingInletPeriodicAMI2D/system/controlDict
@@ -0,0 +1,53 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  dev                                   |
+|   \\  /    A nd           | Web:      www.OpenFOAM.org                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "system";
+    object      controlDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+application     pimpleDyMFoam;
+
+startFrom       latestTime;
+
+startTime       0;
+
+stopAt          endTime;
+
+endTime         5;
+
+deltaT          0.005;
+
+writeControl    adjustableRunTime;
+
+writeInterval   0.05;
+
+purgeWrite      0;
+
+writeFormat     ascii;
+
+writePrecision  6;
+
+writeCompression off;
+
+timeFormat      general;
+
+timePrecision   6;
+
+runTimeModifiable true;
+
+adjustTimeStep  true;
+
+maxCo           0.5;
+
+
+// ************************************************************************* //
diff --git a/tutorials/incompressible/pimpleDyMFoam/oscillatingInletPeriodicAMI2D/system/fvSchemes b/tutorials/incompressible/pimpleDyMFoam/oscillatingInletPeriodicAMI2D/system/fvSchemes
new file mode 100644
index 00000000000..f65b5bf3979
--- /dev/null
+++ b/tutorials/incompressible/pimpleDyMFoam/oscillatingInletPeriodicAMI2D/system/fvSchemes
@@ -0,0 +1,63 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  dev                                   |
+|   \\  /    A nd           | Web:      www.OpenFOAM.org                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "system";
+    object      fvSchemes;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+ddtSchemes
+{
+    default         Euler;
+}
+
+gradSchemes
+{
+    default         Gauss linear;
+    grad(p)         Gauss linear;
+    grad(U)         cellLimited Gauss linear 1;
+}
+
+divSchemes
+{
+    default         none;
+//    div(phi,U)      Gauss upwind;
+    div(phi,U)      Gauss linearUpwind grad(U);
+    div(phi,k)      Gauss upwind;
+    div(phi,epsilon) Gauss upwind;
+    div((nuEff*dev2(T(grad(U))))) Gauss linear;
+}
+
+laplacianSchemes
+{
+    default         Gauss linear limited corrected 0.33;
+}
+
+interpolationSchemes
+{
+    default         linear;
+}
+
+snGradSchemes
+{
+    default         limited corrected 0.33;
+}
+
+fluxRequired
+{
+    default         no;
+    pcorr           ;
+    p               ;
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/incompressible/pimpleDyMFoam/oscillatingInletPeriodicAMI2D/system/fvSolution b/tutorials/incompressible/pimpleDyMFoam/oscillatingInletPeriodicAMI2D/system/fvSolution
new file mode 100644
index 00000000000..61da6726255
--- /dev/null
+++ b/tutorials/incompressible/pimpleDyMFoam/oscillatingInletPeriodicAMI2D/system/fvSolution
@@ -0,0 +1,80 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  dev                                   |
+|   \\  /    A nd           | Web:      www.OpenFOAM.org                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      fvSolution;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+solvers
+{
+    pcorr
+    {
+        solver          GAMG;
+        tolerance       1e-2;
+        relTol          0;
+        smoother        GaussSeidel;
+        cacheAgglomeration no;
+        nCellsInCoarsestLevel 10;
+        agglomerator    faceAreaPair;
+        mergeLevels     1;
+        maxIter         50;
+    }
+
+    p
+    {
+        $pcorr;
+        tolerance       1e-5;
+        relTol          0.01;
+    }
+
+    pFinal
+    {
+        $p;
+        tolerance       1e-6;
+        relTol          0;
+    }
+
+    "(U|k|epsilon)"
+    {
+        solver          smoothSolver;
+        smoother        symGaussSeidel;
+        tolerance       1e-6;
+        relTol          0.1;
+    }
+
+    "(U|k|epsilon)Final"
+    {
+        $U;
+        tolerance       1e-6;
+        relTol          0;
+    }
+}
+
+PIMPLE
+{
+    correctPhi          no;
+    nOuterCorrectors    1;
+    nCorrectors         2;
+    nNonOrthogonalCorrectors 0;
+}
+
+relaxationFactors
+{
+//    "(U|k|epsilon).*"   1;
+}
+
+cache
+{
+    grad(U);
+}
+
+// ************************************************************************* //
-- 
GitLab