diff --git a/applications/utilities/mesh/manipulation/stitchMesh/stitchMesh.C b/applications/utilities/mesh/manipulation/stitchMesh/stitchMesh.C
index 4b524880cefeb0b465c24d23828ec683f1ef3aad..09bf6d9a9d1f3f8810ca70824fdde27a2105773b 100644
--- a/applications/utilities/mesh/manipulation/stitchMesh/stitchMesh.C
+++ b/applications/utilities/mesh/manipulation/stitchMesh/stitchMesh.C
@@ -66,34 +66,35 @@ Description
 #include "fvCFD.H"
 #include "polyTopoChanger.H"
 #include "mapPolyMesh.H"
-#include "ListOps.H"
 #include "slidingInterface.H"
 #include "perfectInterface.H"
 #include "IOobjectList.H"
 #include "ReadFields.H"
+#include <numeric>
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
-// Checks whether patch present
-void checkPatch(const polyBoundaryMesh& bMesh, const word& name)
+// Checks whether patch present and non-zero
+bool checkPatch(const polyBoundaryMesh& bMesh, const word& name)
 {
     const label patchi = bMesh.findPatchID(name);
 
     if (patchi == -1)
     {
-        FatalErrorInFunction
-            << "Cannot find patch " << name << endl
-            << "It should be present and of non-zero size" << endl
-            << "Valid patches are " << bMesh.names()
-            << exit(FatalError);
+        Info<< "No patch " << name << " in mesh" << nl
+            << "Known patches: " << bMesh.names() << endl;
+
+        return false;
     }
 
     if (bMesh[patchi].empty())
     {
-        FatalErrorInFunction
-            << "Patch " << name << " is present but zero size"
-            << exit(FatalError);
+        Info<< "Patch " << name << " has zero size" << nl;
+
+        return false;
     }
+
+    return true;
 }
 
 
@@ -101,28 +102,38 @@ int main(int argc, char *argv[])
 {
     argList::addNote
     (
-        "Merge the faces on the specified patches (if geometrically possible)\n"
-        "so the faces become internal.\n"
-        "Integral matching is used when the options -partial and -perfect are "
-        "omitted.\n"
+        "Merge the faces on specified patches (if geometrically possible)"
+        " so that the\n"
+        "faces become internal.\n"
+        "This utility can be called without arguments (uses stitchMeshDict)"
+        " or with\n"
+        "two arguments (master/slave patch names)."
     );
 
     argList::noParallel();
     #include "addOverwriteOption.H"
     #include "addRegionOption.H"
-
-    argList::validArgs.append("masterPatch");
-    argList::validArgs.append("slavePatch");
+    #include "addDictOption.H"
 
+    argList::addBoolOption
+    (
+        "integral",
+        "couple integral master/slave patches (2 argument mode: default)"
+    );
     argList::addBoolOption
     (
         "partial",
-        "couple partially overlapping patches (optional)"
+        "couple partially overlapping master/slave patches (2 argument mode)"
     );
     argList::addBoolOption
     (
         "perfect",
-        "couple perfectly aligned patches (optional)"
+        "couple perfectly aligned master/slave patches (2 argument mode)"
+    );
+    argList::addBoolOption
+    (
+        "intermediate",
+        "write intermediate stages, not just the final result"
     );
     argList::addOption
     (
@@ -131,202 +142,258 @@ int main(int argc, char *argv[])
         "dictionary file with tolerances"
     );
 
-    #include "setRootCase.H"
-    #include "createTime.H"
-    runTime.functionObjects().off();
-    #include "createNamedMesh.H"
-
-    const word oldInstance = mesh.pointsInstance();
+    // The arguments are non-mandatory when using dictionary mode
+    argList::validArgs.append("masterPatch");
+    argList::validArgs.append("slavePatch");
 
-    const word masterPatchName = args[1];
-    const word slavePatchName  = args[2];
+    #include "setRootCaseNonMandatoryArgs.H"
 
-    const bool partialCover = args.optionFound("partial");
-    const bool perfectCover = args.optionFound("perfect");
-    const bool overwrite    = args.optionFound("overwrite");
+    // We now handle checking args and general sanity etc.
+    const bool useCommandArgs = (args.size() > 1);
 
-    if (partialCover && perfectCover)
+    if (useCommandArgs)
     {
-        FatalErrorInFunction
-            << "Cannot supply both partial and perfect." << endl
-            << "Use perfect match option if the patches perfectly align"
-            << " (both vertex positions and face centres)" << endl
-            << exit(FatalError);
-    }
-
-
-    const word mergePatchName(masterPatchName + slavePatchName);
-    const word cutZoneName(mergePatchName + "CutFaceZone");
-
-    slidingInterface::typeOfMatch tom = slidingInterface::INTEGRAL;
+        if (args.optionFound("dict"))
+        {
+            FatalErrorInFunction
+                << "Cannot specify both dictionary and command-line arguments"
+                << nl
+                << endl;
+        }
 
-    if (partialCover)
-    {
-        Info<< "Coupling partially overlapping patches "
-            << masterPatchName << " and " << slavePatchName << nl
-            << "Resulting internal faces will be in faceZone " << cutZoneName
-            << nl
-            << "Any uncovered faces will remain in their patch"
-            << endl;
-
-        tom = slidingInterface::PARTIAL;
-    }
-    else if (perfectCover)
-    {
-        Info<< "Coupling perfectly aligned patches "
-            << masterPatchName << " and " << slavePatchName << nl
-            << "Resulting (internal) faces will be in faceZone " << cutZoneName
-            << nl << nl
-            << "Note: both patches need to align perfectly." << nl
-            << "Both the vertex"
-            << " positions and the face centres need to align to within" << nl
-            << "a tolerance given by the minimum edge length on the patch"
-            << endl;
+        // If we have arguments - we require all arguments!
+        if (!args.check(true, false))
+        {
+            FatalError.exit();
+        }
     }
     else
     {
-        Info<< "Coupling patches " << masterPatchName << " and "
-            << slavePatchName << nl
-            << "Resulting (internal) faces will be in faceZone " << cutZoneName
-            << nl << nl
-            << "Note: the overall area covered by both patches should be"
-            << " identical (\"integral\" interface)." << endl
-            << "If this is not the case use the -partial option" << nl << endl;
-    }
+        // Carp about inapplicable options
 
-    // set up the tolerances for the sliding mesh
-    dictionary slidingTolerances;
-    if (args.optionFound("toleranceDict"))
-    {
-        IOdictionary toleranceFile
-        (
-            IOobject
-            (
-                args["toleranceDict"],
-                runTime.constant(),
-                mesh,
-                IOobject::MUST_READ_IF_MODIFIED,
-                IOobject::NO_WRITE
-            )
-        );
-        slidingTolerances += toleranceFile;
+        if (args.optionFound("integral"))
+        {
+            FatalErrorInFunction
+                << "Only specify -integral with command-line arguments"
+                << endl;
+        }
+
+        if (args.optionFound("partial"))
+        {
+            FatalErrorInFunction
+                << "Only specify -partial with command-line arguments"
+                << endl;
+        }
+
+        if (args.optionFound("perfect"))
+        {
+            FatalErrorInFunction
+                << "Only specify -perfect with command-line arguments"
+                << endl;
+        }
     }
 
-    // Check for non-empty master and slave patches
-    checkPatch(mesh.boundaryMesh(), masterPatchName);
-    checkPatch(mesh.boundaryMesh(), slavePatchName);
+    #include "createTime.H"
+    runTime.functionObjects().off();
+    #include "createNamedMesh.H"
+
+    const word oldInstance = mesh.pointsInstance();
 
-    // Create and add face zones and mesh modifiers
+    const bool intermediate = args.optionFound("intermediate");
+    const bool overwrite = args.optionFound("overwrite");
 
-    // Master patch
-    const polyPatch& masterPatch = mesh.boundaryMesh()[masterPatchName];
+    const word dictName("stitchMeshDict");
 
-    // Make list of masterPatch faces
-    labelList isf(masterPatch.size());
+    // A validated input dictionary
+    dictionary validatedDict;
 
-    forAll(isf, i)
+    if (useCommandArgs)
     {
-        isf[i] = masterPatch.start() + i;
-    }
+        // Command argument driven:
+        const int integralCover = args.optionFound("integral");
+        const int partialCover  = args.optionFound("partial");
+        const int perfectCover  = args.optionFound("perfect");
 
-    polyTopoChanger stitcher(mesh, IOobject::NO_READ);
-    stitcher.clear();
-    stitcher.setSize(1);
+        if ((integralCover + partialCover + perfectCover) > 1)
+        {
+            FatalErrorInFunction
+                << "Can only specify one of -integral | -partial | -perfect."
+                << nl
+                << "Use perfect match option if the patches perfectly align"
+                << " (both vertex positions and face centres)" << endl
+                << exit(FatalError);
+        }
 
-    mesh.pointZones().clearAddressing();
-    mesh.faceZones().clearAddressing();
-    mesh.cellZones().clearAddressing();
+        // Patch names
+        const word masterPatchName(args[1]);
+        const word slavePatchName(args[2]);
 
-    if (perfectCover)
-    {
-        // Starts as master zone, but receives the resulting internal faces
-        mesh.faceZones()
-        (
-            cutZoneName,
-            true // verbose
-        ).resetAddressing(isf.xfer(), false);
+        // Patch names
+        Info<< "    " <<  masterPatchName
+            << " / " << slavePatchName << nl;
 
-        // Add the perfect interface mesh modifier
-        stitcher.set
+        // Bail out if either patch has problems
+        if
         (
-            0,
-            new perfectInterface
+            !checkPatch(mesh.boundaryMesh(), masterPatchName)
+         || !checkPatch(mesh.boundaryMesh(), slavePatchName)
+        )
+        {
+            FatalErrorInFunction
+                << "Cannot continue"
+                << exit(FatalError);
+
+            return 1;
+        }
+
+        // Input was validated
+        dictionary dict;
+
+        if (perfectCover)
+        {
+            dict.add("match", word("perfect"));
+        }
+        else if (partialCover)
+        {
+            dict.add
             (
-                "couple",
-                0,
-                stitcher,
-                cutZoneName,
-                masterPatchName,
-                slavePatchName
-            )
-        );
+                "match",
+                slidingInterface::typeOfMatchNames[slidingInterface::PARTIAL]
+            );
+        }
+        else
+        {
+            dict.add
+            (
+                "match",
+                slidingInterface::typeOfMatchNames[slidingInterface::INTEGRAL]
+            );
+        }
+
+        // Patch names
+        dict.add("master", masterPatchName);
+        dict.add("slave", slavePatchName);
+
+        validatedDict.add("stitchMesh", dict);
     }
     else
     {
-        // An empty point zone
-        mesh.pointZones()
-        (
-            mergePatchName + "CutPointZone",
-            true // verbose
-        ) = labelList();
+        // dictionary-driven:
 
-        // The master zone
-        mesh.faceZones()
-        (
-            mergePatchName + "MasterZone",
-            true // verbose
-        ).resetAddressing(isf.xfer(), false);
+        #include "setSystemRunTimeDictionaryIO.H"
 
-        // Slave patch
-        const polyPatch& slavePatch = mesh.boundaryMesh()[slavePatchName];
+        Info<< "Reading " << dictName;
+
+        IOdictionary stitchDict(dictIO);
+
+        Info<< " with " << stitchDict.size() << " entries" << nl;
 
-        labelList osf(slavePatch.size());
+        // Suppress duplicate names
+        wordHashSet requestedPatches;
 
-        forAll(osf, i)
+        forAllConstIters(stitchDict, iter)
         {
-            osf[i] = slavePatch.start() + i;
+            if (!iter().isDict())
+            {
+                Info<< "Ignoring non-dictionary entry: "
+                    << iter().keyword() << nl;
+                continue;
+            }
+
+            const dictionary& dict = iter().dict();
+
+            // Match type
+            word matchName;
+            if (dict.readIfPresent("match", matchName))
+            {
+                if
+                (
+                    matchName != "perfect"
+                 && !slidingInterface::typeOfMatchNames.hasEnum(matchName)
+                )
+                {
+                    Info<< "Error: unknown match type - " << matchName
+                        << " should be one of "
+                        << slidingInterface::typeOfMatchNames.toc() << nl;
+                    continue;
+                }
+            }
+
+            // Patch names
+            const word masterPatchName(dict["master"]);
+            const word slavePatchName(dict["slave"]);
+
+            // Patch names
+            Info<< "    " <<  masterPatchName
+                << " / " << slavePatchName << nl;
+
+            if (!requestedPatches.insert(masterPatchName))
+            {
+                Info<< "Error: patch specified multiple times - "
+                    << masterPatchName << nl;
+                continue;
+            }
+
+            if (!requestedPatches.insert(slavePatchName))
+            {
+                Info<< "Error: patch specified multiple times - "
+                    << slavePatchName << nl;
+
+                requestedPatches.erase(masterPatchName);
+                continue;
+            }
+
+            // Bail out if either patch has problems
+            if
+            (
+                !checkPatch(mesh.boundaryMesh(), masterPatchName)
+             || !checkPatch(mesh.boundaryMesh(), slavePatchName)
+            )
+            {
+                requestedPatches.erase(masterPatchName);
+                requestedPatches.erase(slavePatchName);
+                continue;
+            }
+
+            // Input was validated
+
+            validatedDict.add(iter().keyword(), iter().dict());
         }
+    }
 
-        mesh.faceZones()
-        (
-            mergePatchName + "SlaveZone",
-            true // verbose
-        ).resetAddressing(osf.xfer(), false);
+    const label nActions = validatedDict.size();
+
+    Info<< nl << nActions << " validated actions" << endl;
+
+    if (!nActions)
+    {
+        Info<<"\nStopping" << nl << endl;
+        return 1;
+    }
 
-        // An empty zone for cut faces
-        mesh.faceZones()
-        (
-            cutZoneName,
-            true // verbose
-        ).resetAddressing(labelList(), false);
 
+    // ------------------------------------------
+    // This is where the real work begins
 
-        // Add the sliding interface mesh modifier
-        stitcher.set
+    // set up the tolerances for the sliding mesh
+    dictionary slidingTolerances;
+    if (args.optionFound("toleranceDict"))
+    {
+        IOdictionary toleranceFile
         (
-            0,
-            new slidingInterface
+            IOobject
             (
-                "couple",
-                0,
-                stitcher,
-                mergePatchName + "MasterZone",
-                mergePatchName + "SlaveZone",
-                mergePatchName + "CutPointZone",
-                cutZoneName,
-                masterPatchName,
-                slavePatchName,
-                tom,                    // integral or partial
-                true                    // couple/decouple mode
+                args["toleranceDict"],
+                runTime.constant(),
+                mesh,
+                IOobject::MUST_READ_IF_MODIFIED,
+                IOobject::NO_WRITE
             )
         );
-        static_cast<slidingInterface&>(stitcher[0]).setTolerances
-        (
-            slidingTolerances,
-            true
-        );
+        slidingTolerances += toleranceFile;
     }
 
+
     // Search for list of objects for this time
     IOobjectList objects(mesh, runTime.timeName());
 
@@ -358,51 +425,231 @@ int main(int argc, char *argv[])
     //PtrList<surfaceTensorField> surfaceTensorFields;
     //ReadFields(mesh, objects, surfaceTensorFields);
 
-    if (!overwrite)
+    // Increase precision for output mesh points
+    IOstream::defaultPrecision(max(10u, IOstream::defaultPrecision()));
+
+    polyTopoChanger stitcher(mesh, IOobject::NO_READ);
+
+    // Step through the topology changes
+    label actioni = 0;
+    forAllConstIters(validatedDict, iter)
     {
-        runTime++;
-    }
+        const dictionary& dict = iter().dict();
 
-    // Execute all polyMeshModifiers
-    autoPtr<mapPolyMesh> morphMap = stitcher.changeMesh(true);
+        // Match type
+        bool perfect = false;
+        slidingInterface::typeOfMatch matchType = slidingInterface::PARTIAL;
 
-    mesh.movePoints(morphMap->preMotionPoints());
+        word matchName;
+        if (dict.readIfPresent("match", matchName))
+        {
+            if (matchName == "perfect")
+            {
+                perfect = true;
+            }
+            else
+            {
+                matchType = slidingInterface::typeOfMatchNames[matchName];
+            }
+        }
 
-    // Write mesh
-    if (overwrite)
-    {
-        mesh.setInstance(oldInstance);
-        stitcher.instance() = oldInstance;
-    }
-    Info<< nl << "Writing polyMesh to time " << runTime.timeName() << endl;
+        // Patch names
+        const word masterPatchName(dict["master"]);
+        const word slavePatchName(dict["slave"]);
 
-    IOstream::defaultPrecision(max(10u, IOstream::defaultPrecision()));
+        // Zone names
+        const word mergePatchName(masterPatchName + slavePatchName);
+        const word cutZoneName(mergePatchName + "CutFaceZone");
+
+        Info<< nl << "========================================" << nl;
+
+        // Information messages
+        if (perfect)
+        {
+            Info<< "Coupling PERFECTLY aligned patches "
+                << masterPatchName << " / " << slavePatchName << nl << nl
+                << "Resulting (internal) faces in faceZone "
+                << cutZoneName << nl << nl
+                << "The patch vertices and face centres must align within a"
+                << " tolerance relative to the minimum edge length on the patch"
+                << nl << endl;
+        }
+        else if (matchType == slidingInterface::INTEGRAL)
+        {
+            Info<< "Coupling INTEGRALLY matching of patches "
+                << masterPatchName << " / " << slavePatchName << nl << nl
+                << "Resulting (internal) faces in faceZone "
+                << cutZoneName << nl << nl
+                << "The overall area covered by both patches should be"
+                << " identical!" << endl
+                << "If this is not the case use partial"
+                << nl << endl;
+        }
+        else
+        {
+            Info<< "Coupling PARTIALLY overlapping patches "
+                << masterPatchName << " / " << slavePatchName << nl
+                << "Resulting internal faces in faceZone "
+                << cutZoneName << nl
+                << "Uncovered faces remain in their patch"
+                << nl << endl;
+        }
 
-    // Bypass runTime write (since only writes at writeTime)
-    if
-    (
-        !runTime.objectRegistry::writeObject
-        (
-            runTime.writeFormat(),
-            IOstream::currentVersion,
-            runTime.writeCompression(),
-            true
-        )
-    )
-    {
-        FatalErrorInFunction
-            << "Failed writing polyMesh."
-            << exit(FatalError);
-    }
 
-    mesh.faceZones().write();
-    mesh.pointZones().write();
-    mesh.cellZones().write();
+        // Master/slave patches
+        const polyPatch& masterPatch = mesh.boundaryMesh()[masterPatchName];
+        const polyPatch& slavePatch = mesh.boundaryMesh()[slavePatchName];
+
+        mesh.pointZones().clearAddressing();
+        mesh.faceZones().clearAddressing();
+        mesh.cellZones().clearAddressing();
+
+        // Lists of master and slave faces:
+        labelList faceIds;
+
+        // Markup master face ids
+        faceIds.setSize(masterPatch.size());
+        std::iota(faceIds.begin(), faceIds.end(), masterPatch.start());
+
+        stitcher.clear();
+        stitcher.setSize(1);
+
+        if (perfect)
+        {
+            // Add new (empty) zone for resulting internal faces
+            mesh.faceZones()
+            (
+                cutZoneName,
+                true // verbose
+            ).resetAddressing(faceIds.xfer(), false);
+
+
+            // Add the perfect interface mesh modifier
+            stitcher.set
+            (
+                0,
+                new perfectInterface
+                (
+                    "couple" + Foam::name(actioni),
+                    0,
+                    stitcher,
+                    cutZoneName,
+                    masterPatchName,
+                    slavePatchName
+                )
+            );
+        }
+        else
+        {
+            mesh.pointZones()
+            (
+                mergePatchName + "CutPointZone",
+                true // verbose
+            ) = labelList();
+
+            mesh.faceZones()
+            (
+                mergePatchName + "MasterZone",
+                true // verbose
+            ).resetAddressing(faceIds.xfer(), false);
+
+            // Markup slave face ids
+            faceIds.setSize(slavePatch.size());
+            std::iota(faceIds.begin(), faceIds.end(), slavePatch.start());
+
+            mesh.faceZones()
+            (
+                mergePatchName + "SlaveZone",
+                true // verbose
+            ).resetAddressing(faceIds.xfer(), false);
 
-    // Write fields
-    runTime.write();
+            // Add empty zone for cut faces
+            mesh.faceZones()
+            (
+                cutZoneName,
+                true // verbose
+            ).resetAddressing(labelList(), false);
+
+
+            // Add the sliding interface mesh modifier
+            stitcher.set
+            (
+                0,
+                new slidingInterface
+                (
+                    "couple" + Foam::name(actioni),
+                    0,
+                    stitcher,
+                    mergePatchName + "MasterZone",
+                    mergePatchName + "SlaveZone",
+                    mergePatchName + "CutPointZone",
+                    cutZoneName,
+                    masterPatchName,
+                    slavePatchName,
+                    matchType,      // integral or partial
+                    true            // couple/decouple mode
+                )
+            );
+
+            static_cast<slidingInterface&>(stitcher[0]).setTolerances
+            (
+                slidingTolerances,
+                true
+            );
+        }
+
+        ++actioni;
+
+        // Advance time for intermediate results or only on final
+        if (!overwrite && (intermediate || actioni == nActions))
+        {
+            runTime++;
+        }
+
+        // Execute all polyMeshModifiers
+        autoPtr<mapPolyMesh> morphMap = stitcher.changeMesh(true);
+
+        mesh.movePoints(morphMap->preMotionPoints());
+
+        // Write mesh
+        if (overwrite)
+        {
+            mesh.setInstance(oldInstance);
+            stitcher.instance() = oldInstance;
+        }
+
+        if (intermediate || actioni == nActions)
+        {
+            Info<< nl << "Writing polyMesh to time "
+                << runTime.timeName() << endl;
+
+            // Bypass runTime write (since only writes at writeTime)
+            if
+            (
+                !runTime.objectRegistry::writeObject
+                (
+                    runTime.writeFormat(),
+                    IOstream::currentVersion,
+                    runTime.writeCompression(),
+                    true
+                )
+            )
+            {
+                FatalErrorInFunction
+                    << "Failed writing polyMesh."
+                    << exit(FatalError);
+            }
+
+            mesh.faceZones().write();
+            mesh.pointZones().write();
+            mesh.cellZones().write();
+
+            // Write fields
+            runTime.write();
+        }
+    }
 
-    Info<< nl << "End" << nl <<  endl;
+    Info<< "\nEnd\n" <<  endl;
 
     return 0;
 }
diff --git a/applications/utilities/mesh/manipulation/stitchMesh/stitchMeshDict b/applications/utilities/mesh/manipulation/stitchMesh/stitchMeshDict
new file mode 100644
index 0000000000000000000000000000000000000000..02c1978021a533c0270d4f71947b9c10b8a9fb65
--- /dev/null
+++ b/applications/utilities/mesh/manipulation/stitchMesh/stitchMeshDict
@@ -0,0 +1,38 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  plus                                  |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      stitchMeshDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+outerx
+{
+    match   partial;    // partial | integral | perfect
+    master  outerx;
+    slave   innerx;
+}
+
+outery
+{
+    match   partial;
+    master  outery;
+    slave   innery;
+}
+
+outerz
+{
+    match   partial;
+    master  outerz;
+    slave   innerz;
+}
+
+// ************************************************************************* //
diff --git a/src/dynamicMesh/perfectInterface/perfectInterface.C b/src/dynamicMesh/perfectInterface/perfectInterface.C
index 1b2475dc47915f5c8e52f3ce875927c94ea5e5cb..7794e791bf415ebce1ff127fe6353f5ddb5c0bdd 100644
--- a/src/dynamicMesh/perfectInterface/perfectInterface.C
+++ b/src/dynamicMesh/perfectInterface/perfectInterface.C
@@ -79,7 +79,6 @@ Foam::pointField Foam::perfectInterface::calcFaceCentres
 
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
-// Construct from components
 Foam::perfectInterface::perfectInterface
 (
     const word& name,
@@ -97,7 +96,6 @@ Foam::perfectInterface::perfectInterface
 {}
 
 
-// Construct from dictionary
 Foam::perfectInterface::perfectInterface
 (
     const word& name,
diff --git a/src/dynamicMesh/setUpdater/setUpdater.C b/src/dynamicMesh/setUpdater/setUpdater.C
index f7c4f8edc16633880ee894e3c7315b5a7207cde0..290de7124d35e5a64c52076adaa5a2f478cc1779 100644
--- a/src/dynamicMesh/setUpdater/setUpdater.C
+++ b/src/dynamicMesh/setUpdater/setUpdater.C
@@ -45,6 +45,7 @@ namespace Foam
     );
 }
 
+
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
 Foam::setUpdater::setUpdater
diff --git a/src/dynamicMesh/slidingInterface/slidingInterface.C b/src/dynamicMesh/slidingInterface/slidingInterface.C
index 84caf4901b33b8e7d7ca45b6fdfd15d06f881863..093391c36bd7600be9c4593672051063a908a7ff 100644
--- a/src/dynamicMesh/slidingInterface/slidingInterface.C
+++ b/src/dynamicMesh/slidingInterface/slidingInterface.C
@@ -52,7 +52,7 @@ const Foam::Enum
 <
     Foam::slidingInterface::typeOfMatch
 >
-Foam::slidingInterface::typeOfMatchNames_
+Foam::slidingInterface::typeOfMatchNames
 {
     { typeOfMatch::INTEGRAL, "integral" },
     { typeOfMatch::PARTIAL, "partial" },
@@ -112,8 +112,6 @@ void Foam::slidingInterface::clearOut() const
 
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
-
-// Construct from components
 Foam::slidingInterface::slidingInterface
 (
     const word& name,
@@ -204,7 +202,6 @@ Foam::slidingInterface::slidingInterface
 }
 
 
-// Construct from components
 Foam::slidingInterface::slidingInterface
 (
     const word& name,
@@ -244,7 +241,7 @@ Foam::slidingInterface::slidingInterface
         dict.lookup("slavePatchName"),
         mme.mesh().boundaryMesh()
     ),
-    matchType_(typeOfMatchNames_.lookup("typeOfMatch", dict)),
+    matchType_(typeOfMatchNames.lookup("typeOfMatch", dict)),
     coupleDecouple_(dict.lookup("coupleDecouple")),
     attached_(dict.lookup("attached")),
     projectionAlgo_
@@ -749,7 +746,7 @@ void Foam::slidingInterface::write(Ostream& os) const
         << cutFaceZoneID_.name() << nl
         << masterPatchID_.name() << nl
         << slavePatchID_.name() << nl
-        << typeOfMatchNames_[matchType_] << nl
+        << typeOfMatchNames[matchType_] << nl
         << coupleDecouple_ << nl
         << attached_ << endl;
 }
@@ -776,7 +773,7 @@ void Foam::slidingInterface::writeDict(Ostream& os) const
     os.writeEntry("cutFaceZoneName", cutFaceZoneID_.name());
     os.writeEntry("masterPatchName", masterPatchID_.name());
     os.writeEntry("slavePatchName", slavePatchID_.name());
-    os.writeEntry("typeOfMatch", typeOfMatchNames_[matchType_]);
+    os.writeEntry("typeOfMatch", typeOfMatchNames[matchType_]);
     os.writeEntry("coupleDecouple", coupleDecouple_);
     os.writeEntry("projection", intersection::algorithmNames_[projectionAlgo_]);
     os.writeEntry("attached", attached_);
diff --git a/src/dynamicMesh/slidingInterface/slidingInterface.H b/src/dynamicMesh/slidingInterface/slidingInterface.H
index 52232d8475e480e7a6f131268ec7a1b240804c30..d5fa5a79702f6dc1f42999063927abde716b4fcb 100644
--- a/src/dynamicMesh/slidingInterface/slidingInterface.H
+++ b/src/dynamicMesh/slidingInterface/slidingInterface.H
@@ -84,8 +84,8 @@ public:
             PARTIAL
         };
 
-        //- Direction names
-        static const Enum<typeOfMatch> typeOfMatchNames_;
+        //- Names for the types of matches
+        static const Enum<typeOfMatch> typeOfMatchNames;
 
 private:
 
diff --git a/tutorials/mesh/stitchMesh/simple-cube1/Allrun b/tutorials/mesh/stitchMesh/simple-cube1/Allrun
index 1f37298922d81a48dc3c9f69c798b71f5069bb05..9957423e6e5090599549b2b809516bc188ade853 100755
--- a/tutorials/mesh/stitchMesh/simple-cube1/Allrun
+++ b/tutorials/mesh/stitchMesh/simple-cube1/Allrun
@@ -4,9 +4,11 @@ cd ${0%/*} || exit 1                        # Run from this directory
 
 runApplication ./Allmesh
 
-for dir in x y z
-do
-    runApplication -s dir-$dir stitchMesh -partial outer$dir inner$dir
-done
+# Use stitchMesh with dictionary
+
+# runApplication stitchMesh -intermediate
+runApplication stitchMesh -overwrite
+
+runApplication checkMesh
 
 # -----------------------------------------------------------------------------
diff --git a/tutorials/mesh/stitchMesh/simple-cube1/Allrun-args b/tutorials/mesh/stitchMesh/simple-cube1/Allrun-args
new file mode 100755
index 0000000000000000000000000000000000000000..b5397f82d3964ca6020d09238ae63390ecc5b24f
--- /dev/null
+++ b/tutorials/mesh/stitchMesh/simple-cube1/Allrun-args
@@ -0,0 +1,15 @@
+#!/bin/sh
+cd ${0%/*} || exit 1                        # Run from this directory
+. $WM_PROJECT_DIR/bin/tools/RunFunctions    # Tutorial run functions
+
+runApplication ./Allmesh
+
+# Use stitchMesh with command arguments (no dictionary)
+for dir in x y z
+do
+    runApplication -s dir-$dir stitchMesh -partial outer$dir inner$dir
+done
+
+runApplication checkMesh
+
+# -----------------------------------------------------------------------------
diff --git a/tutorials/mesh/stitchMesh/simple-cube1/system/stitchMeshDict b/tutorials/mesh/stitchMesh/simple-cube1/system/stitchMeshDict
new file mode 100644
index 0000000000000000000000000000000000000000..02c1978021a533c0270d4f71947b9c10b8a9fb65
--- /dev/null
+++ b/tutorials/mesh/stitchMesh/simple-cube1/system/stitchMeshDict
@@ -0,0 +1,38 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  plus                                  |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      stitchMeshDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+outerx
+{
+    match   partial;    // partial | integral | perfect
+    master  outerx;
+    slave   innerx;
+}
+
+outery
+{
+    match   partial;
+    master  outery;
+    slave   innery;
+}
+
+outerz
+{
+    match   partial;
+    master  outerz;
+    slave   innerz;
+}
+
+// ************************************************************************* //