diff --git a/applications/utilities/mesh/conversion/polyDualMesh/Make/files b/applications/utilities/mesh/conversion/polyDualMesh/Make/files
index de69b15edfcfc37273d21c3c670ccf885c87d43b..c43f79e8e148201c61e6d3d41f6fff50a540b4d7 100644
--- a/applications/utilities/mesh/conversion/polyDualMesh/Make/files
+++ b/applications/utilities/mesh/conversion/polyDualMesh/Make/files
@@ -1,4 +1,3 @@
-polyDualMesh.C
 polyDualMeshApp.C
 
 EXE = $(FOAM_APPBIN)/polyDualMesh
diff --git a/applications/utilities/mesh/conversion/polyDualMesh/Make/options b/applications/utilities/mesh/conversion/polyDualMesh/Make/options
index 54c035b8f55d183c1ad02bc372398feceaf31718..6dc63a7a989641aba7de693a1920eec74912cb02 100644
--- a/applications/utilities/mesh/conversion/polyDualMesh/Make/options
+++ b/applications/utilities/mesh/conversion/polyDualMesh/Make/options
@@ -1,5 +1,6 @@
 EXE_INC = \
-    -I$(LIB_SRC)/meshTools/lnInclude
+    -I$(LIB_SRC)/meshTools/lnInclude \
+    -I$(LIB_SRC)/conversion/lnInclude
 
 EXE_LIBS = \
-    -lmeshTools
+    -lmeshTools -lconversion
diff --git a/applications/utilities/parallelProcessing/decomposePar/decomposePar.C b/applications/utilities/parallelProcessing/decomposePar/decomposePar.C
index 0c820006c72b9955e899b38cad0560f8cbec6a86..3685be43c4d99bb808d8e0a4b55b1dcdb6ffcf57 100644
--- a/applications/utilities/parallelProcessing/decomposePar/decomposePar.C
+++ b/applications/utilities/parallelProcessing/decomposePar/decomposePar.C
@@ -50,6 +50,14 @@ Usage
     Remove any existing @a processor subdirectories before decomposing the
     geometry.
 
+    @param -lazy \n
+    Only decompose the geometry if the number of domains has changed from a
+    previous decomposition. No @a processor subdirectories will be removed
+    unless the @a -force option is also specified. This option can be used
+    to avoid redundant geometry decomposition (eg, in scripts), but should
+    be used with caution when the underlying (serial) geometry or the
+    decomposition method etc. have been changed between decompositions.
+
 \*---------------------------------------------------------------------------*/
 
 #include "OSspecific.H"
@@ -80,6 +88,7 @@ int main(int argc, char *argv[])
     argList::validOptions.insert("fields", "");
     argList::validOptions.insert("filterPatches", "");
     argList::validOptions.insert("force", "");
+    argList::validOptions.insert("lazy", "");
 
 #   include "setRootCase.H"
 
@@ -88,6 +97,7 @@ int main(int argc, char *argv[])
     bool decomposeFieldsOnly(args.options().found("fields"));
     bool filterPatches(args.options().found("filterPatches"));
     bool forceOverwrite(args.options().found("force"));
+    bool lazyDecomposition(args.options().found("lazy"));
 
 #   include "createTime.H"
 
@@ -100,47 +110,84 @@ int main(int argc, char *argv[])
         ++nProcs;
     }
 
-    // Check for previously decomposed case first
+    // get requested numberOfSubdomains
+    label nDomains = 0;
+    {
+        IOdictionary decompDict
+        (
+            IOobject
+            (
+                "decomposeParDict",
+                runTime.time().system(),
+                runTime,
+                IOobject::MUST_READ,
+                IOobject::NO_WRITE,
+                false
+            )
+        );
+
+        decompDict.lookup("numberOfSubdomains") >> nDomains;
+    }
+
     if (decomposeFieldsOnly)
     {
-        if (!nProcs)
+        // Sanity check on previously decomposed case
+        if (nProcs != nDomains)
         {
             FatalErrorIn(args.executable())
-                << "Specifying -fields requires a decomposed geometry!"
+                << "Specified -fields, but the case was decomposed with "
+                << nProcs << " domains"
+                << nl
+                << "instead of " << nDomains
+                << " domains as specified in decomposeParDict"
                 << nl
                 << exit(FatalError);
         }
     }
-    else
+    else if (nProcs)
     {
-        if (nProcs)
+        bool procDirsProblem = true;
+
+        if (lazyDecomposition && nProcs == nDomains)
         {
-            if (forceOverwrite)
-            {
-                Info<< "Removing " << nProcs
-                    << " existing processor directories" << endl;
+            // we can reuse the decomposition
+            decomposeFieldsOnly = true;
+            procDirsProblem = false;
+            forceOverwrite = false;
 
-                // remove existing processor dirs
-                for (label procI = nProcs-1; procI >= 0; --procI)
-                {
-                    fileName procDir
-                    (
-                        runTime.path()/(word("processor") + name(procI))
-                    );
+            Info<< "Using existing processor directories" << nl;
+        }
 
-                    rmDir(procDir);
-                }
-            }
-            else
+        if (forceOverwrite)
+        {
+            Info<< "Removing " << nProcs
+                << " existing processor directories" << endl;
+
+            // remove existing processor dirs
+            // reverse order to avoid gaps if someone interrupts the process
+            for (label procI = nProcs-1; procI >= 0; --procI)
             {
-                FatalErrorIn(args.executable())
-                    << "Case is already decomposed, "
-                        "use the -force option or manually remove" << nl
-                    << "processor directories before decomposing. e.g.," << nl
-                    << "    rm -rf " << runTime.path().c_str() << "/processor*"
-                    << nl
-                    << exit(FatalError);
+                fileName procDir
+                (
+                    runTime.path()/(word("processor") + name(procI))
+                );
+
+                rmDir(procDir);
             }
+
+            procDirsProblem = false;
+        }
+
+        if (procDirsProblem)
+        {
+            FatalErrorIn(args.executable())
+                << "Case is already decomposed with " << nProcs
+                << " domains, use the -force option or manually" << nl
+                << "remove processor directories before decomposing. e.g.,"
+                << nl
+                << "    rm -rf " << runTime.path().c_str() << "/processor*"
+                << nl
+                << exit(FatalError);
         }
     }
 
diff --git a/applications/utilities/parallelProcessing/decomposePar/decomposeParDict b/applications/utilities/parallelProcessing/decomposePar/decomposeParDict
index b9ee4eaeb126871f082cf1e42a8e8357571f1529..c7317b464faeaa114f70cc6cb55f7fade8bbcd08 100644
--- a/applications/utilities/parallelProcessing/decomposePar/decomposeParDict
+++ b/applications/utilities/parallelProcessing/decomposePar/decomposeParDict
@@ -1,61 +1,61 @@
-// Mesh decomposition control dictionary
-
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
+/*-------------------------------*- C++ -*---------------------------------*\
+|    =========                                                              |
+|    \\      /     OpenFOAM                                                 |
+|     \\    /                                                               |
+|      \\  /       The Open Source CFD Toolbox                              |
+|       \\/                                        http://www.OpenFOAM.org  |
+\*-------------------------------------------------------------------------*/
 FoamFile
 {
-    version 0.5;
-    format ascii;
-
-    root     "ROOT";
-    case     "CASE";
-    instance "system";
-    local    "";
-
-    class dictionary;
-
-    object decompositionDict;
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    note        "mesh decomposition control dictionary";
+    location    "system";
+    object      decomposeParDict;
 }
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
-numberOfSubdomains   4;
+numberOfSubdomains  4;
 
-//preservePatches (inlet);
-//preserveFaceZones (heater solid1 solid3);
+// preservePatches (inlet);
+// preserveFaceZones (heater solid1 solid3);
 
-method               simple;
-//method               hierarchical;
-//method               metis;
-//method               manual;
+method          simple;
+// method          hierarchical;
+// method          metis;
+// method          manual;
 
 simpleCoeffs
 {
-    n                    (2 2 1);
-    delta                0.001;
+    n           (2 2 1);
+    delta       0.001;
 }
 
 hierarchicalCoeffs
 {
-    n                    (2 2 1);
-    delta                0.001;
-    order                xyz;
+    n           (2 2 1);
+    delta       0.001;
+    order       xyz;
 }
 
 metisCoeffs
 {
-    //processorWeights 
-    //(
-    //    1
-    //    1
-    //    1
-    //    1
-    //);
+ /*
+    processorWeights
+    (
+        1
+        1
+        1
+        1
+    );
+  */
 }
 
 manualCoeffs
 {
-    dataFile             "decompositionData";
+    dataFile    "decompositionData";
 }
 
 // ************************************************************************* //
diff --git a/src/Allwmake b/src/Allwmake
index f7b68983c6fa2882aa2a5c6c16f2e2c43597a597..08bb914b740eff477bdfe8019cf9bb665b0f4493 100755
--- a/src/Allwmake
+++ b/src/Allwmake
@@ -31,6 +31,7 @@ wmake libso randomProcesses
 ( cd turbulenceModels && ./Allwmake )
 ( cd lagrangian && ./Allwmake )
 ( cd postProcessing && ./Allwmake )
+( cd conversion && ./Allwmake )
 
 wmake libso autoMesh
 wmake libso errorEstimation
diff --git a/src/conversion/Allwmake b/src/conversion/Allwmake
new file mode 100755
index 0000000000000000000000000000000000000000..72e9c2b141c710000251e401749d7e614ff76963
--- /dev/null
+++ b/src/conversion/Allwmake
@@ -0,0 +1,4 @@
+#!/bin/sh
+set -x
+
+wmake libso
diff --git a/src/conversion/Make/files b/src/conversion/Make/files
new file mode 100644
index 0000000000000000000000000000000000000000..435c341cd3c800a2db6c43d24d560631c58afb43
--- /dev/null
+++ b/src/conversion/Make/files
@@ -0,0 +1,3 @@
+polyDualMesh/polyDualMesh.C
+
+LIB = $(FOAM_LIBBIN)/libconversion
diff --git a/src/conversion/Make/options b/src/conversion/Make/options
new file mode 100644
index 0000000000000000000000000000000000000000..4b2f0a059fbac055ee17d31b510b95445907d34c
--- /dev/null
+++ b/src/conversion/Make/options
@@ -0,0 +1,5 @@
+EXE_INC = \
+    -I$(LIB_SRC)/meshTools/lnInclude
+
+LIB_LIBS = \
+    -lmeshTools
diff --git a/applications/utilities/mesh/conversion/polyDualMesh/polyDualMesh.C b/src/conversion/polyDualMesh/polyDualMesh.C
similarity index 100%
rename from applications/utilities/mesh/conversion/polyDualMesh/polyDualMesh.C
rename to src/conversion/polyDualMesh/polyDualMesh.C
diff --git a/applications/utilities/mesh/conversion/polyDualMesh/polyDualMesh.H b/src/conversion/polyDualMesh/polyDualMesh.H
similarity index 100%
rename from applications/utilities/mesh/conversion/polyDualMesh/polyDualMesh.H
rename to src/conversion/polyDualMesh/polyDualMesh.H