diff --git a/applications/utilities/miscellaneous/foamListRegions/Make/files b/applications/utilities/miscellaneous/foamListRegions/Make/files
new file mode 100644
index 0000000000000000000000000000000000000000..218b5933c46097797a42339f2117d819e68bac89
--- /dev/null
+++ b/applications/utilities/miscellaneous/foamListRegions/Make/files
@@ -0,0 +1,3 @@
+foamListRegions.C
+
+EXE = $(FOAM_APPBIN)/foamListRegions
diff --git a/applications/utilities/miscellaneous/foamListRegions/Make/options b/applications/utilities/miscellaneous/foamListRegions/Make/options
new file mode 100644
index 0000000000000000000000000000000000000000..4cf2f664c9866f3a5933a855857af2cd70e83c0c
--- /dev/null
+++ b/applications/utilities/miscellaneous/foamListRegions/Make/options
@@ -0,0 +1,5 @@
+EXE_INC = \
+    -I$(LIB_SRC)/regionModels/regionModel/lnInclude
+
+EXE_LIBS = \
+    -lregionModels
diff --git a/applications/utilities/miscellaneous/foamListRegions/foamListRegions.C b/applications/utilities/miscellaneous/foamListRegions/foamListRegions.C
new file mode 100644
index 0000000000000000000000000000000000000000..4e56cd3376fe03fcda52afcfb79324e34fbe926a
--- /dev/null
+++ b/applications/utilities/miscellaneous/foamListRegions/foamListRegions.C
@@ -0,0 +1,113 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2017 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/>.
+
+Application
+    foamListRegions
+
+Group
+    grpPostProcessingUtilities
+
+Description
+    List regions from constant/regionProperties.
+
+    To simplify parsing of the output, the normal banner information
+    is suppressed.
+
+Usage
+    \b foamListRegions [OPTION]
+
+\*---------------------------------------------------------------------------*/
+
+#include "argList.H"
+#include "Time.H"
+#include "regionProperties.H"
+
+using namespace Foam;
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+int main(int argc, char *argv[])
+{
+    argList::addNote("List regions from constant/regionProperties");
+
+    argList::noBanner();
+    argList::noParallel();
+    argList::noJobInfo();
+    argList::noFunctionObjects();
+    // No profiling since there is no time loop
+
+    // Non-mandatory arguments
+    argList::addArgument("regionType ... regionType");
+
+    #include "setRootCaseNonMandatoryArgs.H"
+
+    // As per "createTime.H", but quieter.
+    Time runTime(Time::controlDictName, args);
+
+    regionProperties rp(runTime);
+
+    // We now handle checking args and general sanity etc.
+    wordList regionTypes;
+
+    if (args.size() > 1)
+    {
+        regionTypes.setSize(args.size()-1);
+
+        label nTypes = 0;
+        for (label argi = 1; argi < args.size(); ++argi)
+        {
+            regionTypes[nTypes] = args[argi];
+
+            if (rp.found(regionTypes[nTypes]))
+            {
+                ++nTypes;
+            }
+            else
+            {
+                std::cerr<< "No region-type: " << regionTypes[nTypes] << nl;
+            }
+        }
+
+        regionTypes.setSize(nTypes);
+    }
+    else
+    {
+        regionTypes = rp.sortedToc();
+    }
+
+
+    for (const word& regionType : regionTypes)
+    {
+        const wordList& regionNames = rp[regionType];
+
+        for (const word& regionName : regionNames)
+        {
+            Info<< regionName << nl;
+        }
+    }
+
+    return 0;
+}
+
+
+// ************************************************************************* //
diff --git a/applications/utilities/parallelProcessing/decomposePar/decomposePar.C b/applications/utilities/parallelProcessing/decomposePar/decomposePar.C
index d1b9b58a7de1c71b956fa1443d74f81c192c6855..37de5137e73b1bb5e2bac4c7ba471c400fac96c7 100644
--- a/applications/utilities/parallelProcessing/decomposePar/decomposePar.C
+++ b/applications/utilities/parallelProcessing/decomposePar/decomposePar.C
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
+     \\/     M anipulation  | Copyright (C) 2016-2017 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -275,15 +275,15 @@ int main(int argc, char *argv[])
 
     #include "setRootCase.H"
 
-    bool region                  = args.optionFound("region");
-    bool allRegions              = args.optionFound("allRegions");
-    bool writeCellDist           = args.optionFound("cellDist");
-    bool copyZero                = args.optionFound("copyZero");
-    bool copyUniform             = args.optionFound("copyUniform");
-    bool decomposeFieldsOnly     = args.optionFound("fields");
-    bool decomposeSets           = !args.optionFound("noSets");
-    bool forceOverwrite          = args.optionFound("force");
-    bool ifRequiredDecomposition = args.optionFound("ifRequired");
+    const bool optRegion        = args.optionFound("region");
+    const bool allRegions       = args.optionFound("allRegions");
+    const bool writeCellDist    = args.optionFound("cellDist");
+    const bool copyZero         = args.optionFound("copyZero");
+    const bool copyUniform      = args.optionFound("copyUniform");
+    const bool decomposeSets    = !args.optionFound("noSets");
+    bool decomposeFieldsOnly    = args.optionFound("fields");
+    bool forceOverwrite         = args.optionFound("force");
+    const bool ifRequiredDecomposition = args.optionFound("ifRequired");
 
     // Set time from database
     #include "createTime.H"
@@ -296,44 +296,30 @@ int main(int argc, char *argv[])
     args.optionReadIfPresent("decomposeParDict", decompDictFile);
 
     wordList regionNames;
-    wordList regionDirs;
     if (allRegions)
     {
         Info<< "Decomposing all regions in regionProperties" << nl << endl;
         regionProperties rp(runTime);
-        forAllConstIter(HashTable<wordList>, rp, iter)
+
+        wordHashSet names;
+        forAllConstIters(rp, iter)
         {
-            const wordList& regions = iter();
-            forAll(regions, i)
-            {
-                if (!regionNames.found(regions[i]))
-                {
-                    regionNames.append(regions[i]);
-                }
-            }
+            names.insert(iter.object());
         }
-        regionDirs = regionNames;
+
+        regionNames = names.sortedToc();
     }
     else
     {
-        word regionName;
-        if (args.optionReadIfPresent("region", regionName))
-        {
-            regionNames = wordList(1, regionName);
-            regionDirs = regionNames;
-        }
-        else
-        {
-            regionNames = wordList(1, fvMesh::defaultRegion);
-            regionDirs = wordList(1, word::null);
-        }
+        regionNames = {fvMesh::defaultRegion};
+        args.optionReadIfPresent("region", regionNames[0]);
     }
 
-
     forAll(regionNames, regioni)
     {
         const word& regionName = regionNames[regioni];
-        const word& regionDir = regionDirs[regioni];
+        const word& regionDir =
+            regionName == fvMesh::defaultRegion ? word::null : regionName;
 
         Info<< "\n\nDecomposing mesh " << regionName << nl << endl;
 
@@ -391,7 +377,7 @@ int main(int argc, char *argv[])
                 Info<< "Using existing processor directories" << nl;
             }
 
-            if (region || allRegions)
+            if (allRegions || optRegion)
             {
                 procDirsProblem = false;
                 forceOverwrite = false;
@@ -527,7 +513,7 @@ int main(int argc, char *argv[])
         {
             // Copy the 0 directory into each of the processor directories
             fileName prevTimePath;
-            for (label proci = 0; proci < mesh.nProcs(); proci++)
+            for (label proci = 0; proci < mesh.nProcs(); ++proci)
             {
                 Time processorDb
                 (
@@ -736,13 +722,13 @@ int main(int argc, char *argv[])
 
                 label cloudI = 0;
 
-                forAll(cloudDirs, i)
+                for (const fileName& cloudDir : cloudDirs)
                 {
                     IOobjectList sprayObjs
                     (
                         mesh,
                         runTime.timeName(),
-                        cloud::prefix/cloudDirs[i],
+                        cloud::prefix/cloudDir,
                         IOobject::MUST_READ,
                         IOobject::NO_WRITE,
                         false
@@ -759,7 +745,7 @@ int main(int argc, char *argv[])
                         // ~~~~~~~~~~~~~~~~~~~~~~~~~
 
                         Info<< "Identified lagrangian data set: "
-                            << cloudDirs[i] << endl;
+                            << cloudDir << endl;
 
                         lagrangianPositions.set
                         (
@@ -767,7 +753,7 @@ int main(int argc, char *argv[])
                             new Cloud<indexedParticle>
                             (
                                 mesh,
-                                cloudDirs[i],
+                                cloudDir,
                                 false
                             )
                         );
@@ -944,7 +930,7 @@ int main(int argc, char *argv[])
                 Info<< endl;
 
                 // split the fields over processors
-                for (label proci = 0; proci < mesh.nProcs(); proci++)
+                for (label proci = 0; proci < mesh.nProcs(); ++proci)
                 {
                     Info<< "Processor " << proci << ": field transfer" << endl;
 
@@ -1234,8 +1220,8 @@ int main(int argc, char *argv[])
                     // directory
                     decomposeUniform(copyUniform, mesh, processorDb, regionDir);
 
-                    // For the first region of a multi-region case additionally
-                    // decompose the "uniform" directory in the time directory
+                    // For a multi-region case, also decompose the "uniform"
+                    // directory in the time directory
                     if (regionNames.size() > 1 && regioni == 0)
                     {
                         decomposeUniform(copyUniform, mesh, processorDb);
diff --git a/applications/utilities/parallelProcessing/reconstructPar/reconstructPar.C b/applications/utilities/parallelProcessing/reconstructPar/reconstructPar.C
index efc5f9b0f35e6a8aaa5acb3b8ba453714ba4c7a5..cabee6ef3904dcb5cb3cd5b35ae6304d839d1f18 100644
--- a/applications/utilities/parallelProcessing/reconstructPar/reconstructPar.C
+++ b/applications/utilities/parallelProcessing/reconstructPar/reconstructPar.C
@@ -54,14 +54,14 @@ Description
 
 bool haveAllTimes
 (
-    const HashSet<word>& masterTimeDirSet,
+    const wordHashSet& masterTimeDirSet,
     const instantList& timeDirs
 )
 {
     // Loop over all times
-    forAll(timeDirs, timei)
+    for (const instant& t : timeDirs)
     {
-        if (!masterTimeDirSet.found(timeDirs[timei].name()))
+        if (!masterTimeDirSet.found(t.name()))
         {
             return false;
         }
@@ -126,11 +126,8 @@ int main(int argc, char *argv[])
     #include "setRootCase.H"
     #include "createTime.H"
 
-    HashSet<word> selectedFields;
-    if (args.optionFound("fields"))
-    {
-        args.optionLookup("fields")() >> selectedFields;
-    }
+    wordHashSet selectedFields;
+    args.optionReadIfPresent("fields", selectedFields);
 
     const bool noFields = args.optionFound("noFields");
 
@@ -158,8 +155,8 @@ int main(int argc, char *argv[])
     }
 
 
-    HashSet<word> selectedLagrangianFields;
-    if (args.optionFound("lagrangianFields"))
+    wordHashSet selectedLagrangianFields;
+    if (args.optionReadIfPresent("lagrangianFields", selectedLagrangianFields))
     {
         if (noLagrangian)
         {
@@ -168,50 +165,42 @@ int main(int argc, char *argv[])
                 << "options together."
                 << exit(FatalError);
         }
-
-        args.optionLookup("lagrangianFields")() >> selectedLagrangianFields;
     }
 
 
     const bool newTimes   = args.optionFound("newTimes");
     const bool allRegions = args.optionFound("allRegions");
 
-
     wordList regionNames;
     wordList regionDirs;
     if (allRegions)
     {
-        Info<< "Reconstructing for all regions in regionProperties" << nl
-            << endl;
+        Info<< "Reconstructing all regions in regionProperties" << nl << endl;
         regionProperties rp(runTime);
-        forAllConstIter(HashTable<wordList>, rp, iter)
+
+        wordHashSet names;
+        forAllConstIters(rp, iter)
         {
-            const wordList& regions = iter();
-            forAll(regions, i)
-            {
-                if (!regionNames.found(regions[i]))
-                {
-                    regionNames.append(regions[i]);
-                }
-            }
+            names.insert(iter.object());
         }
+
+        regionNames = names.sortedToc();
         regionDirs = regionNames;
     }
     else
     {
-        word regionName;
-        if (args.optionReadIfPresent("region", regionName))
+        regionNames = {fvMesh::defaultRegion};
+        if (args.optionReadIfPresent("region", regionNames[0]))
         {
-            regionNames = wordList(1, regionName);
             regionDirs = regionNames;
         }
         else
         {
-            regionNames = wordList(1, fvMesh::defaultRegion);
-            regionDirs = wordList(1, word::null);
+            regionDirs = {word::null};
         }
     }
 
+
     // Determine the processor count
     label nProcs = fileHandler().nProcs(args.path(), regionDirs[0]);
 
@@ -267,10 +256,10 @@ int main(int argc, char *argv[])
     {
         masterTimeDirs = runTime.times();
     }
-    HashSet<word> masterTimeDirSet(2*masterTimeDirs.size());
-    forAll(masterTimeDirs, i)
+    wordHashSet masterTimeDirSet(2*masterTimeDirs.size());
+    for (const instant& t : masterTimeDirs)
     {
-        masterTimeDirSet.insert(masterTimeDirs[i].name());
+        masterTimeDirSet.insert(t.name());
     }
 
 
@@ -567,21 +556,18 @@ int main(int argc, char *argv[])
                         );
                     }
 
-                    forAll(cloudDirs, i)
+                    for (const fileName& cloudDir : cloudDirs)
                     {
                         // Check if we already have cloud objects for this
                         // cloudname
-                        HashTable<IOobjectList>::const_iterator iter =
-                            cloudObjects.find(cloudDirs[i]);
-
-                        if (iter == cloudObjects.end())
+                        if (!cloudObjects.found(cloudDir))
                         {
                             // Do local scan for valid cloud objects
                             IOobjectList sprayObjs
                             (
                                 procMeshes.meshes()[proci],
                                 databases[proci].timeName(),
-                                cloud::prefix/cloudDirs[i]
+                                cloud::prefix/cloudDir
                             );
 
                             IOobject* positionsPtr =
@@ -591,7 +577,7 @@ int main(int argc, char *argv[])
 
                             if (coordsPtr || positionsPtr)
                             {
-                                cloudObjects.insert(cloudDirs[i], sprayObjs);
+                                cloudObjects.insert(cloudDir, sprayObjs);
                             }
                         }
                     }
@@ -606,7 +592,7 @@ int main(int argc, char *argv[])
                         const word cloudName = word::validate(iter.key());
 
                         // Objects (on arbitrary processor)
-                        const IOobjectList& sprayObjs = iter();
+                        const IOobjectList& sprayObjs = iter.object();
 
                         Info<< "Reconstructing lagrangian fields for cloud "
                             << cloudName << nl << endl;
diff --git a/applications/utilities/parallelProcessing/redistributePar/redistributePar.C b/applications/utilities/parallelProcessing/redistributePar/redistributePar.C
index e0ba52f7a7dca5eba84e560ca592134a0fd33e50..f9b1cbed0bf5244fb6f117103ed45276c5b5f7b1 100644
--- a/applications/utilities/parallelProcessing/redistributePar/redistributePar.C
+++ b/applications/utilities/parallelProcessing/redistributePar/redistributePar.C
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2015-2016 OpenCFD Ltd.
+     \\/     M anipulation  | Copyright (C) 2015-2017 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -105,7 +105,7 @@ scalar getMergeDistance
     scalar mergeTol = defaultMergeTol;
     args.optionReadIfPresent("mergeTol", mergeTol);
 
-    scalar writeTol =
+    const scalar writeTol =
         Foam::pow(scalar(10.0), -scalar(IOstream::defaultPrecision()));
 
     Info<< "Merge tolerance : " << mergeTol << nl
@@ -236,7 +236,7 @@ void writeDecomposition
 (
     const word& name,
     const fvMesh& mesh,
-    const labelList& decomp
+    const labelUList& decomp
 )
 {
     // Write the decomposition as labelList for use with 'manual'
@@ -388,10 +388,9 @@ void determineDecomposition
 // Write addressing if decomposing (1 to many) or reconstructing (many to 1)
 void writeProcAddressing
 (
-    const bool decompose,
-    const fileName& meshSubDir,
     const fvMesh& mesh,
-    const mapDistributePolyMesh& map
+    const mapDistributePolyMesh& map,
+    const bool decompose
 )
 {
     Info<< "Writing procAddressing files to " << mesh.facesInstance()
@@ -403,7 +402,7 @@ void writeProcAddressing
         (
             "cellProcAddressing",
             mesh.facesInstance(),
-            meshSubDir,
+            polyMesh::meshSubDir,
             mesh,
             IOobject::NO_READ
         ),
@@ -416,7 +415,7 @@ void writeProcAddressing
         (
             "faceProcAddressing",
             mesh.facesInstance(),
-            meshSubDir,
+            polyMesh::meshSubDir,
             mesh,
             IOobject::NO_READ
         ),
@@ -429,7 +428,7 @@ void writeProcAddressing
         (
             "pointProcAddressing",
             mesh.facesInstance(),
-            meshSubDir,
+            polyMesh::meshSubDir,
             mesh,
             IOobject::NO_READ
         ),
@@ -442,7 +441,7 @@ void writeProcAddressing
         (
             "boundaryProcAddressing",
             mesh.facesInstance(),
-            meshSubDir,
+            polyMesh::meshSubDir,
             mesh,
             IOobject::NO_READ
         ),
@@ -545,10 +544,10 @@ void writeProcAddressing
         );
     }
 
-    bool cellOk = cellMap.write();
-    bool faceOk = faceMap.write();
-    bool pointOk = pointMap.write();
-    bool patchOk = patchMap.write();
+    const bool cellOk = cellMap.write();
+    const bool faceOk = faceMap.write();
+    const bool pointOk = pointMap.write();
+    const bool patchOk = patchMap.write();
 
     if (!cellOk || !faceOk || !pointOk || !patchOk)
     {
@@ -562,6 +561,24 @@ void writeProcAddressing
 }
 
 
+// Remove addressing
+void removeProcAddressing(const polyMesh& mesh)
+{
+    for (const auto prefix : {"boundary", "cell", "face", "point"})
+    {
+        IOobject io
+        (
+            prefix + word("ProcAddressing"),
+            mesh.facesInstance(),
+            polyMesh::meshSubDir,
+            mesh
+        );
+
+        const fileName procFile(io.objectPath());
+        rm(procFile);
+    }
+}
+
 
 // Generic mesh-based field reading
 template<class GeoField>
@@ -906,8 +923,8 @@ autoPtr<mapDistributePolyMesh> redistributeAndWrite
 
         // We don't want to map the decomposition (mapping already tested when
         // mapping the cell centre field)
-        IOobjectList::iterator iter = objects.find("cellDist");
-        if (iter != objects.end())
+        auto iter = objects.find("cellDist");
+        if (iter.found())
         {
             objects.erase(iter);
         }
@@ -1162,7 +1179,7 @@ autoPtr<mapDistributePolyMesh> redistributeAndWrite
         (
             "procAddressing",
             mesh.facesInstance(),
-            meshSubDir,
+            polyMesh::meshSubDir,
             mesh,
             IOobject::NO_READ,
             IOobject::AUTO_WRITE
@@ -1181,16 +1198,16 @@ autoPtr<mapDistributePolyMesh> redistributeAndWrite
 
             mesh.write();
             topoSet::removeFiles(mesh);
-            forAll(pointFieldNames, i)
+            for (const word& fieldName : pointFieldNames)
             {
                 IOobject io
                 (
-                    pointFieldNames[i],
+                    fieldName,
                     runTime.timeName(),
                     mesh
                 );
 
-                fileName fieldFile(io.objectPath());
+                const fileName fieldFile(io.objectPath());
                 if (topoSet::debug) DebugVar(fieldFile);
                 rm(fieldFile);
             }
@@ -1204,16 +1221,16 @@ autoPtr<mapDistributePolyMesh> redistributeAndWrite
     {
         mesh.write();
         topoSet::removeFiles(mesh);
-        forAll(pointFieldNames, i)
+        for (const word& fieldName : pointFieldNames)
         {
             IOobject io
             (
-                pointFieldNames[i],
+                fieldName,
                 runTime.timeName(),
                 mesh
             );
 
-            fileName fieldFile(io.objectPath());
+            const fileName fieldFile(io.objectPath());
             if (topoSet::debug) DebugVar(fieldFile);
             rm(fieldFile);
         }
@@ -1224,7 +1241,16 @@ autoPtr<mapDistributePolyMesh> redistributeAndWrite
 
     if (decompose || nDestProcs == 1)
     {
-        writeProcAddressing(decompose, meshSubDir, mesh, map);
+        // Decompose (1 -> N) or reconstruct (N -> 1)
+        // so {boundary,cell,face,point}ProcAddressing have meaning
+        writeProcAddressing(mesh, map, decompose);
+    }
+    else
+    {
+        // Redistribute (N -> M)
+        // {boundary,cell,face,point}ProcAddressing would be incorrect
+        // - can either remove or redistribute previous
+        removeProcAddressing(mesh);
     }
 
 
@@ -2272,9 +2298,9 @@ int main(int argc, char *argv[])
     Foam::argList args(argc, argv);
     bool decompose = args.optionFound("decompose");
     const bool reconstruct = args.optionFound("reconstruct");
+    const bool writeCellDist = args.optionFound("cellDist");
+    const bool newTimes = args.optionFound("newTimes");
     bool overwrite = args.optionFound("overwrite");
-    bool writeCellDist = args.optionFound("cellDist");
-    bool newTimes = args.optionFound("newTimes");
 
 
     if (Foam::sigFpe::requested())
@@ -2363,8 +2389,7 @@ int main(int argc, char *argv[])
         Info<< "No processor directories; switching on decompose mode"
             << nl << endl;
     }
-    // If master changed to decompose mode make sure all nodes know about
-    // it
+    // If master changed to decompose mode make sure all nodes know about it
     Pstream::scatter(decompose);
 
 
@@ -2382,9 +2407,9 @@ int main(int argc, char *argv[])
             timeDirs = Time::findTimes(args.path(), "constant");
         }
         Pstream::scatter(timeDirs);
-        forAll(timeDirs, i)
+        for (const instant& t : timeDirs)
         {
-            mkDir(args.path()/timeDirs[i].name());
+            mkDir(args.path()/t.name());
         }
     }
 
@@ -2418,9 +2443,9 @@ int main(int argc, char *argv[])
             timeDirs = Time::findTimes(basePath, "constant");
         }
         Pstream::scatter(timeDirs);
-        forAll(timeDirs, i)
+        for (const instant& t : timeDirs)
         {
-            mkDir(basePath/timeDirs[i].name());
+            mkDir(basePath/t.name());
         }
     }
 
@@ -2441,33 +2466,32 @@ int main(int argc, char *argv[])
     if (newTimes)
     {
         instantList baseTimeDirs(baseRunTime.times());
-        forAll(baseTimeDirs, i)
+        for (const instant& t : baseTimeDirs)
         {
-            masterTimeDirSet.insert(baseTimeDirs[i].name());
+            masterTimeDirSet.insert(t.name());
         }
     }
 
 
     // Determine any region
     word regionName = polyMesh::defaultRegion;
-    fileName meshSubDir;
+    fileName meshSubDir = polyMesh::meshSubDir;
     if (args.optionReadIfPresent("region", regionName))
     {
         meshSubDir = regionName/polyMesh::meshSubDir;
     }
-    else
-    {
-        meshSubDir = polyMesh::meshSubDir;
-    }
     Info<< "Using mesh subdirectory " << meshSubDir << nl << endl;
 
 
+    // Allow override of decomposeParDict location
+    fileName decompDictFile;
+    args.optionReadIfPresent("decomposeParDict", decompDictFile);
+
 
     // Demand driven lagrangian mapper
     autoPtr<parLagrangianRedistributor> lagrangianReconstructorPtr;
 
 
-
     if (reconstruct)
     {
         // use the times list from the master processor
@@ -2689,7 +2713,8 @@ int main(int argc, char *argv[])
         // detect points by hand
         if (mesh.pointsInstance() != mesh.facesInstance())
         {
-            Info<< "    Dected initial mesh motion; reconstructing points" << nl
+            Info<< "    Detected initial mesh motion;"
+                << " reconstructing points" << nl
                 << endl;
             fvReconstructorPtr().reconstructPoints();
         }
@@ -2918,11 +2943,6 @@ int main(int argc, char *argv[])
             mesh.bounds()
         );
 
-        // Allow override of decomposeParDict location
-        fileName decompDictFile;
-        args.optionReadIfPresent("decomposeParDict", decompDictFile);
-
-
         // Determine decomposition
         // ~~~~~~~~~~~~~~~~~~~~~~~
 
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/0/T b/tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/0.orig/T
similarity index 100%
rename from tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/0/T
rename to tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/0.orig/T
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/0/U b/tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/0.orig/U
similarity index 100%
rename from tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/0/U
rename to tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/0.orig/U
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/0/epsilon b/tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/0.orig/epsilon
similarity index 100%
rename from tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/0/epsilon
rename to tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/0.orig/epsilon
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/0/k b/tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/0.orig/k
similarity index 100%
rename from tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/0/k
rename to tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/0.orig/k
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/0/p b/tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/0.orig/p
similarity index 100%
rename from tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/0/p
rename to tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/0.orig/p
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/0/p_rgh b/tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/0.orig/p_rgh
similarity index 100%
rename from tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/0/p_rgh
rename to tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/0.orig/p_rgh
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/Allclean b/tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/Allclean
index fad685f8abf315ed9ac069365c04299af5775c56..696cfb7f54ca0c8a6ca4fe5b773fb4d6d8368988 100755
--- a/tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/Allclean
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/Allclean
@@ -2,16 +2,10 @@
 cd ${0%/*} || exit 1                        # Run from this directory
 . $WM_PROJECT_DIR/bin/tools/CleanFunctions  # Tutorial clean functions
 
-cleanCase
+cleanCase0
 
 rm -rf VTK
 rm -rf constant/cellToRegion
-rm -f 0/cellToRegion
-rm -rf 0/bottomWater
-rm -rf 0/topAir
-rm -rf 0/heater
-rm -rf 0/leftSolid
-rm -rf 0/rightSolid
 
 rm -rf constant/bottomWater/polyMesh
 rm -rf constant/topAir/polyMesh
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/Allmesh b/tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/Allmesh
index 7f27e81ea3b8060659269bd4e3d75c12971e8b4a..44fa7da1372f309d12deb1c3d8948c311ad5f39c 100755
--- a/tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/Allmesh
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/Allmesh
@@ -4,23 +4,25 @@ cd ${0%/*} || exit 1                        # Run from this directory
 
 runApplication blockMesh
 runApplication topoSet
+
+# Restore initial fields
+restore0Dir
+
 runApplication splitMeshRegions -cellZones -overwrite
 
 # Remove fluid fields from solid regions (important for post-processing)
-for i in heater leftSolid rightSolid
+for region in $(foamListRegions solid)
 do
-   rm -f 0*/$i/{nut,alphat,epsilon,k,U,p_rgh}
+    rm -f 0/$region/{nut,alphat,epsilon,k,U,p_rgh}
 done
 
-for i in bottomWater topAir heater leftSolid rightSolid
+for region in $(foamListRegions)
 do
-   runApplication -s $i changeDictionary -region $i
+    runApplication -s $region changeDictionary -region $region
 done
 
-
 echo
-echo "Creating files for paraview post-processing"
+echo "Use paraFoam -touch-all to create files for paraview post-processing"
 echo
-paraFoam -touchAll
 
 #------------------------------------------------------------------------------
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/system/decomposeParDict b/tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/system/decomposeParDict
index e630d52119812f1ca4e10efdeb5be194b1de3266..c8c7edc63d4855f6f8b1e1d3e98f3381c69bdef0 100644
--- a/tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/system/decomposeParDict
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/system/decomposeParDict
@@ -30,12 +30,11 @@ regions
     heater
     {
         numberOfSubdomains  1;
-        method          none;
+        method          simple; // none;
 
         coeffs
         {
             n       (1 1 1);
-            delta   0.001;
         }
     }
 }
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/0/T b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/0.orig/T
similarity index 89%
rename from tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/0/T
rename to tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/0.orig/T
index d28373b3da5a80c18fcda22b57a4769b98a3226d..fda1ac90bb0302f50cdfa072cfe4b6e424dbfdd1 100644
--- a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/0/T
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/0.orig/T
@@ -20,10 +20,12 @@ internalField   uniform 300;
 
 boundaryField
 {
+    #includeEtc "caseDicts/setConstraintTypes"
+
     ".*"
     {
-        type            calculated;
-        value           uniform 300;
+        type    calculated;
+        value   $internalField;
     }
 }
 
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/0/U b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/0.orig/U
similarity index 89%
rename from tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/0/U
rename to tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/0.orig/U
index 7ec4f2907c0f90e9c0b201b13fdcca7edfdb5a82..1e82313ce1ebe1425bb205571ad88e7fc16b5191 100644
--- a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/0/U
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/0.orig/U
@@ -20,10 +20,12 @@ internalField   uniform (0.01 0 0);
 
 boundaryField
 {
+    #includeEtc "caseDicts/setConstraintTypes"
+
     ".*"
     {
-        type            calculated;
-        value           uniform (0.01 0 0);
+        type    calculated;
+        value   $internalField;
     }
 }
 
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/0/alphat b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/0.orig/alphat
similarity index 89%
rename from tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/0/alphat
rename to tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/0.orig/alphat
index 222501d30ec38778441a3f64baeeff3fda0923df..579aa2a63edd70657908593c427b1f46dc465f55 100644
--- a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/0/alphat
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/0.orig/alphat
@@ -20,12 +20,13 @@ internalField   uniform 0;
 
 boundaryField
 {
+    #includeEtc "caseDicts/setConstraintTypes"
+
     ".*"
     {
-        type            calculated;
-        value           uniform 0;
+        type    calculated;
+        value   $internalField;
     }
 }
 
-
 // ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/0/epsilon b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/0.orig/epsilon
similarity index 89%
rename from tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/0/epsilon
rename to tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/0.orig/epsilon
index ee4ec0c64b525509961dd656ef7d8f3736e6631d..5c3cd8d259ba77f9241a2ba9495acb5d39bca72f 100644
--- a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/0/epsilon
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/0.orig/epsilon
@@ -20,12 +20,13 @@ internalField   uniform 0.01;
 
 boundaryField
 {
+    #includeEtc "caseDicts/setConstraintTypes"
+
     ".*"
     {
-        type            calculated;
-        value           uniform 0.01;
+        type    calculated;
+        value   $internalField;
     }
 }
 
-
 // ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/0/k b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/0.orig/k
similarity index 89%
rename from tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/0/k
rename to tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/0.orig/k
index a2aae944737f621cbd8775fb1c32b67e5a1fbfb4..cb92af63c973748bf01345f1dbe3a4bb22f794d1 100644
--- a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/0/k
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/0.orig/k
@@ -20,12 +20,13 @@ internalField   uniform 0.1;
 
 boundaryField
 {
+    #includeEtc "caseDicts/setConstraintTypes"
+
     ".*"
     {
-        type            calculated;
-        value           uniform 0.1;
+        type    calculated;
+        value   $internalField;
     }
 }
 
-
 // ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/0/p b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/0.orig/p
similarity index 89%
rename from tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/0/p
rename to tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/0.orig/p
index e54b106a156a05c93da2cd2de7ce16202c9f4694..3e0414647bbe09ffbf93cdccbdf281c631086a0f 100644
--- a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/0/p
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/0.orig/p
@@ -20,10 +20,12 @@ internalField   uniform 1e5;
 
 boundaryField
 {
+    #includeEtc "caseDicts/setConstraintTypes"
+
     ".*"
     {
-        type            calculated;
-        value           uniform 1e5;
+        type    calculated;
+        value   $internalField;
     }
 }
 
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/0/p_rgh b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/0.orig/p_rgh
similarity index 91%
rename from tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/0/p_rgh
rename to tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/0.orig/p_rgh
index a9074ce903da41c51a37943960f41b955d45feb2..ed32bb409dc21cd0ac3554b2c255fdfd33b5bb87 100644
--- a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/0/p_rgh
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/0.orig/p_rgh
@@ -20,10 +20,12 @@ internalField   uniform 1e5;
 
 boundaryField
 {
+    #includeEtc "caseDicts/setConstraintTypes"
+
     ".*"
     {
         type            calculated;
-        value           uniform 1e5;
+        value           $internalField;
     }
 }
 
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/0/rho b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/0.orig/rho
similarity index 89%
rename from tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/0/rho
rename to tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/0.orig/rho
index f5c3908bd2e495c367ff848006fe03cd21300576..aa67e89d52fcf1ff12aaf469e73a40cc18f0966a 100644
--- a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/0/rho
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/0.orig/rho
@@ -20,10 +20,12 @@ internalField   uniform 8000;
 
 boundaryField
 {
+    #includeEtc "caseDicts/setConstraintTypes"
+
     ".*"
     {
-        type            calculated;
-        value           uniform 8000;
+        type    calculated;
+        value   $internalField;
     }
 }
 
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/Allclean b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/Allclean
index 0ad9dc9eb83fd688de417304e60614151bf130e8..e6134ad5564b572df85c3acdcffad1bd3cad7893 100755
--- a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/Allclean
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/Allclean
@@ -2,19 +2,13 @@
 cd ${0%/*} || exit 1                        # Run from this directory
 . $WM_PROJECT_DIR/bin/tools/CleanFunctions  # Tutorial clean functions
 
-cleanCase
+cleanCase0
 
 rm -rf constant/extendedFeatureEdgeMesh > /dev/null 2>&1
 rm -f constant/triSurface/*.eMesh > /dev/null 2>&1
 
 rm -rf VTK
 rm -rf constant/cellToRegion
-rm -rf 0/bottomAir
-rm -rf 0/topAir
-rm -rf 0/heater
-rm -rf 0/leftSolid
-rm -rf 0/rightSolid
-rm -f 0/cellToRegion
 
 rm -rf constant/bottomAir/polyMesh
 rm -rf constant/topAir/polyMesh
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/Allrun b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/Allrun
deleted file mode 100755
index b3614e73078de5a4f65e9582a38530cd7d783f9e..0000000000000000000000000000000000000000
--- a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/Allrun
+++ /dev/null
@@ -1,45 +0,0 @@
-#!/bin/sh
-cd ${0%/*} || exit 1                        # Run from this directory
-. $WM_PROJECT_DIR/bin/tools/RunFunctions    # Tutorial run functions
-
-rm -rf constant/polyMesh/sets
-
-runApplication blockMesh
-runApplication surfaceFeatureExtract
-
-runApplication snappyHexMesh -overwrite
-runApplication splitMeshRegions -cellZones -overwrite
-
-# remove fluid fields from solid regions (important for post-processing)
-for i in heater leftSolid rightSolid
-do
-   rm -f 0*/$i/{nut,alphat,epsilon,k,U,p_rgh}
-done
-
-
-for i in bottomAir topAir heater leftSolid rightSolid
-do
-   runApplication -s $i  changeDictionary -region $i
-done
-
-
-#-- Run on single processor
-runApplication $(getApplication)
-
-
-## Decompose
-#runApplication decomposePar -allRegions
-#
-## Run
-#runParallel $(getApplication)
-#
-## Reconstruct
-#runApplication reconstructPar -allRegions
-
-
-echo
-echo "creating files for paraview post-processing"
-echo
-paraFoam -touchAll
-
-#------------------------------------------------------------------------------
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/Allrun b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/Allrun
new file mode 120000
index 0000000000000000000000000000000000000000..f8f6fb52273fc4261c74c5bfbaf71e49adfcb80f
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/Allrun
@@ -0,0 +1 @@
+Allrun-parallel
\ No newline at end of file
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/Allrun-parallel b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/Allrun-parallel
new file mode 100755
index 0000000000000000000000000000000000000000..5e3d4522758439533cf810d1877cdaf925da51d5
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/Allrun-parallel
@@ -0,0 +1,55 @@
+#!/bin/sh
+cd ${0%/*} || exit 1                        # Run from this directory
+. $WM_PROJECT_DIR/bin/tools/RunFunctions    # Tutorial run functions
+
+rm -rf constant/polyMesh/sets
+
+# For meshing only
+decompDict="-decomposeParDict system/decomposeParDict.6"
+
+runApplication blockMesh
+runApplication surfaceFeatureExtract
+
+runApplication $decompDict decomposePar
+
+runParallel $decompDict snappyHexMesh -overwrite
+
+# 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/snappyMultiRegionHeater/Allrun-serial b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/Allrun-serial
new file mode 100755
index 0000000000000000000000000000000000000000..87936c17507c1ec4426df670d0a2ad47b021f770
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/Allrun-serial
@@ -0,0 +1,36 @@
+#!/bin/sh
+cd ${0%/*} || exit 1                        # Run from this directory
+. $WM_PROJECT_DIR/bin/tools/RunFunctions    # Tutorial run functions
+
+rm -rf constant/polyMesh/sets
+
+runApplication blockMesh
+runApplication surfaceFeatureExtract
+
+runApplication snappyHexMesh -overwrite
+
+# 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}
+done
+
+for region in $(foamListRegions)
+do
+    runApplication -s $region changeDictionary -region $region
+done
+
+
+# Run on single processor
+runApplication $(getApplication)
+
+echo
+echo "Use paraFoam -touch-all to create files for paraview post-processing"
+echo
+
+#------------------------------------------------------------------------------
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/system/bottomAir/changeDictionaryDict b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/system/bottomAir/changeDictionaryDict
index 498816d58e46792bf77502281cc25514e91b05c2..03a7a9094ce7d6e85060f5c5f86714f06fffa395 100644
--- a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/system/bottomAir/changeDictionaryDict
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/system/bottomAir/changeDictionaryDict
@@ -37,6 +37,10 @@ U
             type            fixedValue;
             value           uniform (0 0 0);
         }
+        "procBoundary.*"
+        {
+            type            processor;
+        }
     }
 }
 
@@ -51,6 +55,11 @@ T
             type            zeroGradient;
         }
 
+        "procBoundary.*"
+        {
+            type            processor;
+        }
+
         "bottomAir_to_.*"
         {
             type            compressible::turbulentTemperatureCoupledBaffleMixed;
@@ -74,6 +83,10 @@ epsilon
             type            epsilonWallFunction;
             value           uniform 0.01;
         }
+        "procBoundary.*"
+        {
+            type            processor;
+        }
     }
 }
 
@@ -88,6 +101,10 @@ k
             type            kqRWallFunction;
             value           uniform 0.1;
         }
+        "procBoundary.*"
+        {
+            type            processor;
+        }
     }
 }
 
@@ -102,6 +119,10 @@ p_rgh
             type            fixedFluxPressure;
             value           uniform 1e5;
         }
+        "procBoundary.*"
+        {
+            type            processor;
+        }
     }
 }
 
@@ -116,6 +137,10 @@ p
             type            calculated;
             value           uniform 1e5;
         }
+        "procBoundary.*"
+        {
+            type            processor;
+        }
     }
 }
 
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/system/bottomAir/decomposeParDict b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/system/bottomAir/decomposeParDict
deleted file mode 100644
index 7263dc66d4ab81b8564c66f1ab7dfdeb659e9260..0000000000000000000000000000000000000000
--- a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/system/bottomAir/decomposeParDict
+++ /dev/null
@@ -1,48 +0,0 @@
-/*--------------------------------*- 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      decomposeParDict;
-}
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
-numberOfSubdomains  4;
-
-//- Keep owner and neighbour on same processor for faces in zones:
-// preserveFaceZones (heater solid1 solid3);
-
-method          scotch;
-// method          hierarchical;
-// method          simple;
-// method          manual;
-
-coeffs
-{
-    n           (2 2 1);
-    //delta       0.001; // default=0.001
-    //order       xyz;   // default=xzy
-    dataFile    "decompositionData";
-}
-
-scotchCoeffs
-{
-    //processorWeights
-    //(
-    //    1
-    //    1
-    //    1
-    //    1
-    //);
-    //writeGraph  true;
-    //strategy "b";
-}
-
-// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/system/bottomAir/decomposeParDict b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/system/bottomAir/decomposeParDict
new file mode 120000
index 0000000000000000000000000000000000000000..46638e60f61f453fde97c51772ad6111792db0f6
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/system/bottomAir/decomposeParDict
@@ -0,0 +1 @@
+../decomposeParDict
\ No newline at end of file
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/system/decomposeParDict b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/system/decomposeParDict
index 747b5114b73dac97b0632688eea1e670ee4bbe30..ce005bfbda0074b53855b8a312ffa3a0a8ad9bd1 100644
--- a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/system/decomposeParDict
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/system/decomposeParDict
@@ -19,30 +19,25 @@ numberOfSubdomains  4;
 //- Keep owner and neighbour on same processor for faces in zones:
 // preserveFaceZones (heater solid1 solid3);
 
-// method          scotch;
-method          hierarchical;
-// method          simple;
-// method          manual;
+method          scotch;
 
-coeffs
+regions
 {
-    n           (2 2 1);
-    //delta       0.001; // default=0.001
-    //order       xyz;   // default=xzy
-    dataFile    "decompositionData";
+    heater
+    {
+        numberOfSubdomains  1;
+        method          simple;
+
+        coeffs
+        {
+            n       (1 1 1);
+        }
+    }
 }
 
-scotchCoeffs
+coeffs
 {
-    //processorWeights
-    //(
-    //    1
-    //    1
-    //    1
-    //    1
-    //);
-    //writeGraph  true;
-    //strategy "b";
+    n       (2 2 1);
 }
 
 // ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/system/heater/changeDictionaryDict b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/system/heater/changeDictionaryDict
index c4321a17982484be3a280c56398310b5b0c3f2a0..94498b92f7bcfa5880b539e994bd2fa1425d4a69 100644
--- a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/system/heater/changeDictionaryDict
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/system/heater/changeDictionaryDict
@@ -41,6 +41,10 @@ T
             type            zeroGradient;
             value           uniform 300;
         }
+        "procBoundary.*"
+        {
+            type            processor;
+        }
         "heater_to_.*"
         {
             type            compressible::turbulentTemperatureCoupledBaffleMixed;
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/system/heater/decomposeParDict b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/system/heater/decomposeParDict
deleted file mode 100644
index 6f60341487a3c0f21b33a99bd257a6d51b459db9..0000000000000000000000000000000000000000
--- a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/system/heater/decomposeParDict
+++ /dev/null
@@ -1,49 +0,0 @@
-/*--------------------------------*- 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      decomposeParDict;
-}
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
-numberOfSubdomains  4;
-
-//- Keep owner and neighbour on same processor for faces in zones:
-// preserveFaceZones (heater solid1 solid3);
-
-method          scotch;
-// method          hierarchical;
-// method          simple;
-// method          manual;
-
-coeffs
-{
-    n           (2 2 1);
-    //delta       0.001; // default=0.001
-    //order       xyz;   // default=xzy
-    dataFile    "decompositionData";
-}
-
-scotchCoeffs
-{
-    //processorWeights
-    //(
-    //    1
-    //    1
-    //    1
-    //    1
-    //);
-    //writeGraph  true;
-    //strategy "b";
-}
-
-
-// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/system/heater/decomposeParDict b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/system/heater/decomposeParDict
new file mode 120000
index 0000000000000000000000000000000000000000..46638e60f61f453fde97c51772ad6111792db0f6
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/system/heater/decomposeParDict
@@ -0,0 +1 @@
+../decomposeParDict
\ No newline at end of file
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/system/leftSolid/changeDictionaryDict b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/system/leftSolid/changeDictionaryDict
index 2984030dad06c8bd3374d166efdc21d4df30e218..ef614f46206cd17e487ed0ce255b0244054e2c08 100644
--- a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/system/leftSolid/changeDictionaryDict
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/system/leftSolid/changeDictionaryDict
@@ -37,6 +37,10 @@ T
             type            zeroGradient;
             value           uniform 300;
         }
+        "procBoundary.*"
+        {
+            type            processor;
+        }
         "leftSolid_to_.*"
         {
             type            compressible::turbulentTemperatureCoupledBaffleMixed;
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/system/rightSolid/changeDictionaryDict b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/system/rightSolid/changeDictionaryDict
index 184cf95c4e8b8fcd75b505e7eb25b5bc48a9f36a..75655492b8d332fbc810be75294926866c4d8532 100644
--- a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/system/rightSolid/changeDictionaryDict
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/system/rightSolid/changeDictionaryDict
@@ -37,6 +37,10 @@ T
             type            zeroGradient;
             value           uniform 300;
         }
+        "procBoundary.*"
+        {
+            type            processor;
+        }
         "rightSolid_to_.*"
         {
             type            compressible::turbulentTemperatureCoupledBaffleMixed;
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/system/topAir/changeDictionaryDict b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/system/topAir/changeDictionaryDict
index 43e06d9940b5842d6e17a02d3c1584b108299242..15b0c768561fdcf2fde34bd40297c0cc4798c6e0 100644
--- a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/system/topAir/changeDictionaryDict
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/system/topAir/changeDictionaryDict
@@ -25,6 +25,10 @@ U
             type            fixedValue;
             value           uniform (0 0 0);
         }
+        "procBoundary.*"
+        {
+            type            processor;
+        }
         minX
         {
             type            fixedValue;
@@ -49,6 +53,10 @@ T
         {
             type            zeroGradient;
         }
+        "procBoundary.*"
+        {
+            type            processor;
+        }
 
         minX
         {
@@ -83,6 +91,10 @@ epsilon
             type            epsilonWallFunction;
             value           uniform 0.01;
         }
+        "procBoundary.*"
+        {
+            type            processor;
+        }
 
         minX
         {
@@ -109,6 +121,10 @@ k
             type            kqRWallFunction;
             value           uniform 0.1;
         }
+        "procBoundary.*"
+        {
+            type            processor;
+        }
 
         minX
         {
@@ -135,6 +151,10 @@ p_rgh
             type            fixedFluxPressure;
             value           uniform 1e5;
         }
+        "procBoundary.*"
+        {
+            type            processor;
+        }
 
         maxX
         {
@@ -155,6 +175,10 @@ p
             type            calculated;
             value           uniform 1e5;
         }
+        "procBoundary.*"
+        {
+            type            processor;
+        }
 
         maxX
         {
diff --git a/wmake/rules/General/general b/wmake/rules/General/general
index bd57f37e2ff48769770af230d81a53a5aab528f0..3ab6290fc9edb1cdec05c37a5ff8d727fc3121bf 100644
--- a/wmake/rules/General/general
+++ b/wmake/rules/General/general
@@ -1,5 +1,5 @@
 #-------------------------------*- makefile -*---------------------------------
-WM_VERSION = OPENFOAM_PLUS=1706
+WM_VERSION = OPENFOAM_PLUS=1712
 
 AR         = ar
 ARFLAGS    = cr