diff --git a/applications/utilities/mesh/generation/PDRblockMesh/PDRblockMesh.C b/applications/utilities/mesh/generation/PDRblockMesh/PDRblockMesh.C
index 650957006b3fd4001d5bb96302de888de695029b..1b795379836547ed04d0784a008273c5775a81d9 100644
--- a/applications/utilities/mesh/generation/PDRblockMesh/PDRblockMesh.C
+++ b/applications/utilities/mesh/generation/PDRblockMesh/PDRblockMesh.C
@@ -43,8 +43,8 @@ Usage
       - \par -dict \<filename\>
         Alternative dictionary for the mesh description.
 
-      - \par -noClean
-        Do not remove any existing polyMesh/ directory or files
+      - \par -no-clean
+        Do not remove polyMesh/ directory or files
 
       - \par -time
         Write resulting mesh to a time directory (instead of constant)
@@ -92,9 +92,11 @@ int main(int argc, char *argv[])
 
     argList::addBoolOption
     (
-        "noClean",
-        "Do not remove any existing polyMesh/ directory or files"
+        "no-clean",
+        "Do not remove polyMesh/ directory or files"
     );
+    argList::addOptionCompat("no-clean", {"noClean", -2006});
+
     argList::addOption("dict", "file", "Alternative PDRblockMeshDict");
     argList::addOption
     (
@@ -107,7 +109,11 @@ int main(int argc, char *argv[])
     #include "createTime.H"
 
     // Remove old files, unless disabled
-    const bool removeOldFiles = !args.found("noClean");
+    const bool removeOldFiles = !args.found("no-clean");
+
+    const word regionName(polyMesh::defaultRegion);
+    const word regionPath;
+
 
     // Instance for resulting mesh
     bool useTime = false;
@@ -134,8 +140,8 @@ int main(int argc, char *argv[])
     }
 
 
+    // Locate appropriate PDRblockMeshDict
     const word dictName("PDRblockMeshDict");
-
     #include "setSystemRunTimeDictionaryIO.H"
 
     IOdictionary meshDict(dictIO);
@@ -159,34 +165,17 @@ int main(int argc, char *argv[])
 
     if (removeOldFiles)
     {
-        const fileName polyMeshPath
-        (
-            runTime.path()/meshInstance/polyMesh::meshSubDir
-        );
-
-        if (exists(polyMeshPath))
-        {
-            Info<< "Deleting polyMesh directory "
-                << runTime.relativePath(polyMeshPath) << endl;
-            rmDir(polyMeshPath);
-        }
+        #include "cleanMeshDirectory.H"
     }
 
 
     Info<< nl << "Creating polyMesh from PDRblockMesh" << endl;
 
-    auto meshPtr = blkMesh.mesh
-    (
-        IOobject
+    autoPtr<polyMesh> meshPtr =
+        blkMesh.mesh
         (
-            polyMesh::defaultRegion,
-            meshInstance,
-            runTime,
-            IOobject::NO_READ,
-            IOobject::AUTO_WRITE
-        )
-    );
-
+            IOobject(regionName, meshInstance, runTime)
+        );
 
     const polyMesh& mesh = *meshPtr;
 
@@ -204,30 +193,7 @@ int main(int argc, char *argv[])
             << exit(FatalError);
     }
 
-    // Mesh summary
-    {
-        Info<< "----------------" << nl
-            << "Mesh Information" << nl
-            << "----------------" << nl
-            << "  " << "boundingBox: " << boundBox(mesh.points()) << nl
-            << "  " << "nPoints: " << mesh.nPoints() << nl
-            << "  " << "nCells: " << mesh.nCells() << nl
-            << "  " << "nFaces: " << mesh.nFaces() << nl
-            << "  " << "nInternalFaces: " << mesh.nInternalFaces() << nl;
-
-        Info<< "----------------" << nl
-            << "Patches" << nl
-            << "----------------" << nl;
-
-        for (const polyPatch& p : mesh.boundaryMesh())
-        {
-            Info<< "  " << "patch " << p.index()
-                << " (start: " << p.start()
-                << " size: " << p.size()
-                << ") name: " << p.name()
-                << nl;
-        }
-    }
+    #include "printMeshSummary.H"
 
     Info<< "\nEnd\n" << endl;
 
diff --git a/applications/utilities/mesh/generation/PDRblockMesh/cleanMeshDirectory.H b/applications/utilities/mesh/generation/PDRblockMesh/cleanMeshDirectory.H
new file mode 100644
index 0000000000000000000000000000000000000000..46f017fb196001152cd4c47ef0bbf48b0a050e93
--- /dev/null
+++ b/applications/utilities/mesh/generation/PDRblockMesh/cleanMeshDirectory.H
@@ -0,0 +1,45 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2020 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
+
+Description
+    Removal of polyMesh directory
+
+\*---------------------------------------------------------------------------*/
+
+{
+    // Shadows enclosing parameter (dictName)
+    const word blockMeshDictName("blockMeshDict");
+
+    const fileName polyMeshPath
+    (
+        runTime.path()/meshInstance/regionPath/polyMesh::meshSubDir
+    );
+
+    if (exists(polyMeshPath))
+    {
+        if (exists(polyMeshPath/blockMeshDictName))
+        {
+            Info<< "Not deleting polyMesh directory "
+                << runTime.relativePath(polyMeshPath) << nl
+                << "    because it contains " << blockMeshDictName << endl;
+        }
+        else
+        {
+            Info<< "Deleting polyMesh directory "
+                << runTime.relativePath(polyMeshPath) << endl;
+            rmDir(polyMeshPath);
+        }
+    }
+}
+
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/PDRblockMesh/printMeshSummary.H b/applications/utilities/mesh/generation/PDRblockMesh/printMeshSummary.H
new file mode 100644
index 0000000000000000000000000000000000000000..23ac6fddc1a2d61a8c25c28ad0cbdcb5fa7f12c6
--- /dev/null
+++ b/applications/utilities/mesh/generation/PDRblockMesh/printMeshSummary.H
@@ -0,0 +1,85 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2020 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
+
+Description
+    Summary of mesh information (eg, after blockMesh)
+
+\*---------------------------------------------------------------------------*/
+
+{
+    Info<< "----------------" << nl
+        << "Mesh Information" << nl
+        << "----------------" << nl
+        << "  " << "boundingBox: " << boundBox(mesh.points()) << nl
+        << "  " << "nPoints: " << mesh.nPoints() << nl
+        << "  " << "nCells: " << mesh.nCells() << nl
+        << "  " << "nFaces: " << mesh.nFaces() << nl
+        << "  " << "nInternalFaces: " << mesh.nInternalFaces() << nl;
+
+    const auto printZone =
+        [](const Foam::zone& zn)
+        {
+            Info<< "  " << "zone " << zn.index()
+                << " (size: " << zn.size()
+                << ") name: " << zn.name() << nl;
+        };
+
+    if (mesh.cellZones().size())
+    {
+        Info<< "----------------" << nl
+            << "Cell Zones" << nl
+            << "----------------" << nl;
+
+        for (const cellZone& zn : mesh.cellZones())
+        {
+            printZone(zn);
+        }
+    }
+    if (mesh.faceZones().size())
+    {
+        Info<< "----------------" << nl
+            << "Face Zones" << nl
+            << "----------------" << nl;
+
+        for (const faceZone& zn : mesh.faceZones())
+        {
+            printZone(zn);
+        }
+    }
+    if (mesh.pointZones().size())
+    {
+        Info<< "----------------" << nl
+            << "Point Zones" << nl
+            << "----------------" << nl;
+
+        for (const pointZone& zn : mesh.pointZones())
+        {
+            printZone(zn);
+        }
+    }
+
+    Info<< "----------------" << nl
+        << "Patches" << nl
+        << "----------------" << nl;
+
+    for (const polyPatch& p : mesh.boundaryMesh())
+    {
+        Info<< "  " << "patch " << p.index()
+            << " (start: " << p.start()
+            << " size: " << p.size()
+            << ") name: " << p.name()
+            << nl;
+    }
+}
+
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/blockMesh/addCellZones.H b/applications/utilities/mesh/generation/blockMesh/addCellZones.H
deleted file mode 100644
index 7cec1b4541d1553571d30afa2aac3b841f6c3d51..0000000000000000000000000000000000000000
--- a/applications/utilities/mesh/generation/blockMesh/addCellZones.H
+++ /dev/null
@@ -1 +0,0 @@
-#warning File removed - left for old dependency check only
diff --git a/applications/utilities/mesh/generation/blockMesh/blockMesh.C b/applications/utilities/mesh/generation/blockMesh/blockMesh.C
index b510d911705e4cf78b837823c83563f3de15e0f5..8cdb4faf0ed0de114b6dc4109f41b1957ee50245 100644
--- a/applications/utilities/mesh/generation/blockMesh/blockMesh.C
+++ b/applications/utilities/mesh/generation/blockMesh/blockMesh.C
@@ -61,8 +61,8 @@ Usage
       - \par -sets
         Write cellZones as cellSets too (for processing purposes)
 
-      - \par -noClean
-        Do not remove any existing polyMesh/ directory or files
+      - \par -no-clean
+        Do not remove polyMesh/ directory or files
 
       - \par -time
         Write resulting mesh to a time directory (instead of constant)
@@ -141,9 +141,11 @@ int main(int argc, char *argv[])
     );
     argList::addBoolOption
     (
-        "noClean",
-        "Do not remove any existing polyMesh/ directory or files"
+        "no-clean",
+        "Do not remove polyMesh/ directory or files"
     );
+    argList::addOptionCompat("no-clean", {"noClean", -2006});
+
     argList::addOption("dict", "file", "Alternative blockMeshDict");
     argList::addBoolOption
     (
@@ -162,7 +164,7 @@ int main(int argc, char *argv[])
     #include "createTime.H"
 
     // Remove old files, unless disabled
-    const bool removeOldFiles = !args.found("noClean");
+    const bool removeOldFiles = !args.found("no-clean");
 
     // Write cellSets
     const bool writeCellSets = args.found("sets");
@@ -232,66 +234,20 @@ int main(int argc, char *argv[])
     if (args.found("write-obj"))
     {
         quickExit = true;
-
         Info<< nl;
-
-        // Write mesh as edges
-        {
-            OFstream os(runTime.path()/"blockTopology.obj");
-
-            Info<< "Writing block structure in obj format: "
-                << os.name().name() << endl;
-
-            blocks.writeTopology(os);
-        }
-
-        // Write centres of blocks
-        {
-            OFstream os(runTime.path()/"blockCentres.obj");
-
-            Info<< "Writing block centres in obj format: "
-                << os.name().name() << endl;
-
-            for (const point& cc : blocks.topology().cellCentres())
-            {
-                os << "v " << cc.x() << ' ' << cc.y() << ' ' << cc.z() << nl;
-            }
-        }
+        #include "blockMeshOBJ.H"
     }
 
     if (args.found("write-vtk"))
     {
         quickExit = true;
-
-        // non-legacy and ASCII (mesh is small, want readable output)
-        const vtk::outputOptions writeOpts = vtk::formatType::INLINE_ASCII;
-
         Info<< nl;
-
-        const polyMesh& topoMesh = blocks.topology();
-        const vtk::vtuCells topoCells(topoMesh, writeOpts);
-
-        vtk::internalMeshWriter writer
-        (
-            topoMesh,
-            topoCells,
-            writeOpts,
-            runTime.path()/"blockTopology"
-        );
-
-        Info<< "Writing block topology in vtk format: "
-            << args.relativePath(writer.output()).c_str() << endl;
-
-        writer.writeGeometry();
-        writer.beginCellData();
-        writer.writeCellIDs();
+        #include "blockMeshVTK.H"
     }
 
-
     if (quickExit)
     {
         Info<< "\nEnd\n" << endl;
-
         return 0;
     }
 
@@ -309,26 +265,7 @@ int main(int argc, char *argv[])
 
     if (removeOldFiles)
     {
-        const fileName polyMeshPath
-        (
-            runTime.path()/meshInstance/regionPath/polyMesh::meshSubDir
-        );
-
-        if (exists(polyMeshPath))
-        {
-            if (exists(polyMeshPath/dictName))
-            {
-                Info<< "Not deleting polyMesh directory "
-                    << runTime.relativePath(polyMeshPath) << nl
-                    << "    because it contains " << dictName << endl;
-            }
-            else
-            {
-                Info<< "Deleting polyMesh directory "
-                    << runTime.relativePath(polyMeshPath) << endl;
-                rmDir(polyMeshPath);
-            }
-        }
+        #include "cleanMeshDirectory.H"
     }
 
 
@@ -377,30 +314,7 @@ int main(int argc, char *argv[])
         }
     }
 
-    // Write summary
-    {
-        Info<< "----------------" << nl
-            << "Mesh Information" << nl
-            << "----------------" << nl
-            << "  " << "boundingBox: " << boundBox(mesh.points()) << nl
-            << "  " << "nPoints: " << mesh.nPoints() << nl
-            << "  " << "nCells: " << mesh.nCells() << nl
-            << "  " << "nFaces: " << mesh.nFaces() << nl
-            << "  " << "nInternalFaces: " << mesh.nInternalFaces() << nl;
-
-        Info<< "----------------" << nl
-            << "Patches" << nl
-            << "----------------" << nl;
-
-        for (const polyPatch& p : mesh.boundaryMesh())
-        {
-            Info<< "  " << "patch " << p.index()
-                << " (start: " << p.start()
-                << " size: " << p.size()
-                << ") name: " << p.name()
-                << nl;
-        }
-    }
+    #include "printMeshSummary.H"
 
     Info<< "\nEnd\n" << endl;
 
diff --git a/applications/utilities/mesh/generation/blockMesh/blockMeshOBJ.H b/applications/utilities/mesh/generation/blockMesh/blockMeshOBJ.H
new file mode 100644
index 0000000000000000000000000000000000000000..83325bef651bae58d9ff82c077a560d86f95afb1
--- /dev/null
+++ b/applications/utilities/mesh/generation/blockMesh/blockMeshOBJ.H
@@ -0,0 +1,54 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2020 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
+
+Description
+    OBJ output of blockMesh topology blocks
+
+\*---------------------------------------------------------------------------*/
+
+{
+    const polyMesh& topoMesh = blocks.topology();
+
+    // Write mesh as edges
+    {
+        OFstream os(runTime.path()/"blockTopology.obj");
+
+        Info<< "Writing block structure in obj format: "
+            << os.name().name() << endl;
+
+        for (const point& p : topoMesh.points())
+        {
+            os << "v " << p.x() << ' ' << p.y() << ' ' << p.z() << nl;
+        }
+
+        for (const edge& e : topoMesh.edges())
+        {
+            os << "l " << e.start() + 1 << ' ' << e.end() + 1 << nl;
+        }
+    }
+
+    // Write centres of blocks
+    {
+        OFstream os(runTime.path()/"blockCentres.obj");
+
+        Info<< "Writing block centres in obj format: "
+            << os.name().name() << endl;
+
+        for (const point& p : topoMesh.cellCentres())
+        {
+            os << "v " << p.x() << ' ' << p.y() << ' ' << p.z() << nl;
+        }
+    }
+}
+
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/blockMesh/blockMeshVTK.H b/applications/utilities/mesh/generation/blockMesh/blockMeshVTK.H
new file mode 100644
index 0000000000000000000000000000000000000000..431b0b357eed41a7536c1aa2363403c4974d8fc1
--- /dev/null
+++ b/applications/utilities/mesh/generation/blockMesh/blockMeshVTK.H
@@ -0,0 +1,100 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2020 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
+
+Description
+    VTK output of blockMesh topology blocks
+
+\*---------------------------------------------------------------------------*/
+
+{
+    // Non-legacy and ASCII (mesh is small, want readable output)
+    const vtk::outputOptions writeOpts = vtk::formatType::INLINE_ASCII;
+
+    const polyMesh& topoMesh = blocks.topology();
+    const vtk::vtuCells topoCells(topoMesh, writeOpts);
+
+    vtk::internalMeshWriter writer
+    (
+        topoMesh,
+        topoCells,
+        writeOpts,
+        runTime.path()/"blockTopology"
+    );
+
+    Info<< "Writing block topology in vtk format: "
+        << args.relativePath(writer.output()).c_str() << endl;
+
+    writer.writeGeometry();
+    writer.beginCellData();
+    writer.writeCellIDs();
+
+    // No cell decomposition, so there is a 1-to-1 correspondence between
+    // input blocks and VTK output cells.
+
+    vectorField localNormal(blocks.size());
+
+    // Generate local normals as fields for visualisation
+    for (direction cmpt = 0; cmpt < vector::nComponents; ++cmpt)
+    {
+        const label faceMin = label(2*cmpt);
+        const label faceMax = faceMin+1;
+
+        localNormal.resize(blocks.size());
+
+        forAll(blocks, blocki)
+        {
+            const cellShape& shape = blocks[blocki].blockShape();
+            const pointField& verts = blocks[blocki].vertices();
+
+            if (shape.model() == cellModel::ref(cellModel::HEX))
+            {
+                localNormal[blocki] =
+                (
+                    // 30% cell-width as arbitrary value for vector length
+                    0.3*mag
+                    (
+                        shape.face(faceMax).centre(verts)
+                      - shape.face(faceMin).centre(verts)
+                    )
+                  * normalised
+                    (
+                        // Weigh by area to avoid influence of zero-faces
+                        shape.face(faceMax).areaNormal(verts)
+                      - shape.face(faceMin).areaNormal(verts)
+                    )
+                );
+            }
+            else
+            {
+                // Could handle other shapes (how?)
+                localNormal[blocki] = Zero;
+            }
+        }
+
+        // Additional safety (should not happen)
+        localNormal.resize(topoMesh.nCells(), Zero);
+
+        writer.writeCellData
+        (
+            word("local-direction" + name(cmpt)),
+            localNormal
+        );
+    }
+
+    // if (topoMesh.nCells() != blocks.size())
+    // {
+    //     Info<< "Warning: indicated normals may be incorrect" << nl;
+    // }
+}
+
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/blockMesh/cleanMeshDirectory.H b/applications/utilities/mesh/generation/blockMesh/cleanMeshDirectory.H
new file mode 100644
index 0000000000000000000000000000000000000000..46f017fb196001152cd4c47ef0bbf48b0a050e93
--- /dev/null
+++ b/applications/utilities/mesh/generation/blockMesh/cleanMeshDirectory.H
@@ -0,0 +1,45 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2020 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
+
+Description
+    Removal of polyMesh directory
+
+\*---------------------------------------------------------------------------*/
+
+{
+    // Shadows enclosing parameter (dictName)
+    const word blockMeshDictName("blockMeshDict");
+
+    const fileName polyMeshPath
+    (
+        runTime.path()/meshInstance/regionPath/polyMesh::meshSubDir
+    );
+
+    if (exists(polyMeshPath))
+    {
+        if (exists(polyMeshPath/blockMeshDictName))
+        {
+            Info<< "Not deleting polyMesh directory "
+                << runTime.relativePath(polyMeshPath) << nl
+                << "    because it contains " << blockMeshDictName << endl;
+        }
+        else
+        {
+            Info<< "Deleting polyMesh directory "
+                << runTime.relativePath(polyMeshPath) << endl;
+            rmDir(polyMeshPath);
+        }
+    }
+}
+
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/blockMesh/printMeshSummary.H b/applications/utilities/mesh/generation/blockMesh/printMeshSummary.H
new file mode 100644
index 0000000000000000000000000000000000000000..23ac6fddc1a2d61a8c25c28ad0cbdcb5fa7f12c6
--- /dev/null
+++ b/applications/utilities/mesh/generation/blockMesh/printMeshSummary.H
@@ -0,0 +1,85 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2020 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
+
+Description
+    Summary of mesh information (eg, after blockMesh)
+
+\*---------------------------------------------------------------------------*/
+
+{
+    Info<< "----------------" << nl
+        << "Mesh Information" << nl
+        << "----------------" << nl
+        << "  " << "boundingBox: " << boundBox(mesh.points()) << nl
+        << "  " << "nPoints: " << mesh.nPoints() << nl
+        << "  " << "nCells: " << mesh.nCells() << nl
+        << "  " << "nFaces: " << mesh.nFaces() << nl
+        << "  " << "nInternalFaces: " << mesh.nInternalFaces() << nl;
+
+    const auto printZone =
+        [](const Foam::zone& zn)
+        {
+            Info<< "  " << "zone " << zn.index()
+                << " (size: " << zn.size()
+                << ") name: " << zn.name() << nl;
+        };
+
+    if (mesh.cellZones().size())
+    {
+        Info<< "----------------" << nl
+            << "Cell Zones" << nl
+            << "----------------" << nl;
+
+        for (const cellZone& zn : mesh.cellZones())
+        {
+            printZone(zn);
+        }
+    }
+    if (mesh.faceZones().size())
+    {
+        Info<< "----------------" << nl
+            << "Face Zones" << nl
+            << "----------------" << nl;
+
+        for (const faceZone& zn : mesh.faceZones())
+        {
+            printZone(zn);
+        }
+    }
+    if (mesh.pointZones().size())
+    {
+        Info<< "----------------" << nl
+            << "Point Zones" << nl
+            << "----------------" << nl;
+
+        for (const pointZone& zn : mesh.pointZones())
+        {
+            printZone(zn);
+        }
+    }
+
+    Info<< "----------------" << nl
+        << "Patches" << nl
+        << "----------------" << nl;
+
+    for (const polyPatch& p : mesh.boundaryMesh())
+    {
+        Info<< "  " << "patch " << p.index()
+            << " (start: " << p.start()
+            << " size: " << p.size()
+            << ") name: " << p.name()
+            << nl;
+    }
+}
+
+
+// ************************************************************************* //
diff --git a/applications/utilities/surface/surfaceClean/surfaceClean.C b/applications/utilities/surface/surfaceClean/surfaceClean.C
index ce0a7c10b93ff7e2ca2dfcafdab18a43a9583781..98c850c6950da2e1f8c9d6e1a67e7a3b7e09ecff 100644
--- a/applications/utilities/surface/surfaceClean/surfaceClean.C
+++ b/applications/utilities/surface/surfaceClean/surfaceClean.C
@@ -69,9 +69,11 @@ int main(int argc, char *argv[])
 
     argList::addBoolOption
     (
-        "noClean",
+        "no-clean",
         "Suppress surface checking/cleanup on the input surface"
     );
+    argList::addOptionCompat("no-clean", {"noClean", -2006});
+
     argList::addOption
     (
         "scale",
@@ -101,7 +103,7 @@ int main(int argc, char *argv[])
     );
     surf.writeStats(Info);
 
-    if (!args.found("noClean"))
+    if (!args.found("no-clean"))
     {
         Info<< "Removing duplicate and illegal triangles ..." << nl << endl;
         surf.cleanup(true);
diff --git a/bin/tools/CleanFunctions b/bin/tools/CleanFunctions
index 3f126a4c070af40010271b4b3e3f726bc385a529..d001d44bde72c603c0d07da3a28ed824f9b93b3e 100644
--- a/bin/tools/CleanFunctions
+++ b/bin/tools/CleanFunctions
@@ -6,11 +6,10 @@
 #    \\/     M anipulation  |
 #------------------------------------------------------------------------------
 #     Copyright (C) 2011-2016 OpenFOAM Foundation
-#     Copyright (C) 2015-2019 OpenCFD Ltd.
+#     Copyright (C) 2015-2020 OpenCFD Ltd.
 #------------------------------------------------------------------------------
 # License
-#     This file is part of OpenFOAM, licensed under GNU General Public License
-#     <http://www.gnu.org/licenses/>.
+#     This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
 #
 # Script
 #     CleanFunctions
@@ -116,6 +115,9 @@ cleanCase()
     rm -rf sets
     rm -rf system/machines
 
+    # Possible blockMesh output
+    rm -f blockTopology.vtu blockTopology.obj blockCentres.obj
+
     # From mpirunDebug
     rm -f gdbCommands  mpirun.schema
 
diff --git a/src/OpenFOAM/meshes/meshShapes/cellModel/cellModel.H b/src/OpenFOAM/meshes/meshShapes/cellModel/cellModel.H
index bfe223cdb292d8d3180b33c5fd9954391e920696..59490311d2f814d014c2fc26e0bd4542477e8f09 100644
--- a/src/OpenFOAM/meshes/meshShapes/cellModel/cellModel.H
+++ b/src/OpenFOAM/meshes/meshShapes/cellModel/cellModel.H
@@ -214,7 +214,7 @@ public:
         ) const;
 
 
-        //- Vector centroid
+        //- Centroid of the cell
         vector centre
         (
             const labelList& pointLabels,
diff --git a/src/OpenFOAM/meshes/meshShapes/cellShape/cellShape.H b/src/OpenFOAM/meshes/meshShapes/cellShape/cellShape.H
index 250fcbe655504f97fae785a583d0521e55aeba3d..200670501a34d7d9f626c3208c91db038fa09e34 100644
--- a/src/OpenFOAM/meshes/meshShapes/cellShape/cellShape.H
+++ b/src/OpenFOAM/meshes/meshShapes/cellShape/cellShape.H
@@ -126,12 +126,21 @@ public:
 
     // Member Functions
 
-        //- Return the points corresponding to this cellShape
-        inline pointField points(const UList<point>& meshPoints) const;
-
         //- Model reference
         inline const cellModel& model() const;
 
+        //- Number of points
+        inline label nPoints() const;
+
+        //- Number of edges
+        inline label nEdges() const;
+
+        //- Number of faces
+        inline label nFaces() const;
+
+        //- The points corresponding to this shape
+        inline pointField points(const UList<point>& meshPoints) const;
+
         //- Mesh face labels of this cell (in order of model)
         inline labelList meshFaces
         (
@@ -146,29 +155,25 @@ public:
             const labelList& cEdges
         ) const;
 
+        //- The face for the specified model face
+        inline Foam::face face(const label modelFacei) const;
+
         //- Faces of this cell
         inline faceList faces() const;
 
         //- Collapsed faces of this cell
         inline faceList collapsedFaces() const;
 
-        //- Number of faces
-        inline label nFaces() const;
+        //- The edge for the specified model edge
+        inline Foam::edge edge(const label modelEdgei) const;
 
-        //- Edges of this cellShape
+        //- Edges of this shape
         inline edgeList edges() const;
 
-        //- Number of edges
-        inline label nEdges() const;
-
-        //- Number of points
-        inline label nPoints() const;
-
         //- Centroid of the cell
         inline point centre(const UList<point>& points) const;
 
-        //- Return info proxy.
-        //  Used to print token information to a stream
+        //- Return info proxy, to print information to a stream
         Foam::InfoProxy<cellShape> info() const
         {
             return *this;
diff --git a/src/OpenFOAM/meshes/meshShapes/cellShape/cellShapeI.H b/src/OpenFOAM/meshes/meshShapes/cellShape/cellShapeI.H
index b66d8c78b77ce35f07eac7342c6a84cf35a5d970..4af2f862d26ed5184bb2edc666c387b7f1d5c131 100644
--- a/src/OpenFOAM/meshes/meshShapes/cellShape/cellShapeI.H
+++ b/src/OpenFOAM/meshes/meshShapes/cellShape/cellShapeI.H
@@ -29,6 +29,7 @@ License
 #include "Istream.H"
 #include "cell.H"
 #include "cellModel.H"
+#include "UIndirectList.H"
 
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
@@ -122,29 +123,36 @@ inline Foam::autoPtr<Foam::cellShape> Foam::cellShape::clone() const
 
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
-inline Foam::pointField Foam::cellShape::points
-(
-    const UList<point>& meshPoints
-) const
+inline const Foam::cellModel& Foam::cellShape::model() const
 {
-    // There are as many points as there labels for them
-    pointField p(size());
+    return *m;
+}
 
-    // For each point in list, set it to the point in 'pnts' addressed
-    // by 'labs'
-    forAll(p, i)
-    {
-        p[i] = meshPoints[operator[](i)];
-    }
 
-    // Return list
-    return p;
+inline Foam::label Foam::cellShape::nPoints() const
+{
+    return size();
 }
 
 
-inline const Foam::cellModel& Foam::cellShape::model() const
+inline Foam::label Foam::cellShape::nEdges() const
 {
-    return *m;
+    return m->nEdges();
+}
+
+
+inline Foam::label Foam::cellShape::nFaces() const
+{
+    return m->nFaces();
+}
+
+
+inline Foam::pointField Foam::cellShape::points
+(
+    const UList<point>& meshPoints
+) const
+{
+    return pointField(UIndirectList<point>(meshPoints, *this));
 }
 
 
@@ -163,16 +171,13 @@ inline Foam::labelList Foam::cellShape::meshFaces
 
     forAll(localFaces, i)
     {
-        const face& localF = localFaces[i];
+        const Foam::face& localF = localFaces[i];
 
-        forAll(cFaces, j)
+        for (const label meshFacei : cFaces)
         {
-            label meshFacei = cFaces[j];
-
             if (allFaces[meshFacei] == localF)
             {
                 modelToMesh[i] = meshFacei;
-
                 break;
             }
         }
@@ -197,16 +202,13 @@ inline Foam::labelList Foam::cellShape::meshEdges
 
     forAll(localEdges, i)
     {
-        const edge& e = localEdges[i];
+        const Foam::edge& e = localEdges[i];
 
-        forAll(cEdges, j)
+        for (const label edgei : cEdges)
         {
-            label edgeI = cEdges[j];
-
-            if (allEdges[edgeI] == e)
+            if (allEdges[edgei] == e)
             {
-                modelToMesh[i] = edgeI;
-
+                modelToMesh[i] = edgei;
                 break;
             }
         }
@@ -216,6 +218,12 @@ inline Foam::labelList Foam::cellShape::meshEdges
 }
 
 
+inline Foam::face Foam::cellShape::face(const label modelFacei) const
+{
+    return m->face(modelFacei, *this);
+}
+
+
 inline Foam::faceList Foam::cellShape::faces() const
 {
     return m->faces(*this);
@@ -224,31 +232,25 @@ inline Foam::faceList Foam::cellShape::faces() const
 
 inline Foam::faceList Foam::cellShape::collapsedFaces() const
 {
-    faceList oldFaces(faces());
+    const faceList oldFaces(faces());
 
     faceList newFaces(oldFaces.size());
     label newFacei = 0;
 
-    forAll(oldFaces, oldFacei)
+    for (const Foam::face& f : oldFaces)
     {
-        const face& f = oldFaces[oldFacei];
-
-        face& newF = newFaces[newFacei];
-
-        newF.setSize(f.size());
+        Foam::face& newF = newFaces[newFacei];
+        newF.resize(f.size());
 
         label newFp = 0;
-        label prevVertI = -1;
+        label prevVerti = -1;
 
-        forAll(f, fp)
+        for (const label verti : f)
         {
-            label vertI = f[fp];
-
-            if (vertI != prevVertI)
+            if (verti != prevVerti)
             {
-                newF[newFp++] = vertI;
-
-                prevVertI = vertI;
+                newF[newFp++] = verti;
+                prevVerti = verti;
             }
         }
 
@@ -260,20 +262,19 @@ inline Foam::faceList Foam::cellShape::collapsedFaces() const
         if (newFp > 2)
         {
             // Size face and go to next one
-            newF.setSize(newFp);
-
-            newFacei++;
+            newF.resize(newFp);
+            ++newFacei;
         }
     }
-    newFaces.setSize(newFacei);
+    newFaces.resize(newFacei);
 
     return newFaces;
 }
 
 
-inline Foam::label Foam::cellShape::nFaces() const
+inline Foam::edge Foam::cellShape::edge(const label modelEdgei) const
 {
-    return m->nFaces();
+    return m->edge(modelEdgei, *this);
 }
 
 
@@ -283,18 +284,6 @@ inline Foam::edgeList Foam::cellShape::edges() const
 }
 
 
-inline Foam::label Foam::cellShape::nEdges() const
-{
-    return m->nEdges();
-}
-
-
-inline Foam::label Foam::cellShape::nPoints() const
-{
-    return size();
-}
-
-
 inline Foam::point Foam::cellShape::centre(const UList<point>& points) const
 {
     return m->centre(*this, points);
diff --git a/src/mesh/blockMesh/blockMesh/blockMesh.C b/src/mesh/blockMesh/blockMesh/blockMesh.C
index 04db49d80c646754760cb3c3226d134eed7a27cb..3cedbba951e49778152ec32ddf63ba85ac84b7cc 100644
--- a/src/mesh/blockMesh/blockMesh/blockMesh.C
+++ b/src/mesh/blockMesh/blockMesh/blockMesh.C
@@ -240,17 +240,4 @@ Foam::label Foam::blockMesh::numZonedBlocks() const
 }
 
 
-void Foam::blockMesh::writeTopology(Ostream& os) const
-{
-    for (const point& p : topology().points())
-    {
-        os << "v " << p.x() << ' ' << p.y() << ' ' << p.z() << nl;
-    }
-
-    for (const edge& e : topology().edges())
-    {
-        os << "l " << e.start() + 1 << ' ' << e.end() + 1 << nl;
-    }
-}
-
 // ************************************************************************* //
diff --git a/src/mesh/blockMesh/blockMesh/blockMesh.H b/src/mesh/blockMesh/blockMesh/blockMesh.H
index d08a4755859a834226f444834d8ac613b9ffd73d..a082ff6c21c6e45fa6b590f6fa2ce21390bab38d 100644
--- a/src/mesh/blockMesh/blockMesh/blockMesh.H
+++ b/src/mesh/blockMesh/blockMesh/blockMesh.H
@@ -313,12 +313,6 @@ public:
 
         //- Create polyMesh, with cell zones
         autoPtr<polyMesh> mesh(const IOobject& io) const;
-
-
-    // Write
-
-        //- Writes edges of blockMesh in OBJ format.
-        void writeTopology(Ostream& os) const;
 };