From 3cf177e7592d4aa23f0d1d16d910e3161b02bbbd Mon Sep 17 00:00:00 2001
From: Mark Olesen <mark.olesen@esi-group.com>
Date: Thu, 8 Nov 2018 20:50:47 +0000
Subject: [PATCH] Work-package-09 geometric constraint

---
 .../generation/snappyHexMesh/snappyHexMesh.C  |   1 -
 .../decomposePar/decomposeParDict             |  95 ++++----
 .../surfaceRedistributePar.C                  |   4 +-
 .../meshRefinement/meshRefinement.C           |   1 -
 src/parallel/decompose/decomposition.dox      |  85 ++++---
 .../decompose/decompositionMethods/Make/files |  15 +-
 .../decompositionMethods/Make/options         |   2 +
 .../decompositionConstraint.C                 |  35 ++-
 .../decompositionConstraint.H                 |  37 +--
 .../geometric/geometricConstraint.C           | 226 ++++++++++++++++++
 .../geometric/geometricConstraint.H           | 169 +++++++++++++
 .../preserveBafflesConstraint.C               |  25 +-
 .../preserveBafflesConstraint.H               |  25 +-
 .../preserveFaceZonesConstraint.C             |  21 +-
 .../preserveFaceZonesConstraint.H             |  26 +-
 .../preservePatchesConstraint.C               |  25 +-
 .../preservePatchesConstraint.H               |  25 +-
 .../refinementHistoryConstraint.C             | 102 ++++----
 .../refinementHistoryConstraint.H             |  31 ++-
 .../singleProcessorFaceSetsConstraint.C       | 112 +++++----
 .../singleProcessorFaceSetsConstraint.H       |  56 +++--
 .../decompositionMethod/decompositionMethod.C | 163 ++++++-------
 .../decompositionMethod/decompositionMethod.H |  17 +-
 .../geomDecomp/geomDecomp.C                   |   3 +-
 .../hierarchGeomDecomp/hierarchGeomDecomp.C   |  12 +-
 .../manualDecomp/manualDecomp.C               |  13 +-
 .../manualDecomp/manualDecomp.H               |   7 +-
 .../multiLevelDecomp/multiLevelDecomp.C       |  10 +-
 .../structuredDecomp/structuredDecomp.C       |  17 +-
 .../structuredDecomp/structuredDecomp.H       |   6 +-
 .../decompose/metisDecomp/metisDecomp.C       |   7 +-
 .../geometric/Allclean                        |   9 +
 .../decompositionConstraints/geometric/Allrun |  20 ++
 .../geometric/constant/transportProperties    |  21 ++
 .../geometric/constant/turbulenceProperties   |  28 +++
 .../geometric/system/blockMeshDict            |  86 +++++++
 .../geometric/system/controlDict              |  48 ++++
 .../geometric/system/decomposeConstraints     |  84 +++++++
 .../geometric/system/decomposeParDict         |  34 +++
 .../geometric/system/decomposeParDict.8       |  31 +++
 .../geometric/system/fvSchemes                |  58 +++++
 .../geometric/system/fvSolution               |  92 +++++++
 42 files changed, 1454 insertions(+), 430 deletions(-)
 create mode 100644 src/parallel/decompose/decompositionMethods/decompositionConstraints/geometric/geometricConstraint.C
 create mode 100644 src/parallel/decompose/decompositionMethods/decompositionConstraints/geometric/geometricConstraint.H
 create mode 100755 tutorials/preProcessing/decompositionConstraints/geometric/Allclean
 create mode 100755 tutorials/preProcessing/decompositionConstraints/geometric/Allrun
 create mode 100644 tutorials/preProcessing/decompositionConstraints/geometric/constant/transportProperties
 create mode 100644 tutorials/preProcessing/decompositionConstraints/geometric/constant/turbulenceProperties
 create mode 100644 tutorials/preProcessing/decompositionConstraints/geometric/system/blockMeshDict
 create mode 100644 tutorials/preProcessing/decompositionConstraints/geometric/system/controlDict
 create mode 100644 tutorials/preProcessing/decompositionConstraints/geometric/system/decomposeConstraints
 create mode 100644 tutorials/preProcessing/decompositionConstraints/geometric/system/decomposeParDict
 create mode 100644 tutorials/preProcessing/decompositionConstraints/geometric/system/decomposeParDict.8
 create mode 100644 tutorials/preProcessing/decompositionConstraints/geometric/system/fvSchemes
 create mode 100644 tutorials/preProcessing/decompositionConstraints/geometric/system/fvSolution

diff --git a/applications/utilities/mesh/generation/snappyHexMesh/snappyHexMesh.C b/applications/utilities/mesh/generation/snappyHexMesh/snappyHexMesh.C
index 5a7da19bb7b..61d6f2bb9ae 100644
--- a/applications/utilities/mesh/generation/snappyHexMesh/snappyHexMesh.C
+++ b/applications/utilities/mesh/generation/snappyHexMesh/snappyHexMesh.C
@@ -43,7 +43,6 @@ Description
 #include "refinementFeatures.H"
 #include "shellSurfaces.H"
 #include "decompositionMethod.H"
-#include "noDecomp.H"
 #include "fvMeshDistribute.H"
 #include "wallPolyPatch.H"
 #include "refinementParameters.H"
diff --git a/applications/utilities/parallelProcessing/decomposePar/decomposeParDict b/applications/utilities/parallelProcessing/decomposePar/decomposeParDict
index f1a97ca7cbd..fc0edd941cb 100644
--- a/applications/utilities/parallelProcessing/decomposePar/decomposeParDict
+++ b/applications/utilities/parallelProcessing/decomposePar/decomposeParDict
@@ -183,50 +183,56 @@ structuredCoeffs
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 // Decomposition constraints
 
-//constraints
-//{
-//    preserveBaffles
-//    {
-//        //- Keep owner and neighbour of baffles on same processor (i.e.
-//        // keep it detectable as a baffle). Baffles are two boundary face
-//        // sharing the same points
-//        type    preserveBaffles;
-//    }
-//    preserveFaceZones
-//    {
-//        //- Keep owner and neighbour on same processor for faces in zones
-//        type    preserveFaceZones;
-//        zones   (".*");
-//    }
-//    preservePatches
-//    {
-//        //- Keep owner and neighbour on same processor for faces in patches
-//        //  (only makes sense for cyclic patches. Not suitable for e.g.
-//        //   cyclicAMI since these are not coupled on the patch level. Use
-//        //   singleProcessorFaceSets for those)
-//        type    preservePatches;
-//        patches (".*");
-//    }
-//    singleProcessorFaceSets
-//    {
-//        //- Keep all of faceSet on a single processor. This puts all cells
-//        //  connected with a point, edge or face on the same processor.
-//        //  (just having face connected cells might not guarantee a balanced
-//        //  decomposition)
-//        // The processor can be -1 (the decompositionMethod chooses the
-//        // processor for a good load balance) or explicitly provided (upsets
-//        // balance)
-//        type    singleProcessorFaceSets;
-//        singleProcessorFaceSets ((f1 -1));
-//    }
-//    refinementHistory
-//    {
-//        //- Decompose cells such that all cell originating from single cell
-//        //  end up on same processor
-//        type    refinementHistory;
-//    }
-//}
-
+/*
+constraints
+{
+    baffles
+    {
+        //- Keep owner and neighbour of baffles on same processor (i.e.
+        // keep it detectable as a baffle). Baffles are two boundary face
+        // sharing the same points
+        type    preserveBaffles;
+        enabled false;
+    }
+    faces
+    {
+        //- Keep owner and neighbour on same processor for faces in zones
+        type    preserveFaceZones;
+        zones   (".*");
+        enabled false;
+    }
+    patches
+    {
+        //- Keep owner and neighbour on same processor for faces in patches
+        //  (only makes sense for cyclic patches. Not suitable for e.g.
+        //   cyclicAMI since these are not coupled on the patch level. Use
+        //   singleProcessorFaceSets for those)
+        type    preservePatches;
+        patches (".*");
+        enabled false;
+    }
+    processors
+    {
+        //- Keep all of faceSet on a single processor. This puts all cells
+        //  connected with a point, edge or face on the same processor.
+        //  (just having face connected cells might not guarantee a balanced
+        //  decomposition)
+        // The processor can be -1 (the decompositionMethod chooses the
+        // processor for a good load balance) or explicitly provided (upsets
+        // balance)
+        type    singleProcessorFaceSets;
+        sets    ((f1 -1));
+        enabled false;
+    }
+    refinement
+    {
+        //- Decompose cells such that all cell originating from single cell
+        //  end up on same processor
+        type    refinementHistory;
+        enabled false;
+    }
+}
+*/
 
 // Deprecated form of specifying decomposition constraints:
 //- Keep owner and neighbour on same processor for faces in zones:
@@ -251,5 +257,4 @@ structuredCoeffs
 //  same points.
 //preserveBaffles true;
 
-
 // ************************************************************************* //
diff --git a/applications/utilities/surface/surfaceRedistributePar/surfaceRedistributePar.C b/applications/utilities/surface/surfaceRedistributePar/surfaceRedistributePar.C
index 41a8cd34861..3c2f829aa6b 100644
--- a/applications/utilities/surface/surfaceRedistributePar/surfaceRedistributePar.C
+++ b/applications/utilities/surface/surfaceRedistributePar/surfaceRedistributePar.C
@@ -33,8 +33,8 @@ Description
     processor has all triangles that overlap its mesh.
 
 Note
-    - best decomposition option is hierarchGeomDecomp since
-      guarantees square decompositions.
+    - best decomposition option is hierarchical since it guarantees
+      square decompositions.
     - triangles might be present on multiple processors.
     - merging uses geometric tolerance so take care with writing precision.
 
diff --git a/src/mesh/snappyHexMesh/meshRefinement/meshRefinement.C b/src/mesh/snappyHexMesh/meshRefinement/meshRefinement.C
index 7b49cfa7b55..198f51586fb 100644
--- a/src/mesh/snappyHexMesh/meshRefinement/meshRefinement.C
+++ b/src/mesh/snappyHexMesh/meshRefinement/meshRefinement.C
@@ -49,7 +49,6 @@ License
 #include "globalIndex.H"
 #include "meshTools.H"
 #include "OFstream.H"
-#include "geomDecomp.H"
 #include "Random.H"
 #include "searchableSurfaces.H"
 #include "treeBoundBox.H"
diff --git a/src/parallel/decompose/decomposition.dox b/src/parallel/decompose/decomposition.dox
index 0256b48e4a4..d9622448a5d 100644
--- a/src/parallel/decompose/decomposition.dox
+++ b/src/parallel/decompose/decomposition.dox
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2017 OpenCFD Ltd.
+    \\  /    A nd           | Copyright (C) 2017-2018 OpenCFD Ltd.
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -177,7 +177,7 @@ decomposition is termed a level. For example,
             method  hierarchical;
             coeffs
             {
-                n (16 4 2);
+                n   (16 4 2);
             }
         }
         cpus
@@ -228,53 +228,80 @@ For example,
 \verbatim
     constraints
     {
-        preserveBaffles
+        // Keep owner and neighbour of baffles on same processor
+        // (ie, keep it detectable as a baffle).
+        // Baffles are two boundary face sharing the same points
+        baffles
         {
-            // Keep owner and neighbour of baffles on same processor
-            // (ie, keep it detectable as a baffle).
-            // Baffles are two boundary face sharing the same points
-
             type    preserveBaffles;
+            enabled true;
         }
 
-        preserveFaceZones
+        // Keep owner and neighbour on same processor for faces in zones
+        faces
         {
-            // Keep owner and neighbour on same processor for faces in zones
-
             type    preserveFaceZones;
             zones   (".*");
+            enabled true;
         }
 
-        preservePatches
+        // Keep owner and neighbour on same processor for faces in patches
+        // (only makes sense for cyclic patches. Not suitable for e.g.
+        // cyclicAMI since these are not coupled on the patch level.
+        // Use singleProcessorFaceSets for those.
+        patches
         {
-            // Keep owner and neighbour on same processor for faces in patches
-            // (only makes sense for cyclic patches. Not suitable for e.g.
-            // cyclicAMI since these are not coupled on the patch level.
-            // Use singleProcessorFaceSets for those.
-
             type    preservePatches;
             patches (".*");
+            enabled true;
         }
 
-        singleProcessorFaceSets
+        // Keep all of faceSet on a single processor. This puts all cells
+        // connected with a point, edge or face on the same processor.
+        // (just having face connected cells might not guarantee a balanced
+        // decomposition)
+        // The processor can be -1 (the decompositionMethod chooses the
+        // processor for a good load balance) or explicitly provided (upsets
+        // balance)
+        processors
         {
-            // Keep all of faceSet on a single processor. This puts all cells
-            // connected with a point, edge or face on the same processor.
-            // (just having face connected cells might not guarantee a balanced
-            // decomposition)
-            // The processor can be -1 (the decompositionMethod chooses the
-            // processor for a good load balance) or explicitly provided (upsets
-            // balance)
-
             type    singleProcessorFaceSets;
-            singleProcessorFaceSets ((f1 -1));
+            sets    ((f1 -1));
+            enabled true;
         }
 
-        refinementHistory
+        // Decompose cells such that all cell originating from single cell
+        // end up on same processor
+        refinement
         {
-            // Decompose cells such that all cell originating from single cell
-            // end up on same processor
             type    refinementHistory;
+            enabled true;
+        }
+
+        // Prevent decomposition splitting of the geometric regions
+        // Uses any topoSetFaceSource for selecting the constrained faces
+        geometric
+        {
+            type    geometric;
+
+            grow    false;
+
+            selection
+            {
+                box1
+                {
+                    source  box;
+                    min     (-10 -10 -10);
+                    max     (1 1 1);
+                }
+
+                ball1
+                {
+                    source  sphere;
+                    origin  (-2 -2 1);
+                    radius  1;
+                }
+            }
         }
     }
 \endverbatim
diff --git a/src/parallel/decompose/decompositionMethods/Make/files b/src/parallel/decompose/decompositionMethods/Make/files
index 0bae18c40d6..575366dfaec 100644
--- a/src/parallel/decompose/decompositionMethods/Make/files
+++ b/src/parallel/decompose/decompositionMethods/Make/files
@@ -9,14 +9,15 @@ structuredDecomp/structuredDecomp.C
 noDecomp/noDecomp.C
 
 
-decompositionConstraints = decompositionConstraints
+constraints = decompositionConstraints
 
-$(decompositionConstraints)/decompositionConstraint/decompositionConstraint.C
-$(decompositionConstraints)/preserveBaffles/preserveBafflesConstraint.C
-$(decompositionConstraints)/preserveFaceZones/preserveFaceZonesConstraint.C
-$(decompositionConstraints)/preservePatches/preservePatchesConstraint.C
-$(decompositionConstraints)/singleProcessorFaceSets/singleProcessorFaceSetsConstraint.C
-$(decompositionConstraints)/refinementHistory/refinementHistoryConstraint.C
+$(constraints)/decompositionConstraint/decompositionConstraint.C
+$(constraints)/preserveBaffles/preserveBafflesConstraint.C
+$(constraints)/preserveFaceZones/preserveFaceZonesConstraint.C
+$(constraints)/preservePatches/preservePatchesConstraint.C
+$(constraints)/geometric/geometricConstraint.C
+$(constraints)/singleProcessorFaceSets/singleProcessorFaceSetsConstraint.C
+$(constraints)/refinementHistory/refinementHistoryConstraint.C
 
 
 LIB = $(FOAM_LIBBIN)/libdecompositionMethods
diff --git a/src/parallel/decompose/decompositionMethods/Make/options b/src/parallel/decompose/decompositionMethods/Make/options
index 45133caabbc..487f3df83ab 100644
--- a/src/parallel/decompose/decompositionMethods/Make/options
+++ b/src/parallel/decompose/decompositionMethods/Make/options
@@ -1,9 +1,11 @@
 EXE_INC = \
+    -I$(LIB_SRC)/fileFormats/lnInclude \
     -I$(LIB_SRC)/meshTools/lnInclude \
     -I$(LIB_SRC)/dynamicMesh/lnInclude \
     -I$(LIB_SRC)/finiteVolume/lnInclude
 
 LIB_LIBS = \
+    -lfileFormats \
     -lmeshTools \
     -ldynamicMesh \
     -lfiniteVolume
diff --git a/src/parallel/decompose/decompositionMethods/decompositionConstraints/decompositionConstraint/decompositionConstraint.C b/src/parallel/decompose/decompositionMethods/decompositionConstraints/decompositionConstraint/decompositionConstraint.C
index 3be42dbba3c..eca00bb4068 100644
--- a/src/parallel/decompose/decompositionMethods/decompositionConstraints/decompositionConstraint/decompositionConstraint.C
+++ b/src/parallel/decompose/decompositionMethods/decompositionConstraints/decompositionConstraint/decompositionConstraint.C
@@ -37,16 +37,39 @@ namespace Foam
 
 Foam::decompositionConstraint::decompositionConstraint
 (
-    const dictionary& constraintsDict,
-    const word& type
+    const dictionary& constraintDict
 )
 :
-    coeffDict_(constraintsDict)
+    coeffDict_(constraintDict)
+{}
+
+
+Foam::decompositionConstraint::decompositionConstraint
+(
+    const dictionary& constraintDict,
+    const word&
+)
+:
+    coeffDict_(constraintDict)
 {}
 
 
 // * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * * //
 
+Foam::autoPtr<Foam::decompositionConstraint>
+Foam::decompositionConstraint::New
+(
+    const dictionary& dict
+)
+{
+    return decompositionConstraint::New
+    (
+        dict,
+        dict.get<word>("type")
+    );
+}
+
+
 Foam::autoPtr<Foam::decompositionConstraint>
 Foam::decompositionConstraint::New
 (
@@ -61,14 +84,14 @@ Foam::decompositionConstraint::New
     if (!cstrIter.found())
     {
         FatalIOErrorInFunction(dict)
-            << "Unknown decompositionConstraint type "
+            << "Unknown decompositionConstraint: "
             << modelType << nl << nl
-            << "Valid decompositionConstraint types :" << endl
+            << "Valid types:" << nl
             << dictionaryConstructorTablePtr_->sortedToc()
             << exit(FatalIOError);
     }
 
-    return autoPtr<decompositionConstraint>(cstrIter()(dict, modelType));
+    return autoPtr<decompositionConstraint>(cstrIter()(dict));
 }
 
 
diff --git a/src/parallel/decompose/decompositionMethods/decompositionConstraints/decompositionConstraint/decompositionConstraint.H b/src/parallel/decompose/decompositionMethods/decompositionConstraints/decompositionConstraint/decompositionConstraint.H
index 58ad56379db..a1e8b75b150 100644
--- a/src/parallel/decompose/decompositionMethods/decompositionConstraints/decompositionConstraint/decompositionConstraint.H
+++ b/src/parallel/decompose/decompositionMethods/decompositionConstraints/decompositionConstraint/decompositionConstraint.H
@@ -25,6 +25,7 @@ Class
     Foam::decompositionConstraint
 
 Description
+    Abstract class for handling decomposition constraints.
 
 SourceFiles
     decompositionConstraint.C
@@ -35,10 +36,10 @@ SourceFiles
 #define decompositionConstraint_H
 
 #include "dictionary.H"
-#include "runTimeSelectionTables.H"
 #include "boolList.H"
 #include "labelList.H"
 #include "labelPair.H"
+#include "runTimeSelectionTables.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
@@ -58,12 +59,11 @@ protected:
 
     // Protected data
 
-        //- Model coefficients dictionary
+        //- Constraint coefficients dictionary
         dictionary coeffDict_;
 
-private:
 
-    // Private Member Functions
+    // Protected Member Functions
 
         //- No copy construct
         decompositionConstraint(const decompositionConstraint&) = delete;
@@ -71,7 +71,6 @@ private:
         //- No copy assignment
         void operator=(const decompositionConstraint&) = delete;
 
-
 public:
 
     //- Runtime type information
@@ -86,20 +85,24 @@ public:
             decompositionConstraint,
             dictionary,
             (
-                const dictionary& constraintsDict,
-                const word& type
+                const dictionary& dict
             ),
-            (constraintsDict, type)
+            (dict)
         );
 
 
     // Constructors
 
-        //- Construct with generic dictionary with optional entry for type
+        //- Construct with constraint dictionary
+        explicit decompositionConstraint(const dictionary& constraintDict);
+
+        //- Construct with constraint dictionary and model type.
+        //  The model type could be used for defining a coefficients
+        //  sub-dictionary.
         decompositionConstraint
         (
-            const dictionary& constraintsDict,
-            const word& type
+            const dictionary& constraintDict,
+            const word& modelType
         );
 
 
@@ -108,8 +111,14 @@ public:
         //- Return a reference to the selected decompositionConstraint
         static autoPtr<decompositionConstraint> New
         (
-            const dictionary& constraintsDict,
-            const word& type
+            const dictionary& constraintDict
+        );
+
+        //- Return a reference to the selected decompositionConstraint
+        static autoPtr<decompositionConstraint> New
+        (
+            const dictionary& constraintDict,
+            const word& modelType
         );
 
 
@@ -119,7 +128,7 @@ public:
 
     // Member Functions
 
-        //- Add my constraints to list of constraints
+        //- Add this constraint to list of constraints
         virtual void add
         (
             const polyMesh& mesh,
diff --git a/src/parallel/decompose/decompositionMethods/decompositionConstraints/geometric/geometricConstraint.C b/src/parallel/decompose/decompositionMethods/decompositionConstraints/geometric/geometricConstraint.C
new file mode 100644
index 00000000000..98b6af9c352
--- /dev/null
+++ b/src/parallel/decompose/decompositionMethods/decompositionConstraints/geometric/geometricConstraint.C
@@ -0,0 +1,226 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2018 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 "geometricConstraint.H"
+#include "addToRunTimeSelectionTable.H"
+#include "syncTools.H"
+#include "polyMesh.H"
+#include "Time.H"
+#include "BitOps.H"
+#include "faceBoolSet.H"
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+namespace Foam
+{
+namespace decompositionConstraints
+{
+    defineTypeName(geometric);
+
+    addToRunTimeSelectionTable
+    (
+        decompositionConstraint,
+        geometric,
+        dictionary
+    );
+}
+}
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::decompositionConstraints::geometric::geometric
+(
+    const dictionary& dict
+)
+:
+    decompositionConstraint(dict, typeName),
+    sources_(),
+    selection_(coeffDict_.subDict("selection")),
+    grow_(dict.lookupOrDefault<bool>("grow", false))
+{
+    // Stored as dictionary, since we do not have the mesh at this stage
+
+    if (decompositionConstraint::debug)
+    {
+        Info<< type()
+            << " : adding " << selection_.size()
+            << " geometric constraints for faces" << endl;
+    }
+}
+
+
+Foam::decompositionConstraints::geometric::geometric
+(
+    PtrList<topoSetFaceSource>&& selections
+)
+:
+    decompositionConstraint(dictionary(), typeName),
+    sources_(std::move(selections)),
+    selection_(),
+    grow_(false)
+{
+    if (decompositionConstraint::debug)
+    {
+        Info<< type()
+            << " : adding " << sources_.size()
+            << " geometric constraints for faces" << endl;
+    }
+}
+
+
+// * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * * //
+
+void Foam::decompositionConstraints::geometric::add
+(
+    const polyMesh& mesh,
+    boolList& blockedFace,
+    PtrList<labelList>& specifiedProcessorFaces,
+    labelList& specifiedProcessor,
+    List<labelPair>& explicitConnections
+) const
+{
+    const label nFaces = mesh.nFaces();
+
+    blockedFace.resize(nFaces, true);
+
+    label nchanged = 0;
+    if (decompositionConstraint::debug)
+    {
+        nchanged = BitOps::count(blockedFace, false);
+    }
+
+    // Modify via topoSetFaceSource
+    faceBoolSet facesToBlock(mesh, std::move(blockedFace));
+
+    for (const topoSetFaceSource& source : sources_)
+    {
+        // source.verbose(false);
+        source.applyToSet(topoSetSource::SUBTRACT, facesToBlock);
+    }
+
+    for (const entry& dEntry : selection_)
+    {
+        if (!dEntry.isDict())
+        {
+            WarningInFunction
+                << "Ignoring non-dictionary entry "
+                << dEntry << endl;
+            continue;
+        }
+
+        const dictionary& spec = dEntry.dict();
+
+        auto source = topoSetFaceSource::New
+        (
+            spec.get<word>("source"),
+            mesh,
+            spec.optionalSubDict("sourceInfo")
+        );
+        // source->verbose(false);
+
+        source->applyToSet(topoSetSource::SUBTRACT, facesToBlock);
+    }
+
+
+    // Finished with topo changes
+    blockedFace.transfer(facesToBlock.addressing());
+
+    if (decompositionConstraint::debug)
+    {
+        nchanged = BitOps::count(blockedFace, false) - nchanged;
+    }
+    else
+    {
+        nchanged = 0;
+    }
+
+    // Grow mode.
+    // Include the faces of cells for which there are already two
+    // or more faces in a constraint.
+    if (grow_)
+    {
+        bitSet moreUnblocking(nFaces, false);
+
+        label nUnblocked = 0;
+
+        for (label celli=0; celli < mesh.nCells(); ++celli)
+        {
+            const cell& cFaces = mesh.cells()[celli];
+
+            nUnblocked = 0;
+            for (const label facei : cFaces)
+            {
+                if (!blockedFace[facei])
+                {
+                    ++nUnblocked;
+                    if (nUnblocked > 2)
+                    {
+                        break;
+                    }
+                }
+            }
+
+            if (nUnblocked > 2)
+            {
+                moreUnblocking.set(cFaces);
+            }
+        }
+
+        nUnblocked = 0;
+
+        for (label facei : moreUnblocking)
+        {
+            if (blockedFace[facei])
+            {
+                blockedFace[facei] = false;
+                ++nUnblocked;
+            }
+        }
+
+        if (decompositionConstraint::debug)
+        {
+            Info<< type()
+                << " : geometric constraint grow added "
+                << returnReduce(nUnblocked, sumOp<label>())
+                <<" faces" << endl;
+        }
+
+        // Include in the total
+        nchanged += nUnblocked;
+    }
+
+    if (decompositionConstraint::debug)
+    {
+        Info<< type()
+            << " : geometric constraint added for "
+            << returnReduce(nchanged, sumOp<label>())
+            <<" faces" << endl;
+    }
+
+    syncTools::syncFaceList(mesh, blockedFace, andEqOp<bool>());
+}
+
+
+// ************************************************************************* //
diff --git a/src/parallel/decompose/decompositionMethods/decompositionConstraints/geometric/geometricConstraint.H b/src/parallel/decompose/decompositionMethods/decompositionConstraints/geometric/geometricConstraint.H
new file mode 100644
index 00000000000..b6346f01b50
--- /dev/null
+++ b/src/parallel/decompose/decompositionMethods/decompositionConstraints/geometric/geometricConstraint.H
@@ -0,0 +1,169 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2018 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::decompositionConstraints::geometric
+
+Description
+    Keep faces together based on geometric considerations from a
+    searchableSurfaces list.
+    The faces inside of each searchableSurface are to be kept together
+    during the decomposition.
+
+    \verbatim
+    constraints
+    {
+        geom1
+        {
+            type    geometric;
+
+            grow    false;
+
+            selection
+            {
+                box1
+                {
+                    source  box;
+                    min     (-0.1 -0.01 -0.1);
+                    max     (0.1 0.30 0.1);
+                }
+                ball
+                {
+                    source  sphere;
+                    origin  (-0.1 -0.01 -0.1);
+                    radius  0.25;
+                }
+                blob
+                {
+                    source      surface;
+                    surfaceType triSurfaceMesh;
+                    surfaceName blob.obj;
+                }
+            }
+        }
+    }
+    \endverbatim
+
+    \heading Dictionary parameters
+    \table
+        Property    | Description                           | Required | Default
+        type        | geometric                             | yes |
+        grow        | Grow cells with partial connectivity  | no  | false
+        geometry    | Dictionary of enclosing volumes       | yes |
+    \endtable
+
+Note
+    The searchableSurface must describe a closed volume.
+    Ie, its hasVolumeType() method must be true.
+
+    The selection of enclosing volumes is treated as an OR operation.
+
+    The "grow" mode includes an additional check to include cell faces
+    for any cell that already has two or more of its faces "unblocked".
+    This could indicate a connection over a corner, but does not distinguish
+    between connectivity introduced by the constraint and the connectivity
+    defined by other constraints.
+
+SourceFiles
+    geometricConstraint.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef geometricConstraint_H
+#define geometricConstraint_H
+
+#include "decompositionConstraint.H"
+#include "PtrList.H"
+#include "topoSetFaceSource.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+namespace decompositionConstraints
+{
+
+/*---------------------------------------------------------------------------*\
+                          Class geometric Declaration
+\*---------------------------------------------------------------------------*/
+
+class geometric
+:
+    public decompositionConstraint
+{
+    // Private data
+
+        //- Face selections as topoSetFaceSource
+        PtrList<topoSetFaceSource> sources_;
+
+        //- Dictionary of face selections for topoSetFaceSource
+        dictionary selection_;
+
+        //- Additional check of cell connection (via corners?)
+        bool grow_;
+
+
+public:
+
+    //- Runtime type information
+    TypeName("geometric");
+
+
+    // Constructors
+
+        //- Construct with constraint dictionary
+        explicit geometric(const dictionary& dict);
+
+        //- Move construct from components.
+        //  (topoSetFaceSource cannot be cloned)
+        explicit geometric(PtrList<topoSetFaceSource>&& selections);
+
+
+    //- Destructor
+    virtual ~geometric() = default;
+
+
+    // Member Functions
+
+        //- Add this constraint to list of constraints
+        virtual void add
+        (
+            const polyMesh& mesh,
+            boolList& blockedFace,
+            PtrList<labelList>& specifiedProcessorFaces,
+            labelList& specifiedProcessor,
+            List<labelPair>& explicitConnections
+        ) const;
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace decompositionConstraints
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/parallel/decompose/decompositionMethods/decompositionConstraints/preserveBaffles/preserveBafflesConstraint.C b/src/parallel/decompose/decompositionMethods/decompositionConstraints/preserveBaffles/preserveBafflesConstraint.C
index 06c5f3e97ac..4851760d807 100644
--- a/src/parallel/decompose/decompositionMethods/decompositionConstraints/preserveBaffles/preserveBafflesConstraint.C
+++ b/src/parallel/decompose/decompositionMethods/decompositionConstraints/preserveBaffles/preserveBafflesConstraint.C
@@ -34,12 +34,12 @@ namespace Foam
 {
 namespace decompositionConstraints
 {
-    defineTypeName(preserveBafflesConstraint);
+    defineTypeName(preserveBaffles);
 
     addToRunTimeSelectionTable
     (
         decompositionConstraint,
-        preserveBafflesConstraint,
+        preserveBaffles,
         dictionary
     );
 }
@@ -48,32 +48,31 @@ namespace decompositionConstraints
 
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
-Foam::decompositionConstraints::preserveBafflesConstraint::
-preserveBafflesConstraint
+Foam::decompositionConstraints::preserveBaffles::preserveBaffles
 (
-    const dictionary& constraintsDict,
-    const word& modelType
+    const dictionary& dict
 )
 :
-    decompositionConstraint(constraintsDict, typeName)
+    decompositionConstraint(dict, typeName)
 {
     if (decompositionConstraint::debug)
     {
-        Info<< type() << " : setting constraints to preserve baffles"
+        Info<< type()
+            << " : setting constraints to preserve baffles"
             //<< returnReduce(bafflePairs.size(), sumOp<label>())
             << endl;
     }
 }
 
 
-Foam::decompositionConstraints::preserveBafflesConstraint::
-preserveBafflesConstraint()
+Foam::decompositionConstraints::preserveBaffles::preserveBaffles()
 :
     decompositionConstraint(dictionary(), typeName)
 {
     if (decompositionConstraint::debug)
     {
-        Info<< type() << " : setting constraints to preserve baffles"
+        Info<< type()
+            << " : setting constraints to preserve baffles"
             //<< returnReduce(bafflePairs.size(), sumOp<label>())
             << endl;
     }
@@ -82,7 +81,7 @@ preserveBafflesConstraint()
 
 // * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * * //
 
-void Foam::decompositionConstraints::preserveBafflesConstraint::add
+void Foam::decompositionConstraints::preserveBaffles::add
 (
     const polyMesh& mesh,
     boolList& blockedFace,
@@ -177,7 +176,7 @@ void Foam::decompositionConstraints::preserveBafflesConstraint::add
 }
 
 
-void Foam::decompositionConstraints::preserveBafflesConstraint::apply
+void Foam::decompositionConstraints::preserveBaffles::apply
 (
     const polyMesh& mesh,
     const boolList& blockedFace,
diff --git a/src/parallel/decompose/decompositionMethods/decompositionConstraints/preserveBaffles/preserveBafflesConstraint.H b/src/parallel/decompose/decompositionMethods/decompositionConstraints/preserveBaffles/preserveBafflesConstraint.H
index 3fa49b00f13..8c10c7ff6c0 100644
--- a/src/parallel/decompose/decompositionMethods/decompositionConstraints/preserveBaffles/preserveBafflesConstraint.H
+++ b/src/parallel/decompose/decompositionMethods/decompositionConstraints/preserveBaffles/preserveBafflesConstraint.H
@@ -22,11 +22,17 @@ License
     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
 
 Class
-    Foam::preserveBafflesConstraint
+    Foam::decompositionConstraints::preserveBaffles
 
 Description
     Detects baffles and keeps owner and neighbour on same processor.
 
+    \heading Dictionary parameters
+    \table
+        Property    | Description                       | Required  | Default
+        type        | preserveBaffles                   | yes   |
+    \endtable
+
 SourceFiles
     preserveBafflesConstraint.C
 
@@ -41,15 +47,14 @@ SourceFiles
 
 namespace Foam
 {
-
 namespace decompositionConstraints
 {
 
 /*---------------------------------------------------------------------------*\
-                Class preserveBafflesConstraint Declaration
+                       Class preserveBaffles Declaration
 \*---------------------------------------------------------------------------*/
 
-class preserveBafflesConstraint
+class preserveBaffles
 :
     public decompositionConstraint
 {
@@ -61,19 +66,15 @@ public:
 
     // Constructors
 
-        //- Construct with generic dictionary with optional entry for type
-        preserveBafflesConstraint
-        (
-            const dictionary& constraintsDict,
-            const word& type
-        );
+        //- Construct with constraint dictionary
+        explicit preserveBaffles(const dictionary& dict);
 
         //- Construct from components
-        preserveBafflesConstraint();
+        preserveBaffles();
 
 
     //- Destructor
-    virtual ~preserveBafflesConstraint() = default;
+    virtual ~preserveBaffles() = default;
 
 
     // Member Functions
diff --git a/src/parallel/decompose/decompositionMethods/decompositionConstraints/preserveFaceZones/preserveFaceZonesConstraint.C b/src/parallel/decompose/decompositionMethods/decompositionConstraints/preserveFaceZones/preserveFaceZonesConstraint.C
index 79c2400658b..cc5c495a64b 100644
--- a/src/parallel/decompose/decompositionMethods/decompositionConstraints/preserveFaceZones/preserveFaceZonesConstraint.C
+++ b/src/parallel/decompose/decompositionMethods/decompositionConstraints/preserveFaceZones/preserveFaceZonesConstraint.C
@@ -33,12 +33,12 @@ namespace Foam
 {
 namespace decompositionConstraints
 {
-    defineTypeName(preserveFaceZonesConstraint);
+    defineTypeName(preserveFaceZones);
 
     addToRunTimeSelectionTable
     (
         decompositionConstraint,
-        preserveFaceZonesConstraint,
+        preserveFaceZones,
         dictionary
     );
 }
@@ -47,15 +47,13 @@ namespace decompositionConstraints
 
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
-Foam::decompositionConstraints::preserveFaceZonesConstraint::
-preserveFaceZonesConstraint
+Foam::decompositionConstraints::preserveFaceZones::preserveFaceZones
 (
-    const dictionary& constraintsDict,
-    const word& modelType
+    const dictionary& dict
 )
 :
-    decompositionConstraint(constraintsDict, typeName),
-    zones_(coeffDict_.lookup("zones"))
+    decompositionConstraint(dict, typeName),
+    zones_(coeffDict_.get<wordRes>("zones"))
 {
     if (decompositionConstraint::debug)
     {
@@ -66,8 +64,7 @@ preserveFaceZonesConstraint
 }
 
 
-Foam::decompositionConstraints::preserveFaceZonesConstraint::
-preserveFaceZonesConstraint
+Foam::decompositionConstraints::preserveFaceZones::preserveFaceZones
 (
     const UList<wordRe>& zones
 )
@@ -86,7 +83,7 @@ preserveFaceZonesConstraint
 
 // * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * * //
 
-void Foam::decompositionConstraints::preserveFaceZonesConstraint::add
+void Foam::decompositionConstraints::preserveFaceZones::add
 (
     const polyMesh& mesh,
     boolList& blockedFace,
@@ -127,7 +124,7 @@ void Foam::decompositionConstraints::preserveFaceZonesConstraint::add
 }
 
 
-void Foam::decompositionConstraints::preserveFaceZonesConstraint::apply
+void Foam::decompositionConstraints::preserveFaceZones::apply
 (
     const polyMesh& mesh,
     const boolList& blockedFace,
diff --git a/src/parallel/decompose/decompositionMethods/decompositionConstraints/preserveFaceZones/preserveFaceZonesConstraint.H b/src/parallel/decompose/decompositionMethods/decompositionConstraints/preserveFaceZones/preserveFaceZonesConstraint.H
index d274d17b187..8deed167f8a 100644
--- a/src/parallel/decompose/decompositionMethods/decompositionConstraints/preserveFaceZones/preserveFaceZonesConstraint.H
+++ b/src/parallel/decompose/decompositionMethods/decompositionConstraints/preserveFaceZones/preserveFaceZonesConstraint.H
@@ -22,12 +22,19 @@ License
     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
 
 Class
-    Foam::preserveFaceZonesConstraint
+    Foam::decompositionConstraints::preserveFaceZones
 
 Description
     Constraint to keep/move owner and neighbour of faceZone onto same
     processor.
 
+    \heading Dictionary parameters
+    \table
+        Property    | Description                       | Required  | Default
+        type        | preserveFaceZones                 | yes   |
+        zones       | List of face zone names or regexs | yes   |
+    \endtable
+
 SourceFiles
     preserveFaceZonesConstraint.C
 
@@ -43,15 +50,14 @@ SourceFiles
 
 namespace Foam
 {
-
 namespace decompositionConstraints
 {
 
 /*---------------------------------------------------------------------------*\
-                Class preserveFaceZonesConstraint Declaration
+                      Class preserveFaceZones Declaration
 \*---------------------------------------------------------------------------*/
 
-class preserveFaceZonesConstraint
+class preserveFaceZones
 :
     public decompositionConstraint
 {
@@ -69,19 +75,15 @@ public:
 
     // Constructors
 
-        //- Construct with generic dictionary with optional entry for type
-        preserveFaceZonesConstraint
-        (
-            const dictionary& constraintsDict,
-            const word& type
-        );
+        //- Construct with constraint dictionary
+        explicit preserveFaceZones(const dictionary& dict);
 
         //- Construct from components
-        preserveFaceZonesConstraint(const UList<wordRe>& zones);
+        explicit preserveFaceZones(const UList<wordRe>& zones);
 
 
     //- Destructor
-    virtual ~preserveFaceZonesConstraint() = default;
+    virtual ~preserveFaceZones() = default;
 
 
     // Member Functions
diff --git a/src/parallel/decompose/decompositionMethods/decompositionConstraints/preservePatches/preservePatchesConstraint.C b/src/parallel/decompose/decompositionMethods/decompositionConstraints/preservePatches/preservePatchesConstraint.C
index 35130948488..9fc432e54e4 100644
--- a/src/parallel/decompose/decompositionMethods/decompositionConstraints/preservePatches/preservePatchesConstraint.C
+++ b/src/parallel/decompose/decompositionMethods/decompositionConstraints/preservePatches/preservePatchesConstraint.C
@@ -33,12 +33,12 @@ namespace Foam
 {
 namespace decompositionConstraints
 {
-    defineTypeName(preservePatchesConstraint);
+    defineTypeName(preservePatches);
 
     addToRunTimeSelectionTable
     (
         decompositionConstraint,
-        preservePatchesConstraint,
+        preservePatches,
         dictionary
     );
 }
@@ -47,15 +47,13 @@ namespace decompositionConstraints
 
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
-Foam::decompositionConstraints::preservePatchesConstraint::
-preservePatchesConstraint
+Foam::decompositionConstraints::preservePatches::preservePatches
 (
-    const dictionary& constraintsDict,
-    const word& modelType
+    const dictionary& dict
 )
 :
-    decompositionConstraint(constraintsDict, typeName),
-    patches_(coeffDict_.lookup("patches"))
+    decompositionConstraint(dict, typeName),
+    patches_(coeffDict_.get<wordRes>("patches"))
 {
     if (decompositionConstraint::debug)
     {
@@ -66,8 +64,7 @@ preservePatchesConstraint
 }
 
 
-Foam::decompositionConstraints::preservePatchesConstraint::
-preservePatchesConstraint
+Foam::decompositionConstraints::preservePatches::preservePatches
 (
     const UList<wordRe>& patches
 )
@@ -86,7 +83,7 @@ preservePatchesConstraint
 
 // * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * * //
 
-void Foam::decompositionConstraints::preservePatchesConstraint::add
+void Foam::decompositionConstraints::preservePatches::add
 (
     const polyMesh& mesh,
     boolList& blockedFace,
@@ -97,7 +94,7 @@ void Foam::decompositionConstraints::preservePatchesConstraint::add
 {
     const polyBoundaryMesh& pbm = mesh.boundaryMesh();
 
-    blockedFace.setSize(mesh.nFaces(), true);
+    blockedFace.resize(mesh.nFaces(), true);
 
     const labelList patchIDs(pbm.patchSet(patches_).sortedToc());
 
@@ -129,7 +126,7 @@ void Foam::decompositionConstraints::preservePatchesConstraint::add
 }
 
 
-void Foam::decompositionConstraints::preservePatchesConstraint::apply
+void Foam::decompositionConstraints::preservePatches::apply
 (
     const polyMesh& mesh,
     const boolList& blockedFace,
@@ -177,7 +174,7 @@ void Foam::decompositionConstraints::preservePatchesConstraint::apply
 
         forAll(faceCells, i)
         {
-            label bFaceI = pp.start()+i-mesh.nInternalFaces();
+            const label bFaceI = pp.start()+i-mesh.nInternalFaces();
 
             if (decomposition[faceCells[i]] != destProc[bFaceI])
             {
diff --git a/src/parallel/decompose/decompositionMethods/decompositionConstraints/preservePatches/preservePatchesConstraint.H b/src/parallel/decompose/decompositionMethods/decompositionConstraints/preservePatches/preservePatchesConstraint.H
index 8a6a5fe595c..37caeb1291c 100644
--- a/src/parallel/decompose/decompositionMethods/decompositionConstraints/preservePatches/preservePatchesConstraint.H
+++ b/src/parallel/decompose/decompositionMethods/decompositionConstraints/preservePatches/preservePatchesConstraint.H
@@ -22,12 +22,19 @@ License
     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
 
 Class
-    Foam::preservePatchesConstraint
+    Foam::decompositionConstraints::preservePatches
 
 Description
     Constraint to keep owner and neighbour of (cyclic) patch on same
     processor.
 
+    \heading Dictionary parameters
+    \table
+        Property    | Description                       | Required  | Default
+        type        | preservePatches                   | yes   |
+        patches     | List of patch names or regexs     | yes   |
+    \endtable
+
 SourceFiles
     preservePatchesConstraint.C
 
@@ -48,10 +55,10 @@ namespace decompositionConstraints
 {
 
 /*---------------------------------------------------------------------------*\
-                  Class preservePatchesConstraint Declaration
+                       Class preservePatches Declaration
 \*---------------------------------------------------------------------------*/
 
-class preservePatchesConstraint
+class preservePatches
 :
     public decompositionConstraint
 {
@@ -69,19 +76,15 @@ public:
 
     // Constructors
 
-        //- Construct with generic dictionary with optional entry for type
-        preservePatchesConstraint
-        (
-            const dictionary& constraintsDict,
-            const word& type
-        );
+        //- Construct with constraint dictionary
+        explicit preservePatches(const dictionary& dict);
 
         //- Construct from components
-        preservePatchesConstraint(const UList<wordRe>& patches);
+        explicit preservePatches(const UList<wordRe>& patches);
 
 
     //- Destructor
-    virtual ~preservePatchesConstraint() = default;
+    virtual ~preservePatches() = default;
 
 
     // Member Functions
diff --git a/src/parallel/decompose/decompositionMethods/decompositionConstraints/refinementHistory/refinementHistoryConstraint.C b/src/parallel/decompose/decompositionMethods/decompositionConstraints/refinementHistory/refinementHistoryConstraint.C
index ebdb9f641db..a4de20b748c 100644
--- a/src/parallel/decompose/decompositionMethods/decompositionConstraints/refinementHistory/refinementHistoryConstraint.C
+++ b/src/parallel/decompose/decompositionMethods/decompositionConstraints/refinementHistory/refinementHistoryConstraint.C
@@ -32,50 +32,52 @@ License
 
 namespace Foam
 {
-    defineTypeName(refinementHistoryConstraint);
+namespace decompositionConstraints
+{
+    defineTypeName(refinementHistory);
 
     addToRunTimeSelectionTable
     (
         decompositionConstraint,
-        refinementHistoryConstraint,
+        refinementHistory,
         dictionary
     );
 }
+}
 
 
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
-Foam::refinementHistoryConstraint::refinementHistoryConstraint
+Foam::decompositionConstraints::refinementHistory::refinementHistory
 (
-    const dictionary& constraintsDict,
-    const word& modelType
+    const dictionary& dict
 )
 :
-    decompositionConstraint(constraintsDict, typeName)
+    decompositionConstraint(dict, typeName)
 {
     if (decompositionConstraint::debug)
     {
-        Info<< type() << " : setting constraints to refinement history"
-            << endl;
+        Info<< type()
+            << " : setting constraints to refinement history" << endl;
     }
 }
 
 
-Foam::refinementHistoryConstraint::refinementHistoryConstraint()
+Foam::decompositionConstraints::refinementHistory::refinementHistory()
 :
     decompositionConstraint(dictionary(), typeName)
 {
     if (decompositionConstraint::debug)
     {
-        Info<< type() << " : setting constraints to refinement history"
-            << endl;
+        Info<< type()
+            << " : setting constraints to refinement history" << endl;
     }
 }
 
 
 // * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * * //
 
-void Foam::refinementHistoryConstraint::add
+void Foam::decompositionConstraints::refinementHistory::add
 (
     const polyMesh& mesh,
     boolList& blockedFace,
@@ -84,16 +86,33 @@ void Foam::refinementHistoryConstraint::add
     List<labelPair>& explicitConnections
 ) const
 {
-    const refinementHistory* refPtr =
-        mesh.findObject<refinementHistory>("refinementHistory");
+    // The refinement history type
+    typedef ::Foam::refinementHistory HistoryType;
 
-    autoPtr<const refinementHistory> storagePtr;
+    // Local storage if read from file
+    autoPtr<const HistoryType> readFromFile;
 
-    if (!refPtr)
+    const HistoryType* historyPtr =
+        mesh.findObject<HistoryType>("refinementHistory");
+
+    if (historyPtr)
+    {
+        if (decompositionConstraint::debug)
+        {
+            Info<< type() << " : found refinementHistory" << endl;
+        }
+    }
+    else
     {
-        storagePtr.reset
+        if (decompositionConstraint::debug)
+        {
+            Info<< type() << " : reading refinementHistory from time "
+                << mesh.facesInstance() << endl;
+        }
+
+        readFromFile.reset
         (
-            new refinementHistory
+            new HistoryType
             (
                 IOobject
                 (
@@ -107,27 +126,11 @@ void Foam::refinementHistoryConstraint::add
                 mesh.nCells()
             )
         );
-    }
 
-    if (decompositionConstraint::debug)
-    {
-        if (refPtr)
-        {
-            Info<< type() << " : found refinementHistory" << nl;
-        }
-        else
-        {
-            Info<< type() << " : reading refinementHistory from time "
-                << mesh.facesInstance() << nl;
-        }
+        historyPtr = readFromFile.get();  // get(), not release()
     }
 
-    const refinementHistory& history =
-    (
-        storagePtr.valid()
-      ? *storagePtr
-      : *refPtr
-    );
+    const auto& history = *historyPtr;
 
     if (history.active())
     {
@@ -143,7 +146,7 @@ void Foam::refinementHistoryConstraint::add
 }
 
 
-void Foam::refinementHistoryConstraint::apply
+void Foam::decompositionConstraints::refinementHistory::apply
 (
     const polyMesh& mesh,
     const boolList& blockedFace,
@@ -153,16 +156,20 @@ void Foam::refinementHistoryConstraint::apply
     labelList& decomposition
 ) const
 {
-    const refinementHistory* refPtr =
-        mesh.findObject<refinementHistory>("refinementHistory");
+    // The refinement history type
+    typedef ::Foam::refinementHistory HistoryType;
+
+    // Local storage if read from file
+    autoPtr<const HistoryType> readFromFile;
 
-    autoPtr<const refinementHistory> storagePtr;
+    const HistoryType* historyPtr =
+        mesh.findObject<HistoryType>("refinementHistory");
 
-    if (!refPtr)
+    if (!historyPtr)
     {
-        storagePtr.reset
+        readFromFile.reset
         (
-            new refinementHistory
+            new HistoryType
             (
                 IOobject
                 (
@@ -176,14 +183,11 @@ void Foam::refinementHistoryConstraint::apply
                 mesh.nCells()
             )
         );
+
+        historyPtr = readFromFile.get();  // get(), not release()
     }
 
-    const refinementHistory& history =
-    (
-        storagePtr.valid()
-      ? *storagePtr
-      : *refPtr
-    );
+    const auto& history = *historyPtr;
 
     if (history.active())
     {
diff --git a/src/parallel/decompose/decompositionMethods/decompositionConstraints/refinementHistory/refinementHistoryConstraint.H b/src/parallel/decompose/decompositionMethods/decompositionConstraints/refinementHistory/refinementHistoryConstraint.H
index d544ed8eb96..da6af22f553 100644
--- a/src/parallel/decompose/decompositionMethods/decompositionConstraints/refinementHistory/refinementHistoryConstraint.H
+++ b/src/parallel/decompose/decompositionMethods/decompositionConstraints/refinementHistory/refinementHistoryConstraint.H
@@ -22,12 +22,18 @@ License
     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
 
 Class
-    Foam::refinementHistoryConstraint
+    Foam::decompositionConstraints::refinementHistory
 
 Description
     Constraint to keep all cells originating from refining the same cell
     onto the same processor. Reads polyMesh/refinementHistory.
 
+    \heading Dictionary parameters
+    \table
+        Property    | Description                       | Required  | Default
+        type        | refinementHistory                 | yes   |
+    \endtable
+
 SourceFiles
     refinementHistoryConstraint.C
 
@@ -42,12 +48,14 @@ SourceFiles
 
 namespace Foam
 {
+namespace decompositionConstraints
+{
 
 /*---------------------------------------------------------------------------*\
-                Class refinementHistoryConstraint Declaration
+                      Class refinementHistory Declaration
 \*---------------------------------------------------------------------------*/
 
-class refinementHistoryConstraint
+class refinementHistory
 :
     public decompositionConstraint
 {
@@ -59,24 +67,20 @@ public:
 
     // Constructors
 
-        //- Construct with generic dictionary with optional entry for type
-        refinementHistoryConstraint
-        (
-            const dictionary& constraintsDict,
-            const word& type
-        );
+        //- Construct with constraint dictionary
+        explicit refinementHistory(const dictionary& dict);
 
         //- Construct from components
-        refinementHistoryConstraint();
+        refinementHistory();
 
 
     //- Destructor
-    virtual ~refinementHistoryConstraint() = default;
+    virtual ~refinementHistory() = default;
 
 
     // Member Functions
 
-        //- Add my constraints to list of constraints
+        //- Add this constraint to list of constraints
         virtual void add
         (
             const polyMesh& mesh,
@@ -86,7 +90,7 @@ public:
             List<labelPair>& explicitConnections
         ) const;
 
-        //- Apply any additional post-decomposition constraints
+        //- Apply this constraint post-decomposition
         virtual void apply
         (
             const polyMesh& mesh,
@@ -101,6 +105,7 @@ public:
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
+} // End namespace decompositionConstraints
 } // End namespace Foam
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
diff --git a/src/parallel/decompose/decompositionMethods/decompositionConstraints/singleProcessorFaceSets/singleProcessorFaceSetsConstraint.C b/src/parallel/decompose/decompositionMethods/decompositionConstraints/singleProcessorFaceSets/singleProcessorFaceSetsConstraint.C
index 15109c7b3e3..59a6a73860c 100644
--- a/src/parallel/decompose/decompositionMethods/decompositionConstraints/singleProcessorFaceSets/singleProcessorFaceSetsConstraint.C
+++ b/src/parallel/decompose/decompositionMethods/decompositionConstraints/singleProcessorFaceSets/singleProcessorFaceSetsConstraint.C
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2015-2016 OpenFOAM Foundation
-     \\/     M anipulation  |
+     \\/     M anipulation  | Copyright (C) 2018 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -28,34 +28,45 @@ License
 #include "syncTools.H"
 #include "faceSet.H"
 
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
 
 namespace Foam
 {
 namespace decompositionConstraints
 {
-    defineTypeName(singleProcessorFaceSetsConstraint);
+    defineTypeName(singleProcessorFaceSets);
 
     addToRunTimeSelectionTable
     (
         decompositionConstraint,
-        singleProcessorFaceSetsConstraint,
+        singleProcessorFaceSets,
         dictionary
     );
 }
 }
 
+// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
+
+void Foam::decompositionConstraints::singleProcessorFaceSets::printInfo() const
+{
+    for (const auto& nameAndProc : setNameAndProcs_)
+    {
+        Info<< "    all cells connected to faceSet "
+            << nameAndProc.first()
+            << " on processor " << nameAndProc.second() << endl;
+    }
+}
+
 
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
-Foam::decompositionConstraints::singleProcessorFaceSetsConstraint::
-singleProcessorFaceSetsConstraint
+Foam::decompositionConstraints::singleProcessorFaceSets::
+singleProcessorFaceSets
 (
-    const dictionary& constraintsDict,
-    const word& modelType
+    const dictionary& dict
 )
 :
-    decompositionConstraint(constraintsDict, typeName),
+    decompositionConstraint(dict, typeName),
     setNameAndProcs_
     (
         coeffDict_.lookupCompat("sets", {{"singleProcessorFaceSets", 1806}})
@@ -66,18 +77,13 @@ singleProcessorFaceSetsConstraint
         Info<< type()
             << " : adding constraints to keep" << endl;
 
-        forAll(setNameAndProcs_, setI)
-        {
-            Info<< "    all cells connected to faceSet "
-                << setNameAndProcs_[setI].first()
-                << " on processor " << setNameAndProcs_[setI].second() << endl;
-        }
+        printInfo();
     }
 }
 
 
-Foam::decompositionConstraints::singleProcessorFaceSetsConstraint::
-singleProcessorFaceSetsConstraint
+Foam::decompositionConstraints::singleProcessorFaceSets::
+singleProcessorFaceSets
 (
     const List<Tuple2<word, label>>& setNameAndProcs
 )
@@ -90,19 +96,33 @@ singleProcessorFaceSetsConstraint
         Info<< type()
             << " : adding constraints to keep" << endl;
 
-        forAll(setNameAndProcs_, setI)
-        {
-            Info<< "    all cells connected to faceSet "
-                << setNameAndProcs_[setI].first()
-                << " on processor " << setNameAndProcs_[setI].second() << endl;
-        }
+        printInfo();
+    }
+}
+
+
+Foam::decompositionConstraints::singleProcessorFaceSets::
+singleProcessorFaceSets
+(
+    Istream& is
+)
+:
+    decompositionConstraint(dictionary(), typeName),
+    setNameAndProcs_(is)
+{
+    if (decompositionConstraint::debug)
+    {
+        Info<< type()
+            << " : adding constraints to keep" << endl;
+
+        printInfo();
     }
 }
 
 
 // * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * * //
 
-void Foam::decompositionConstraints::singleProcessorFaceSetsConstraint::add
+void Foam::decompositionConstraints::singleProcessorFaceSets::add
 (
     const polyMesh& mesh,
     boolList& blockedFace,
@@ -111,20 +131,19 @@ void Foam::decompositionConstraints::singleProcessorFaceSetsConstraint::add
     List<labelPair>& explicitConnections
 ) const
 {
-    blockedFace.setSize(mesh.nFaces(), true);
+    blockedFace.resize(mesh.nFaces(), true);
 
     // Mark faces already in set
     labelList faceToSet(mesh.nFaces(), -1);
     forAll(specifiedProcessorFaces, setI)
     {
         const labelList& faceLabels = specifiedProcessorFaces[setI];
-        forAll(faceLabels, i)
+        for (const label facei : faceLabels)
         {
-            faceToSet[faceLabels[i]] = setI;
+            faceToSet[facei] = setI;
         }
     }
 
-
     forAll(setNameAndProcs_, setI)
     {
         //Info<< "Keeping all cells connected to faceSet "
@@ -140,10 +159,10 @@ void Foam::decompositionConstraints::singleProcessorFaceSetsConstraint::add
         labelList nMatch(specifiedProcessorFaces.size(), 0);
         forAllConstIter(faceSet, fz, iter)
         {
-            label setI = faceToSet[iter.key()];
-            if (setI != -1)
+            label seti = faceToSet[iter.key()];
+            if (seti != -1)
             {
-                nMatch[setI]++;
+                ++nMatch[seti];
             }
         }
 
@@ -156,13 +175,13 @@ void Foam::decompositionConstraints::singleProcessorFaceSetsConstraint::add
         {
             if (nMatch[setI] == fz.size())
             {
-                // full match
+                // Full match
                 store = false;
                 break;
             }
             else if (nMatch[setI] > 0)
             {
-                // partial match
+                // Partial match
                 store = false;
                 break;
             }
@@ -184,13 +203,14 @@ void Foam::decompositionConstraints::singleProcessorFaceSetsConstraint::add
     boolList procFacePoint(mesh.nPoints(), false);
     forAll(specifiedProcessorFaces, setI)
     {
-        const labelList& set = specifiedProcessorFaces[setI];
-        forAll(set, fI)
+        const labelList& faceLabels = specifiedProcessorFaces[setI];
+        for (const label facei : faceLabels)
         {
-            const face& f = mesh.faces()[set[fI]];
-            forAll(f, fp)
+            const face& f = mesh.faces()[facei];
+
+            for (const label pointi : f)
             {
-                procFacePoint[f[fp]] = true;
+                procFacePoint[pointi] = true;
             }
         }
     }
@@ -210,7 +230,7 @@ void Foam::decompositionConstraints::singleProcessorFaceSetsConstraint::add
                 if (blockedFace[pFaces[i]])
                 {
                     blockedFace[pFaces[i]] = false;
-                    nUnblocked++;
+                    ++nUnblocked;
                 }
             }
         }
@@ -226,7 +246,7 @@ void Foam::decompositionConstraints::singleProcessorFaceSetsConstraint::add
 }
 
 
-void Foam::decompositionConstraints::singleProcessorFaceSetsConstraint::apply
+void Foam::decompositionConstraints::singleProcessorFaceSets::apply
 (
     const polyMesh& mesh,
     const boolList& blockedFace,
@@ -286,23 +306,23 @@ void Foam::decompositionConstraints::singleProcessorFaceSetsConstraint::apply
             if (procFacePoint[pointi])
             {
                 const labelList& pFaces = mesh.pointFaces()[pointi];
-                forAll(pFaces, i)
+                for (const label faceI : pFaces)
                 {
-                    label faceI = pFaces[i];
+                    const label own = mesh.faceOwner()[faceI];
 
-                    label own = mesh.faceOwner()[faceI];
                     if (decomposition[own] != procI)
                     {
                         decomposition[own] = procI;
-                        nChanged++;
+                        ++nChanged;
                     }
+
                     if (mesh.isInternalFace(faceI))
                     {
-                        label nei = mesh.faceNeighbour()[faceI];
+                        const label nei = mesh.faceNeighbour()[faceI];
                         if (decomposition[nei] != procI)
                         {
                             decomposition[nei] = procI;
-                            nChanged++;
+                            ++nChanged;
                         }
                     }
                 }
diff --git a/src/parallel/decompose/decompositionMethods/decompositionConstraints/singleProcessorFaceSets/singleProcessorFaceSetsConstraint.H b/src/parallel/decompose/decompositionMethods/decompositionConstraints/singleProcessorFaceSets/singleProcessorFaceSetsConstraint.H
index 691f5ef9938..7cff84aef9d 100644
--- a/src/parallel/decompose/decompositionMethods/decompositionConstraints/singleProcessorFaceSets/singleProcessorFaceSetsConstraint.H
+++ b/src/parallel/decompose/decompositionMethods/decompositionConstraints/singleProcessorFaceSets/singleProcessorFaceSetsConstraint.H
@@ -22,12 +22,36 @@ License
     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
 
 Class
-    Foam::singleProcessorFaceSetsConstraint
+    Foam::decompositionConstraints::singleProcessorFaceSets
 
 Description
     Constraint to keep all cells connected to face or point of faceSet on
     a single processor.
 
+    \heading Dictionary parameters
+    \table
+        Property    | Description                       | Required  | Default
+        type        | singleProcessorFaceSets           | yes   |
+        sets        | List of sets and processers       | yes   |
+    \endtable
+
+    Example,
+    \verbatim
+    constraints
+    {
+        procs
+        {
+            type    singleProcessorFaceSets;
+            sets
+            (
+                (faceSet1   0)
+                (faceSet5   12)
+                (faceSet25 510)
+            );
+        }
+    }
+    \endverbatim
+
 SourceFiles
     singleProcessorFaceSetsConstraint.C
 
@@ -43,15 +67,14 @@ SourceFiles
 
 namespace Foam
 {
-
 namespace decompositionConstraints
 {
 
 /*---------------------------------------------------------------------------*\
-                Class singleProcessorFaceSetsConstraint Declaration
+                   Class singleProcessorFaceSets Declaration
 \*---------------------------------------------------------------------------*/
 
-class singleProcessorFaceSetsConstraint
+class singleProcessorFaceSets
 :
     public decompositionConstraint
 {
@@ -60,6 +83,10 @@ class singleProcessorFaceSetsConstraint
         //- List of faceSet+processor
         List<Tuple2<word, label>> setNameAndProcs_;
 
+        //- Report names of sets and processor numnbers
+        void printInfo() const;
+
+
 public:
 
     //- Runtime type information
@@ -68,27 +95,26 @@ public:
 
     // Constructors
 
-        //- Construct with generic dictionary with optional entry for type
-        singleProcessorFaceSetsConstraint
-        (
-            const dictionary& constraintsDict,
-            const word& type
-        );
+        //- Construct with constraint dictionary
+        explicit singleProcessorFaceSets(const dictionary& dict);
 
-        //- Construct from components
-        singleProcessorFaceSetsConstraint
+        //- Copy construct from components
+        explicit singleProcessorFaceSets
         (
             const List<Tuple2<word, label>>& setNameAndProcs
         );
 
+        //- Read construct a List of (setName processor)
+        explicit singleProcessorFaceSets(Istream& is);
+
 
     //- Destructor
-    virtual ~singleProcessorFaceSetsConstraint() = default;
+    virtual ~singleProcessorFaceSets() = default;
 
 
     // Member Functions
 
-        //- Add my constraints to list of constraints
+        //- Add this constraint to list of constraints
         virtual void add
         (
             const polyMesh& mesh,
@@ -98,7 +124,7 @@ public:
             List<labelPair>& explicitConnections
         ) const;
 
-        //- Apply any additional post-decomposition constraints
+        //- Add this constraint post-decomposition
         virtual void apply
         (
             const polyMesh& mesh,
diff --git a/src/parallel/decompose/decompositionMethods/decompositionMethod/decompositionMethod.C b/src/parallel/decompose/decompositionMethods/decompositionMethod/decompositionMethod.C
index e8c7b575019..c2acb24eee4 100644
--- a/src/parallel/decompose/decompositionMethods/decompositionMethod/decompositionMethod.C
+++ b/src/parallel/decompose/decompositionMethods/decompositionMethod/decompositionMethod.C
@@ -34,6 +34,7 @@ License
 #include "BitOps.H"
 #include "FaceCellWave.H"
 
+// Compatibility (MAY-2014)
 #include "preserveBafflesConstraint.H"
 #include "preservePatchesConstraint.H"
 #include "preserveFaceZonesConstraint.H"
@@ -114,103 +115,106 @@ const Foam::dictionary& Foam::decompositionMethod::optionalRegionDict
 
 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
 
+bool Foam::decompositionMethod::constraintCompat(const word& modelType) const
+{
+    bool usable = decompDict_.found(modelType);
+    if (!usable)
+    {
+        return false;
+    }
+
+    for (const auto& item : constraints_)
+    {
+        if (modelType == item.type())
+        {
+            usable = false;
+            break;
+        }
+    }
+
+    if (usable)
+    {
+        Warning
+            << nl << "    Using '" << modelType
+            << "' constraint specification." << nl;
+    }
+    else
+    {
+        Warning
+            << nl << "    Ignoring '" << modelType
+            << "' constraint specification - was already specified." << nl;
+    }
+
+    // The syntax changed MAY-2014
+    error::warnAboutAge("constraint keyword", 1406);
+
+    return usable;
+}
+
+
 void Foam::decompositionMethod::readConstraints()
 {
     constraints_.clear();
 
-    // Read any constraints
-    wordList constraintTypes;
-
-    const dictionary* dictptr = decompositionDict_.findDict("constraints");
+    const dictionary* dictptr = decompDict_.findDict("constraints");
 
     if (dictptr)
     {
         for (const entry& dEntry : *dictptr)
         {
-            const dictionary& dict = dEntry.dict();
+            if (!dEntry.isDict())  // safety
+            {
+                // Ignore or warn
+                continue;
+            }
 
-            constraintTypes.append(dict.get<word>("type"));
+            const dictionary& dict = dEntry.dict();
 
-            constraints_.append
-            (
-                decompositionConstraint::New
-                (
-                    dict,
-                    constraintTypes.last()
-                )
-            );
+            if (dict.lookupOrDefault("enabled", true))
+            {
+                constraints_.append(decompositionConstraint::New(dict));
+            }
         }
     }
 
-    // Backwards compatibility
-    if
-    (
-        decompositionDict_.found("preserveBaffles")
-     && !constraintTypes.found
-        (
-            decompositionConstraints::preserveBafflesConstraint::typeName
-        )
-    )
+    // Backwards compatibility (MAY-2014)
+    if (constraintCompat("preserveBaffles"))
     {
         constraints_.append
         (
-            new decompositionConstraints::preserveBafflesConstraint()
+            new decompositionConstraints::preserveBaffles()
         );
     }
 
-    if
-    (
-        decompositionDict_.found("preservePatches")
-     && !constraintTypes.found
-        (
-            decompositionConstraints::preservePatchesConstraint::typeName
-        )
-    )
+    if (constraintCompat("preservePatches"))
     {
-        const wordReList pNames(decompositionDict_.lookup("preservePatches"));
-
         constraints_.append
         (
-            new decompositionConstraints::preservePatchesConstraint(pNames)
+            new decompositionConstraints::preservePatches
+            (
+                decompDict_.get<wordRes>("preservePatches")
+            )
         );
     }
 
-    if
-    (
-        decompositionDict_.found("preserveFaceZones")
-     && !constraintTypes.found
-        (
-            decompositionConstraints::preserveFaceZonesConstraint::typeName
-        )
-    )
+    if (constraintCompat("preserveFaceZones"))
     {
-        const wordReList zNames(decompositionDict_.lookup("preserveFaceZones"));
-
         constraints_.append
         (
-            new decompositionConstraints::preserveFaceZonesConstraint(zNames)
+            new decompositionConstraints::preserveFaceZones
+            (
+                decompDict_.get<wordRes>("preserveFaceZones")
+            )
         );
     }
 
-    if
-    (
-        decompositionDict_.found("singleProcessorFaceSets")
-     && !constraintTypes.found
-        (
-            decompositionConstraints::preserveFaceZonesConstraint::typeName
-        )
-    )
+    if (constraintCompat("singleProcessorFaceSets"))
     {
-        const List<Tuple2<word, label>> zNameAndProcs
-        (
-            decompositionDict_.lookup("singleProcessorFaceSets")
-        );
-
         constraints_.append
         (
-            new decompositionConstraints::singleProcessorFaceSetsConstraint
+            new decompositionConstraints::singleProcessorFaceSets
             (
-                zNameAndProcs
+                decompDict_.lookup("singleProcessorFaceSets")
             )
         );
     }
@@ -268,14 +272,14 @@ const Foam::dictionary& Foam::decompositionMethod::findCoeffsDict
 
     if
     (
-        !decompositionRegionDict_.empty()
+        !decompRegionDict_.empty()
     &&
         (
-            (fnd = decompositionRegionDict_.csearch(coeffsName)).isDict()
+            (fnd = decompRegionDict_.csearch(coeffsName)).isDict()
          ||
             (
                 !(select & selectionType::EXACT)
-             && (fnd = decompositionRegionDict_.csearch(defaultName)).isDict()
+             && (fnd = decompRegionDict_.csearch(defaultName)).isDict()
             )
         )
     )
@@ -285,11 +289,11 @@ const Foam::dictionary& Foam::decompositionMethod::findCoeffsDict
 
     if
     (
-        (fnd = decompositionDict_.csearch(coeffsName)).isDict()
+        (fnd = decompDict_.csearch(coeffsName)).isDict()
      ||
         (
             !(select & selectionType::EXACT)
-         && (fnd = decompositionDict_.csearch(defaultName)).isDict()
+         && (fnd = decompDict_.csearch(defaultName)).isDict()
         )
     )
     {
@@ -301,7 +305,7 @@ const Foam::dictionary& Foam::decompositionMethod::findCoeffsDict
     {
         FatalIOError
             << "'" << coeffsName << "' dictionary not found in dictionary "
-            << decompositionDict_.name() << endl
+            << decompDict_.name() << endl
             << abort(FatalIOError);
     }
 
@@ -310,7 +314,7 @@ const Foam::dictionary& Foam::decompositionMethod::findCoeffsDict
         return dictionary::null;
     }
 
-    return decompositionDict_;
+    return decompDict_;
 }
 
 
@@ -321,8 +325,8 @@ Foam::decompositionMethod::decompositionMethod
     const dictionary& decompDict
 )
 :
-    decompositionDict_(decompDict),
-    decompositionRegionDict_(dictionary::null),
+    decompDict_(decompDict),
+    decompRegionDict_(dictionary::null),
     nDomains_(nDomains(decompDict))
 {
     readConstraints();
@@ -335,10 +339,10 @@ Foam::decompositionMethod::decompositionMethod
     const word& regionName
 )
 :
-    decompositionDict_(decompDict),
-    decompositionRegionDict_
+    decompDict_(decompDict),
+    decompRegionDict_
     (
-        optionalRegionDict(decompositionDict_, regionName)
+        optionalRegionDict(decompDict_, regionName)
     ),
     nDomains_(nDomains(decompDict, regionName))
 {
@@ -381,7 +385,6 @@ Foam::autoPtr<Foam::decompositionMethod> Foam::decompositionMethod::New
 (
     const dictionary& decompDict,
     const word& regionName
-
 )
 {
     const dictionary& regionDict(optionalRegionDict(decompDict, regionName));
@@ -428,7 +431,7 @@ Foam::labelList Foam::decompositionMethod::decompose
     const pointField& points
 ) const
 {
-    scalarField weights(points.size(), 1.0);
+    scalarField weights(points.size(), scalar(1));
 
     return decompose(mesh, points, weights);
 }
@@ -482,7 +485,7 @@ Foam::labelList Foam::decompositionMethod::decompose
     const pointField& coarsePoints
 ) const
 {
-    scalarField weights(coarsePoints.size(), 1.0);
+    scalarField weights(coarsePoints.size(), scalar(1));
 
     return decompose
     (
@@ -500,7 +503,7 @@ Foam::labelList Foam::decompositionMethod::decompose
     const pointField& cc
 ) const
 {
-    scalarField weights(cc.size(), 1.0);
+    scalarField weights(cc.size(), scalar(1));
 
     return decompose(globalCellCells, cc, weights);
 }
@@ -565,7 +568,7 @@ void Foam::decompositionMethod::calcCellCells
     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
     // Number of faces per coarse cell
-    labelList nFacesPerCell(nLocalCoarse, 0);
+    labelList nFacesPerCell(nLocalCoarse, Zero);
 
     for (label facei = 0; facei < mesh.nInternalFaces(); ++facei)
     {
@@ -764,7 +767,7 @@ void Foam::decompositionMethod::calcCellCells
     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
     // Number of faces per coarse cell
-    labelList nFacesPerCell(nLocalCoarse, 0);
+    labelList nFacesPerCell(nLocalCoarse, Zero);
 
     for (label facei = 0; facei < mesh.nInternalFaces(); ++facei)
     {
@@ -1016,7 +1019,7 @@ Foam::labelList Foam::decompositionMethod::decompose
     // If we average the region centre instead, cyclics could cause
     // the average domain centre to be outside of domain.
 
-    scalarField regionWeights(localRegion.nLocalRegions(), 0.0);
+    scalarField regionWeights(localRegion.nLocalRegions(), Zero);
 
     pointField regionCentres(localRegion.nLocalRegions(), point::max);
 
diff --git a/src/parallel/decompose/decompositionMethods/decompositionMethod/decompositionMethod.H b/src/parallel/decompose/decompositionMethods/decompositionMethod/decompositionMethod.H
index 4c4aad89940..6b1a55f0107 100644
--- a/src/parallel/decompose/decompositionMethods/decompositionMethod/decompositionMethod.H
+++ b/src/parallel/decompose/decompositionMethods/decompositionMethod/decompositionMethod.H
@@ -50,7 +50,14 @@ class decompositionMethod
 {
     // Private Member Functions
 
-        //- Set PtrList of constraints by reading decompositionDict_.
+        //- Check (and warn) about existence of old constraint syntax.
+        //  The syntax changed MAY-2014.
+        //
+        //  \return true if this model name was found in the decompDict_
+        //      but not previously added with the newer syntax.
+        bool constraintCompat(const word& modelType) const;
+
+        //- Set PtrList of constraints by reading decompDict_.
         void readConstraints();
 
         //- No copy construct
@@ -77,10 +84,10 @@ protected:
     // Protected data
 
         //- Top-level decomposition dictionary (eg, decomposeParDict)
-        const dictionary& decompositionDict_;
+        const dictionary& decompDict_;
 
         //- Region-specific decomposition dictionary information
-        const dictionary& decompositionRegionDict_;
+        const dictionary& decompRegionDict_;
 
         //- Number of domains for the decomposition
         label nDomains_;
@@ -238,14 +245,14 @@ public:
         ) const
         {
             NotImplemented;
-            return labelList(0);
+            return labelList();
         }
 
         //- Decompose with uniform weights on the points
         virtual labelList decompose(const pointField& points) const
         {
             NotImplemented;
-            return labelList(0);
+            return labelList();
         }
 
 
diff --git a/src/parallel/decompose/decompositionMethods/geomDecomp/geomDecomp.C b/src/parallel/decompose/decompositionMethods/geomDecomp/geomDecomp.C
index d4eeb242410..1cb99153b89 100644
--- a/src/parallel/decompose/decompositionMethods/geomDecomp/geomDecomp.C
+++ b/src/parallel/decompose/decompositionMethods/geomDecomp/geomDecomp.C
@@ -30,7 +30,6 @@ License
 void Foam::geomDecomp::readCoeffs()
 {
     coeffsDict_.readIfPresent("delta", delta_);
-
     coeffsDict_.readEntry("n", n_);
 
     // Verify that the input makes sense
@@ -63,7 +62,7 @@ void Foam::geomDecomp::checkDecompositionDirections
     const Vector<label>& meshDirs
 ) const
 {
-    for (direction dir = 0; dir < Vector<label>::nComponents; dir++)
+    for (direction dir = 0; dir < Vector<label>::nComponents; ++dir)
     {
         if (n_[dir] > 1 && meshDirs[dir] == -1)
         {
diff --git a/src/parallel/decompose/decompositionMethods/hierarchGeomDecomp/hierarchGeomDecomp.C b/src/parallel/decompose/decompositionMethods/hierarchGeomDecomp/hierarchGeomDecomp.C
index 05c66ad764d..cc87a33f2d6 100644
--- a/src/parallel/decompose/decompositionMethods/hierarchGeomDecomp/hierarchGeomDecomp.C
+++ b/src/parallel/decompose/decompositionMethods/hierarchGeomDecomp/hierarchGeomDecomp.C
@@ -59,7 +59,7 @@ void Foam::hierarchGeomDecomp::setDecompOrder()
     {
         if (order.size() != 3)
         {
-            FatalIOErrorInFunction(decompositionDict_)
+            FatalIOErrorInFunction(decompDict_)
                 << "number of characters in order (" << order << ") != 3"
                 << exit(FatalIOError);
         }
@@ -75,7 +75,7 @@ void Foam::hierarchGeomDecomp::setDecompOrder()
                 case 'z': decompOrder_[i] = 2; break;
 
                 default:
-                    FatalIOErrorInFunction(decompositionDict_)
+                    FatalIOErrorInFunction(decompDict_)
                         << "Illegal decomposition order " << order << nl
                         << "It should only contain x, y or z"
                         << exit(FatalError);
@@ -536,7 +536,7 @@ void Foam::hierarchGeomDecomp::sortComponent
 
     // Now evaluate local cumulative weights, based on the sorting.
     // Make one bigger than the nodes.
-    scalarField sortedWeightedSizes(current.size()+1, 0);
+    scalarField sortedWeightedSizes(current.size()+1, Zero);
     calculateSortedWeightedSizes
     (
         current,
@@ -719,7 +719,7 @@ Foam::labelList Foam::hierarchGeomDecomp::decompose
 ) const
 {
     // construct a list for the final result
-    labelList finalDecomp(points.size(), 0);
+    labelList finalDecomp(points.size(), Zero);
 
     // Start off with every point sorted onto itself.
     labelList slice(points.size());
@@ -759,8 +759,8 @@ Foam::labelList Foam::hierarchGeomDecomp::decompose
     const scalarField& weights
 ) const
 {
-    // construct a list for the final result
-    labelList finalDecomp(points.size(), 0);
+    // Construct a list for the final result
+    labelList finalDecomp(points.size(), Zero);
 
     // Start off with every point sorted onto itself.
     labelList slice(points.size());
diff --git a/src/parallel/decompose/decompositionMethods/manualDecomp/manualDecomp.C b/src/parallel/decompose/decompositionMethods/manualDecomp/manualDecomp.C
index 86c5cb656c0..1077871f955 100644
--- a/src/parallel/decompose/decompositionMethods/manualDecomp/manualDecomp.C
+++ b/src/parallel/decompose/decompositionMethods/manualDecomp/manualDecomp.C
@@ -24,9 +24,8 @@ License
 \*---------------------------------------------------------------------------*/
 
 #include "manualDecomp.H"
-#include "addToRunTimeSelectionTable.H"
-#include "IFstream.H"
 #include "labelIOList.H"
+#include "addToRunTimeSelectionTable.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
@@ -55,7 +54,10 @@ namespace Foam
 Foam::manualDecomp::manualDecomp(const dictionary& decompDict)
 :
     decompositionMethod(decompDict),
-    dataFile_(findCoeffsDict(typeName + "Coeffs").lookup("dataFile"))
+    dataFile_
+    (
+        findCoeffsDict(typeName + "Coeffs").get<fileName>("dataFile")
+    )
 {}
 
 
@@ -66,7 +68,10 @@ Foam::manualDecomp::manualDecomp
 )
 :
     decompositionMethod(decompDict, regionName),
-    dataFile_(findCoeffsDict(typeName + "Coeffs").lookup("dataFile"))
+    dataFile_
+    (
+        findCoeffsDict(typeName + "Coeffs").get<fileName>("dataFile")
+    )
 {}
 
 
diff --git a/src/parallel/decompose/decompositionMethods/manualDecomp/manualDecomp.H b/src/parallel/decompose/decompositionMethods/manualDecomp/manualDecomp.H
index 21c0e2764da..4654ffcc643 100644
--- a/src/parallel/decompose/decompositionMethods/manualDecomp/manualDecomp.H
+++ b/src/parallel/decompose/decompositionMethods/manualDecomp/manualDecomp.H
@@ -111,11 +111,6 @@ public:
 
         //- Return for every coordinate the wanted processor number.
         //  Explicitly provided connectivity - does not use mesh_.
-        //  The connectivity is equal to mesh.cellCells() except for
-        //  - in parallel the cell numbers are global cell numbers (starting
-        //    from 0 at processor0 and then incrementing all through the
-        //    processors)
-        //  - the connections are across coupled patches
         virtual labelList decompose
         (
             const labelListList& globalCellCells,
@@ -124,7 +119,7 @@ public:
         ) const
         {
             NotImplemented;
-            return labelList(0);
+            return labelList();
         }
 
 };
diff --git a/src/parallel/decompose/decompositionMethods/multiLevelDecomp/multiLevelDecomp.C b/src/parallel/decompose/decompositionMethods/multiLevelDecomp/multiLevelDecomp.C
index 6861199f260..3411b2d8e39 100644
--- a/src/parallel/decompose/decompositionMethods/multiLevelDecomp/multiLevelDecomp.C
+++ b/src/parallel/decompose/decompositionMethods/multiLevelDecomp/multiLevelDecomp.C
@@ -397,7 +397,7 @@ void Foam::multiLevelDecomp::decompose
             Pout<< "Decomposition at level " << currLevel << " :" << endl;
         }
 
-        for (label domainI = 0; domainI < nCurrDomains; domainI++)
+        for (label domainI = 0; domainI < nCurrDomains; ++domainI)
         {
             // Extract elements for current domain
             const labelList domainPoints(findIndices(dist, domainI));
@@ -505,12 +505,12 @@ void Foam::multiLevelDecomp::decompose
                 )
             );
 
-            for (label blockI = 0; blockI < nCurrDomains; blockI++)
+            for (label blockI = 0; blockI < nCurrDomains; ++blockI)
             {
                 // Count the number inbetween blocks of nNext size
 
                 label nPoints = 0;
-                labelList nOutsideConnections(nCurrDomains, 0);
+                labelList nOutsideConnections(nCurrDomains, Zero);
                 forAll(pointPoints, pointi)
                 {
                     if ((dist[pointi] / nNext) == blockI)
@@ -633,7 +633,7 @@ Foam::labelList Foam::multiLevelDecomp::decompose
     CompactListList<label> cellCells;
     calcCellCells(mesh, identity(cc.size()), cc.size(), true, cellCells);
 
-    labelList finalDecomp(cc.size(), 0);
+    labelList finalDecomp(cc.size(), Zero);
     labelList cellMap(identity(cc.size()));
 
     decompose
@@ -659,7 +659,7 @@ Foam::labelList Foam::multiLevelDecomp::decompose
     const scalarField& pointWeights
 ) const
 {
-    labelList finalDecomp(points.size(), 0);
+    labelList finalDecomp(points.size(), Zero);
     labelList pointMap(identity(points.size()));
 
     decompose
diff --git a/src/parallel/decompose/decompositionMethods/structuredDecomp/structuredDecomp.C b/src/parallel/decompose/decompositionMethods/structuredDecomp/structuredDecomp.C
index 825156ddf56..f2aed184c10 100644
--- a/src/parallel/decompose/decompositionMethods/structuredDecomp/structuredDecomp.C
+++ b/src/parallel/decompose/decompositionMethods/structuredDecomp/structuredDecomp.C
@@ -50,7 +50,7 @@ Foam::structuredDecomp::structuredDecomp(const dictionary& decompDict)
 :
     decompositionMethod(decompDict),
     methodDict_(findCoeffsDict(typeName + "Coeffs", selectionType::MANDATORY)),
-    patches_(methodDict_.lookup("patches"))
+    patches_(methodDict_.get<wordRes>("patches"))
 {
     methodDict_.set("numberOfSubdomains", nDomains());
     method_ = decompositionMethod::New(methodDict_);
@@ -150,7 +150,7 @@ Foam::labelList Foam::structuredDecomp::decompose
             {
                 WarningInFunction
                     << "Did not visit some cells, e.g. cell " << celli
-                    << " at " << mesh.cellCentres()[celli] << endl
+                    << " at " << mesh.cellCentres()[celli] << nl
                     << "Assigning  these cells to domain 0." << endl;
                 haveWarned = true;
             }
@@ -166,17 +166,4 @@ Foam::labelList Foam::structuredDecomp::decompose
 }
 
 
-Foam::labelList Foam::structuredDecomp::decompose
-(
-    const labelListList& globalCellCells,
-    const pointField& cc,
-    const scalarField& cWeights
-) const
-{
-    NotImplemented;
-
-    return labelList(0);
-}
-
-
 // ************************************************************************* //
diff --git a/src/parallel/decompose/decompositionMethods/structuredDecomp/structuredDecomp.H b/src/parallel/decompose/decompositionMethods/structuredDecomp/structuredDecomp.H
index 95d1246b74e..ca00ce9115d 100644
--- a/src/parallel/decompose/decompositionMethods/structuredDecomp/structuredDecomp.H
+++ b/src/parallel/decompose/decompositionMethods/structuredDecomp/structuredDecomp.H
@@ -105,7 +105,11 @@ public:
             const labelListList& globalCellCells,
             const pointField& cc,
             const scalarField& cWeights
-        ) const;
+        ) const
+        {
+            NotImplemented;
+            return labelList();
+        }
 };
 
 
diff --git a/src/parallel/decompose/metisDecomp/metisDecomp.C b/src/parallel/decompose/metisDecomp/metisDecomp.C
index 5fabedf464a..8889b48fb2b 100644
--- a/src/parallel/decompose/metisDecomp/metisDecomp.C
+++ b/src/parallel/decompose/metisDecomp/metisDecomp.C
@@ -71,8 +71,7 @@ Foam::label Foam::metisDecomp::decomposeSerial
     // k-way: multi-level k-way
     word method("recursive");
 
-    const dictionary* coeffsDictPtr =
-        decompositionDict_.findDict("metisCoeffs");
+    const dictionary* coeffsDictPtr = decompDict_.findDict("metisCoeffs");
 
     label numCells = xadj.size()-1;
 
@@ -133,7 +132,7 @@ Foam::label Foam::metisDecomp::decomposeSerial
             {
                 FatalErrorInFunction
                     << "Method " << method << " in metisCoeffs in dictionary : "
-                    << decompositionDict_.name()
+                    << decompDict_.name()
                     << " should be 'recursive' or 'k-way'"
                     << exit(FatalError);
             }
@@ -148,7 +147,7 @@ Foam::label Foam::metisDecomp::decomposeSerial
             {
                 FatalErrorInFunction
                     << "Number of options in metisCoeffs in dictionary : "
-                    << decompositionDict_.name()
+                    << decompDict_.name()
                     << " should be " << METIS_NOPTIONS
                     << exit(FatalError);
             }
diff --git a/tutorials/preProcessing/decompositionConstraints/geometric/Allclean b/tutorials/preProcessing/decompositionConstraints/geometric/Allclean
new file mode 100755
index 00000000000..214bd9a5ecb
--- /dev/null
+++ b/tutorials/preProcessing/decompositionConstraints/geometric/Allclean
@@ -0,0 +1,9 @@
+#!/bin/sh
+cd ${0%/*} || exit 1                        # Run from this directory
+. $WM_PROJECT_DIR/bin/tools/CleanFunctions  # Tutorial clean functions
+
+\rm -f constant/triSurface/blob.obj
+
+cleanCase0
+
+#------------------------------------------------------------------------------
diff --git a/tutorials/preProcessing/decompositionConstraints/geometric/Allrun b/tutorials/preProcessing/decompositionConstraints/geometric/Allrun
new file mode 100755
index 00000000000..8cbcee602dc
--- /dev/null
+++ b/tutorials/preProcessing/decompositionConstraints/geometric/Allrun
@@ -0,0 +1,20 @@
+#!/bin/sh
+cd ${0%/*} || exit 1                        # Run from this directory
+. $WM_PROJECT_DIR/bin/tools/RunFunctions    # Tutorial run functions
+
+mkdir -p constant/triSurface
+
+# Use 'blob' as an arbitrary enclosing surface
+runApplication surfaceTransformPoints \
+    -translate '(0 0 5)' \
+    -origin '(0 0 5)' \
+    -rotate-angle '((1 0 0) 45)' \
+    $FOAM_TUTORIALS/resources/geometry/blob.stl.gz constant/triSurface/blob.obj
+
+runApplication blockMesh
+
+runApplication decomposePar -dry-run -cellDist
+
+runApplication foamToVTK -xml -excludePatches '(".*")'
+
+#------------------------------------------------------------------------------
diff --git a/tutorials/preProcessing/decompositionConstraints/geometric/constant/transportProperties b/tutorials/preProcessing/decompositionConstraints/geometric/constant/transportProperties
new file mode 100644
index 00000000000..171f00e1151
--- /dev/null
+++ b/tutorials/preProcessing/decompositionConstraints/geometric/constant/transportProperties
@@ -0,0 +1,21 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v1812                                 |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      transportProperties;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+transportModel  Newtonian;
+
+nu              1.5e-05;
+
+// ************************************************************************* //
diff --git a/tutorials/preProcessing/decompositionConstraints/geometric/constant/turbulenceProperties b/tutorials/preProcessing/decompositionConstraints/geometric/constant/turbulenceProperties
new file mode 100644
index 00000000000..a6f61e83396
--- /dev/null
+++ b/tutorials/preProcessing/decompositionConstraints/geometric/constant/turbulenceProperties
@@ -0,0 +1,28 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v1812                                 |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      turbulenceProperties;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+simulationType RAS;
+
+RAS
+{
+    RASModel            kOmegaSST;
+
+    turbulence          on;
+
+    printCoeffs         on;
+}
+
+// ************************************************************************* //
diff --git a/tutorials/preProcessing/decompositionConstraints/geometric/system/blockMeshDict b/tutorials/preProcessing/decompositionConstraints/geometric/system/blockMeshDict
new file mode 100644
index 00000000000..89d21ca68e0
--- /dev/null
+++ b/tutorials/preProcessing/decompositionConstraints/geometric/system/blockMeshDict
@@ -0,0 +1,86 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v1812                                 |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      blockMeshDict;
+}
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+scale   1;
+
+vertices
+(
+    (-5 -4 0)
+    (15 -4 0)
+    (15  4 0)
+    (-5  4 0)
+    (-5 -4 8)
+    (15 -4 8)
+    (15  4 8)
+    (-5  4 8)
+);
+
+blocks
+(
+    hex (0 1 2 3 4 5 6 7) (200 80 80) simpleGrading (1 1 1)
+);
+
+edges
+(
+);
+
+boundary
+(
+    frontAndBack
+    {
+        type patch;
+        faces
+        (
+            (3 7 6 2)
+            (1 5 4 0)
+        );
+    }
+    inlet
+    {
+        type patch;
+        faces
+        (
+            (0 4 7 3)
+        );
+    }
+    outlet
+    {
+        type patch;
+        faces
+        (
+            (2 6 5 1)
+        );
+    }
+    lowerWall
+    {
+        type wall;
+        faces
+        (
+            (0 3 2 1)
+        );
+    }
+    upperWall
+    {
+        type patch;
+        faces
+        (
+            (4 5 6 7)
+        );
+    }
+);
+
+// ************************************************************************* //
diff --git a/tutorials/preProcessing/decompositionConstraints/geometric/system/controlDict b/tutorials/preProcessing/decompositionConstraints/geometric/system/controlDict
new file mode 100644
index 00000000000..06a744e2dfb
--- /dev/null
+++ b/tutorials/preProcessing/decompositionConstraints/geometric/system/controlDict
@@ -0,0 +1,48 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v1812                                 |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      controlDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+application     decomposePar;
+
+startFrom       latestTime;
+
+startTime       0;
+
+stopAt          endTime;
+
+endTime         500;
+
+deltaT          1;
+
+writeControl    timeStep;
+
+writeInterval   100;
+
+purgeWrite      0;
+
+writeFormat     binary;
+
+writePrecision  6;
+
+writeCompression off;
+
+timeFormat      general;
+
+timePrecision   6;
+
+runTimeModifiable true;
+
+
+// ************************************************************************* //
diff --git a/tutorials/preProcessing/decompositionConstraints/geometric/system/decomposeConstraints b/tutorials/preProcessing/decompositionConstraints/geometric/system/decomposeConstraints
new file mode 100644
index 00000000000..856c15fbd97
--- /dev/null
+++ b/tutorials/preProcessing/decompositionConstraints/geometric/system/decomposeConstraints
@@ -0,0 +1,84 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v1812                                 |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      decomposeConstraints;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+// Optional decomposition constraints
+constraints
+{
+    geometric
+    {
+        type    geometric;
+
+        grow    true;
+
+        selection
+        {
+            blob
+            {
+                source  surface;
+                surfaceType  triSurfaceMesh;
+                surfaceName  blob.obj;
+            }
+
+            box1
+            {
+                source  box;
+                min     (-10 -10 -10);
+                max     (1 1 1);
+            }
+
+            semi
+            {
+                source  sphere;
+                origin  (-2 -2 1);
+                radius  1;
+            }
+
+            mid
+            {
+                source  sphere;
+                origin  (5 0 4);
+                radius  1;
+            }
+
+            ball
+            {
+                source  sphere;
+                origin  (15 4 8);
+                radius  3;
+            }
+
+            // This entry should generate a warning (and be ignored)
+            // since it does not describe an enclosed volume.
+            disk
+            {
+                source  surface;
+                surface disk;
+                origin  (0 0 0);
+                normal  (0 0 1);
+                radius  3;
+            }
+        }
+    }
+
+    baffles
+    {
+        type   preserveBaffles;
+    }
+
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/preProcessing/decompositionConstraints/geometric/system/decomposeParDict b/tutorials/preProcessing/decompositionConstraints/geometric/system/decomposeParDict
new file mode 100644
index 00000000000..028bba73705
--- /dev/null
+++ b/tutorials/preProcessing/decompositionConstraints/geometric/system/decomposeParDict
@@ -0,0 +1,34 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v1812                                 |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      decomposeParDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+// Do NOT attempt with hierarchical with these constraints!
+
+numberOfSubdomains 128;
+
+// method          simple;
+method          scotch;
+// method          random;
+
+coeffs
+{
+    n   (16 8 4);
+}
+
+// Optional decomposition constraints
+#include "<system>/decomposeConstraints"
+
+
+// ************************************************************************* //
diff --git a/tutorials/preProcessing/decompositionConstraints/geometric/system/decomposeParDict.8 b/tutorials/preProcessing/decompositionConstraints/geometric/system/decomposeParDict.8
new file mode 100644
index 00000000000..d1e61d2f7fe
--- /dev/null
+++ b/tutorials/preProcessing/decompositionConstraints/geometric/system/decomposeParDict.8
@@ -0,0 +1,31 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v1812                                 |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      decomposeParDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+// Do NOT attempt with hierarchical with these constraints!
+
+numberOfSubdomains 8;
+
+method          scotch;
+
+coeffs
+{
+    n   (2 2 2);
+}
+
+// Optional decomposition constraints
+#include "<system>/decomposeConstraints"
+
+// ************************************************************************* //
diff --git a/tutorials/preProcessing/decompositionConstraints/geometric/system/fvSchemes b/tutorials/preProcessing/decompositionConstraints/geometric/system/fvSchemes
new file mode 100644
index 00000000000..51b10c67991
--- /dev/null
+++ b/tutorials/preProcessing/decompositionConstraints/geometric/system/fvSchemes
@@ -0,0 +1,58 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v1806                                 |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      fvSchemes;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+ddtSchemes
+{
+    default         steadyState;
+}
+
+gradSchemes
+{
+    default         Gauss linear;
+    grad(U)         cellLimited Gauss linear 1;
+}
+
+divSchemes
+{
+    default         none;
+    div(phi,U)      bounded Gauss linearUpwindV grad(U);
+    div(phi,k)      bounded Gauss upwind;
+    div(phi,omega)  bounded Gauss upwind;
+    div((nuEff*dev2(T(grad(U))))) Gauss linear;
+}
+
+laplacianSchemes
+{
+    default         Gauss linear corrected;
+}
+
+interpolationSchemes
+{
+    default         linear;
+}
+
+snGradSchemes
+{
+    default         corrected;
+}
+
+wallDist
+{
+    method meshWave;
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/preProcessing/decompositionConstraints/geometric/system/fvSolution b/tutorials/preProcessing/decompositionConstraints/geometric/system/fvSolution
new file mode 100644
index 00000000000..dc40f02c021
--- /dev/null
+++ b/tutorials/preProcessing/decompositionConstraints/geometric/system/fvSolution
@@ -0,0 +1,92 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v1806                                 |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      fvSolution;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+solvers
+{
+    p
+    {
+        solver           GAMG;
+        tolerance        1e-7;
+        relTol           0.01;
+        smoother         GaussSeidel;
+        nPreSweeps       0;
+        nPostSweeps      2;
+        cacheAgglomeration on;
+        agglomerator     faceAreaPair;
+        nCellsInCoarsestLevel 10;
+        mergeLevels      1;
+    }
+
+    Phi
+    {
+        $p;
+    }
+
+    U
+    {
+        solver           smoothSolver;
+        smoother         GaussSeidel;
+        tolerance        1e-8;
+        relTol           0.1;
+        nSweeps          1;
+    }
+
+    k
+    {
+        solver           smoothSolver;
+        smoother         GaussSeidel;
+        tolerance        1e-8;
+        relTol           0.1;
+        nSweeps          1;
+    }
+
+    omega
+    {
+        solver           smoothSolver;
+        smoother         GaussSeidel;
+        tolerance        1e-8;
+        relTol           0.1;
+        nSweeps          1;
+    }
+}
+
+SIMPLE
+{
+    nNonOrthogonalCorrectors 0;
+    consistent yes;
+}
+
+potentialFlow
+{
+    nNonOrthogonalCorrectors 10;
+}
+
+relaxationFactors
+{
+    equations
+    {
+        U               0.9;
+        k               0.7;
+        omega           0.7;
+    }
+}
+
+cache
+{
+    grad(U);
+}
+
+// ************************************************************************* //
-- 
GitLab