diff --git a/applications/utilities/mesh/generation/Allwmake b/applications/utilities/mesh/generation/Allwmake
index ef28f9aaf581f6d71d65e0f6b2a0085c1768c307..48ca530c96933f6c31bf4f126658efc9f607fd51 100755
--- a/applications/utilities/mesh/generation/Allwmake
+++ b/applications/utilities/mesh/generation/Allwmake
@@ -4,12 +4,15 @@ set -x
 
 wmake blockMesh
 wmake all extrude
-wmake extrude2DMesh
+
+extrude2DMesh/Allwmake
+
 wmake snappyHexMesh
 
 if [ -d "$CGAL_ARCH_PATH" ]
 then
-    cd cvMesh && ./Allwmake
+    cvMesh/Allwmake
+    cv2DMesh/Allwmake
 fi
 
 # ----------------------------------------------------------------- end-of-file
diff --git a/applications/utilities/mesh/generation/cv2DMesh/Allwclean b/applications/utilities/mesh/generation/cv2DMesh/Allwclean
new file mode 100755
index 0000000000000000000000000000000000000000..d0ae53e41503d0ccd189b47c40f83dc193030e03
--- /dev/null
+++ b/applications/utilities/mesh/generation/cv2DMesh/Allwclean
@@ -0,0 +1,8 @@
+#!/bin/sh
+cd ${0%/*} || exit 1    # run from this directory
+set -x
+
+wclean libso conformalVoronoi2DMesh
+wclean
+
+# ----------------------------------------------------------------- end-of-file
diff --git a/applications/utilities/mesh/generation/cv2DMesh/Allwmake b/applications/utilities/mesh/generation/cv2DMesh/Allwmake
new file mode 100755
index 0000000000000000000000000000000000000000..54868499573cf6b3ce989a211b0fd1be7944c490
--- /dev/null
+++ b/applications/utilities/mesh/generation/cv2DMesh/Allwmake
@@ -0,0 +1,8 @@
+#!/bin/sh
+cd ${0%/*} || exit 1    # run from this directory
+set -x
+
+wmake libso conformalVoronoi2DMesh
+wmake
+
+# ----------------------------------------------------------------- end-of-file
diff --git a/applications/utilities/mesh/generation/cv2DMesh/CGALTriangulation2Ddefs.H b/applications/utilities/mesh/generation/cv2DMesh/CGALTriangulation2Ddefs.H
new file mode 100644
index 0000000000000000000000000000000000000000..1485226d98ce2814ee8862864582744a73675930
--- /dev/null
+++ b/applications/utilities/mesh/generation/cv2DMesh/CGALTriangulation2Ddefs.H
@@ -0,0 +1,82 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2007-2011 OpenFOAM Foundation
+     \\/     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/>.
+
+Typedefs
+    CGALTriangulation2Ddefs
+
+Description
+    CGAL data structures used for 2D Delaunay meshing.
+
+    Define CGAL_INEXACT to use Exact_predicates_inexact_constructions kernel
+    otherwise the more robust but much less efficient
+    Exact_predicates_exact_constructions will be used.
+
+    Define CGAL_HIERARCHY to use hierarchical Delaunay triangulation which is
+    faster but uses more memory than the standard Delaunay triangulation.
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef CGALTriangulation2Ddefs_H
+#define CGALTriangulation2Ddefs_H
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#include "CGAL/Delaunay_triangulation_2.h"
+
+#include "indexedVertex.H"
+#include "indexedFace.H"
+
+#ifdef CGAL_INEXACT
+    // Fast kernel using a double as the storage type but the triangulation
+    // may fail
+    #include "CGAL/Exact_predicates_inexact_constructions_kernel.h"
+    typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
+#else
+    // Very robust but expensive kernel
+    #include "CGAL/Exact_predicates_exact_constructions_kernel.h"
+    typedef CGAL::Exact_predicates_exact_constructions_kernel K;
+#endif
+
+typedef CGAL::indexedVertex<K>                           Vb;
+typedef CGAL::indexedFace<K>                             Fb;
+
+#ifdef CGAL_HIERARCHY
+    // Data structures for hierarchical Delaunay triangulation which is more
+    // efficient but also uses more storage
+    #include "CGAL/Triangulation_hierarchy_2.h"
+    typedef CGAL::Triangulation_hierarchy_vertex_base_2<Vb>  Vbh;
+    typedef CGAL::Triangulation_data_structure_2<Vbh, Fb>    Tds;
+    typedef CGAL::Delaunay_triangulation_2<K, Tds>           DT;
+    typedef CGAL::Triangulation_hierarchy_2<DT>              Delaunay;
+#else
+    // Data structures for standard Delaunay triangulation
+    typedef CGAL::Triangulation_data_structure_2<Vb, Fb>     Tds;
+    typedef CGAL::Delaunay_triangulation_2<K, Tds>           Delaunay;
+#endif
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/cv2DMesh/CV2D.C b/applications/utilities/mesh/generation/cv2DMesh/CV2D.C
new file mode 100644
index 0000000000000000000000000000000000000000..aa45a88b3e9fd47319a5332a0899d28492a0a943
--- /dev/null
+++ b/applications/utilities/mesh/generation/cv2DMesh/CV2D.C
@@ -0,0 +1,1050 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2007-2011 OpenFOAM Foundation
+     \\/     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 "CV2D.H"
+#include "Random.H"
+#include "transform.H"
+#include "IFstream.H"
+#include "uint.H"
+#include "ulong.H"
+
+namespace Foam
+{
+
+defineTypeNameAndDebug(CV2D, 0);
+
+}
+
+// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
+
+void Foam::CV2D::insertBoundingBox()
+{
+    Info<< "insertBoundingBox: creating bounding mesh" << endl;
+    scalar bigSpan = 10*meshControls().span();
+    insertPoint(point2D(-bigSpan, -bigSpan), Vb::FAR_POINT);
+    insertPoint(point2D(-bigSpan, bigSpan), Vb::FAR_POINT);
+    insertPoint(point2D(bigSpan, -bigSpan), Vb::FAR_POINT);
+    insertPoint(point2D(bigSpan, bigSpan), Vb::FAR_POINT);
+}
+
+
+void Foam::CV2D::fast_restore_Delaunay(Vertex_handle vh)
+{
+    int i;
+    Face_handle f = vh->face(), next, start(f);
+
+    do
+    {
+        i=f->index(vh);
+        if (!is_infinite(f))
+        {
+            if (!internal_flip(f, cw(i))) external_flip(f, i);
+            if (f->neighbor(i) == start) start = f;
+        }
+        f = f->neighbor(cw(i));
+    } while (f != start);
+}
+
+void Foam::CV2D::external_flip(Face_handle& f, int i)
+{
+    Face_handle n = f->neighbor(i);
+
+    if
+    (
+        CGAL::ON_POSITIVE_SIDE
+     != side_of_oriented_circle(n, f->vertex(i)->point())
+    ) return;
+
+    flip(f, i);
+    i = n->index(f->vertex(i));
+    external_flip(n, i);
+}
+
+bool Foam::CV2D::internal_flip(Face_handle& f, int i)
+{
+    Face_handle n = f->neighbor(i);
+
+    if
+    (
+        CGAL::ON_POSITIVE_SIDE
+     != side_of_oriented_circle(n, f->vertex(i)->point())
+    )
+    {
+        return false;
+    }
+
+    flip(f, i);
+
+    return true;
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::CV2D::CV2D
+(
+    const Time& runTime,
+    const dictionary& cvMeshDict
+)
+:
+    Delaunay(),
+    runTime_(runTime),
+    rndGen_(64293*Pstream::myProcNo()),
+    allGeometry_
+    (
+        IOobject
+        (
+            "cvSearchableSurfaces",
+            runTime_.constant(),
+            "triSurface",
+            runTime_,
+            IOobject::MUST_READ,
+            IOobject::NO_WRITE
+        ),
+        cvMeshDict.subDict("geometry")
+    ),
+    qSurf_
+    (
+        runTime_,
+        rndGen_,
+        allGeometry_,
+        cvMeshDict.subDict("surfaceConformation")
+    ),
+    controls_(cvMeshDict, qSurf_.globalBounds()),
+    cellSizeControl_
+    (
+        allGeometry_,
+        cvMeshDict.subDict("motionControl")
+    ),
+    z_
+    (
+        point
+        (
+            cvMeshDict.subDict("surfaceConformation").lookup("locationInMesh")
+        ).z()
+    ),
+    startOfInternalPoints_(0),
+    startOfSurfacePointPairs_(0),
+    startOfBoundaryConformPointPairs_(0),
+    featurePoints_()
+{
+    Info<< meshControls() << endl;
+
+    insertBoundingBox();
+    insertFeaturePoints();
+}
+
+
+// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
+
+Foam::CV2D::~CV2D()
+{}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+void Foam::CV2D::insertPoints
+(
+    const point2DField& points,
+    const scalar nearness
+)
+{
+    Info<< "insertInitialPoints(const point2DField& points): ";
+
+    startOfInternalPoints_ = number_of_vertices();
+    label nVert = startOfInternalPoints_;
+
+    // Add the points and index them
+    forAll(points, i)
+    {
+        const point2D& p = points[i];
+
+        if (qSurf_.wellInside(toPoint3D(p), nearness))
+        {
+            insert(toPoint(p))->index() = nVert++;
+        }
+        else
+        {
+            Warning
+                << "Rejecting point " << p << " outside surface" << endl;
+        }
+    }
+
+    Info<< nVert << " vertices inserted" << endl;
+
+    if (meshControls().objOutput())
+    {
+        // Checking validity of triangulation
+        assert(is_valid());
+
+        writeTriangles("initial_triangles.obj", true);
+        writeFaces("initial_faces.obj", true);
+    }
+}
+
+
+void Foam::CV2D::insertPoints(const fileName& pointFileName)
+{
+    IFstream pointsFile(pointFileName);
+
+    if (pointsFile.good())
+    {
+        insertPoints
+        (
+            point2DField(pointsFile),
+            0.5*meshControls().minCellSize2()
+        );
+    }
+    else
+    {
+        FatalErrorIn("insertInitialPoints")
+            << "Could not open pointsFile " << pointFileName
+            << exit(FatalError);
+    }
+}
+
+
+void Foam::CV2D::insertGrid()
+{
+    Info<< "insertInitialGrid: ";
+
+    startOfInternalPoints_ = number_of_vertices();
+    label nVert = startOfInternalPoints_;
+
+    scalar x0 = qSurf_.globalBounds().min().x();
+    scalar xR = qSurf_.globalBounds().max().x() - x0;
+    int ni = int(xR/meshControls().minCellSize()) + 1;
+    scalar deltax = xR/ni;
+
+    scalar y0 = qSurf_.globalBounds().min().y();
+    scalar yR = qSurf_.globalBounds().max().y() - y0;
+    int nj = int(yR/meshControls().minCellSize()) + 1;
+    scalar deltay = yR/nj;
+
+    Random rndGen(1321);
+    scalar pert = meshControls().randomPerturbation()*min(deltax, deltay);
+
+    for (int i=0; i<ni; i++)
+    {
+        for (int j=0; j<nj; j++)
+        {
+            point p(x0 + i*deltax, y0 + j*deltay, 0);
+
+            if (meshControls().randomiseInitialGrid())
+            {
+                p.x() += pert*(rndGen.scalar01() - 0.5);
+                p.y() += pert*(rndGen.scalar01() - 0.5);
+            }
+
+            if (qSurf_.wellInside(p, 0.5*meshControls().minCellSize2()))
+            {
+                insert(Point(p.x(), p.y()))->index() = nVert++;
+            }
+        }
+    }
+
+    Info<< nVert << " vertices inserted" << endl;
+
+    if (meshControls().objOutput())
+    {
+        // Checking validity of triangulation
+        assert(is_valid());
+
+        writeTriangles("initial_triangles.obj", true);
+        writeFaces("initial_faces.obj", true);
+    }
+}
+
+
+void Foam::CV2D::insertSurfacePointPairs()
+{
+    startOfSurfacePointPairs_ = number_of_vertices();
+
+    if (meshControls().insertSurfaceNearestPointPairs())
+    {
+        insertSurfaceNearestPointPairs();
+    }
+
+    write("nearest");
+
+    // Insertion of point-pairs for near-points may cause protrusions
+    // so insertBoundaryConformPointPairs must be executed last
+    if (meshControls().insertSurfaceNearPointPairs())
+    {
+        insertSurfaceNearPointPairs();
+    }
+
+    startOfBoundaryConformPointPairs_ = number_of_vertices();
+}
+
+
+void Foam::CV2D::boundaryConform()
+{
+    if (!meshControls().insertSurfaceNearestPointPairs())
+    {
+        markNearBoundaryPoints();
+    }
+
+    // Mark all the faces as SAVE_CHANGED
+    for
+    (
+        Triangulation::Finite_faces_iterator fit = finite_faces_begin();
+        fit != finite_faces_end();
+        fit++
+    )
+    {
+        fit->faceIndex() = Fb::SAVE_CHANGED;
+    }
+
+    for (label iter=1; iter<=meshControls().maxBoundaryConformingIter(); iter++)
+    {
+        label nIntersections = insertBoundaryConformPointPairs
+        (
+            "surfaceIntersections_" + Foam::name(iter) + ".obj"
+        );
+
+        if (nIntersections == 0)
+        {
+            break;
+        }
+        else
+        {
+            Info<< "BC iteration " << iter << ": "
+                << nIntersections << " point-pairs inserted" << endl;
+        }
+
+        // Any faces changed by insertBoundaryConformPointPairs will now
+        // be marked CHANGED, mark those as SAVE_CHANGED and those that
+        // remained SAVE_CHANGED as UNCHANGED
+        for
+        (
+            Triangulation::Finite_faces_iterator fit = finite_faces_begin();
+            fit != finite_faces_end();
+            fit++
+        )
+        {
+            if (fit->faceIndex() == Fb::SAVE_CHANGED)
+            {
+                fit->faceIndex() = Fb::UNCHANGED;
+            }
+            else if (fit->faceIndex() == Fb::CHANGED)
+            {
+                fit->faceIndex() = Fb::SAVE_CHANGED;
+            }
+        }
+    }
+
+    Info<< nl;
+
+    write("boundary");
+}
+
+
+void Foam::CV2D::removeSurfacePointPairs()
+{
+    for
+    (
+        Triangulation::Finite_vertices_iterator vit = finite_vertices_begin();
+        vit != finite_vertices_end();
+        ++vit
+    )
+    {
+        if (vit->index() >= startOfSurfacePointPairs_)
+        {
+            remove(vit);
+        }
+    }
+}
+
+
+void Foam::CV2D::newPoints(const scalar relaxation)
+{
+    Info<< "newPointsFromVertices: ";
+
+    Field<point2D> dualVertices(number_of_faces());
+
+    label dualVerti = 0;
+
+    // Find the dual point of each tetrahedron and assign it an index.
+    for
+    (
+        Triangulation::Finite_faces_iterator fit = finite_faces_begin();
+        fit != finite_faces_end();
+        ++fit
+    )
+    {
+        fit->faceIndex() = -1;
+
+        if
+        (
+            fit->vertex(0)->internalOrBoundaryPoint()
+         || fit->vertex(1)->internalOrBoundaryPoint()
+         || fit->vertex(2)->internalOrBoundaryPoint()
+        )
+        {
+            fit->faceIndex() = dualVerti;
+
+            dualVertices[dualVerti] = toPoint2D(circumcenter(fit));
+
+            dualVerti++;
+        }
+    }
+
+    dualVertices.setSize(dualVerti);
+
+    Field<vector2D> displacementAccumulator
+    (
+        startOfSurfacePointPairs_,
+        vector2D::zero
+    );
+
+    // Calculate target size and alignment for vertices
+    scalarField sizes
+    (
+        number_of_vertices(),
+        meshControls().minCellSize()
+    );
+
+    Field<vector2D> alignments
+    (
+        number_of_vertices(),
+        vector2D(1, 0)
+    );
+
+    for
+    (
+        Triangulation::Finite_vertices_iterator vit = finite_vertices_begin();
+        vit != finite_vertices_end();
+        ++vit
+    )
+    {
+        if (vit->internalOrBoundaryPoint())
+        {
+            point2D vert = toPoint2D(vit->point());
+
+            // alignment and size determination
+            pointIndexHit pHit;
+            label hitSurface = -1;
+
+            qSurf_.findSurfaceNearest
+            (
+                toPoint3D(vert),
+                meshControls().span2(),
+                pHit,
+                hitSurface
+            );
+
+            if (pHit.hit())
+            {
+                vectorField norm(1);
+                allGeometry_[hitSurface].getNormal
+                (
+                    List<pointIndexHit>(1, pHit),
+                    norm
+                );
+
+                alignments[vit->index()] = toPoint2D(norm[0]);
+
+                sizes[vit->index()] =
+                    cellSizeControl_.cellSize(toPoint3D(vit->point()));
+            }
+        }
+    }
+
+    // Info<< "Calculated alignments" << endl;
+
+    scalar cosAlignmentAcceptanceAngle = 0.68;
+
+    // Upper and lower edge length ratios for weight
+    scalar u = 1.0;
+    scalar l = 0.7;
+
+    PackedBoolList pointToBeRetained(startOfSurfacePointPairs_, true);
+
+    std::list<Point> pointsToInsert;
+
+    for
+    (
+        Triangulation::Finite_edges_iterator eit = finite_edges_begin();
+        eit != finite_edges_end();
+        eit++
+    )
+    {
+        Vertex_handle vA = eit->first->vertex(cw(eit->second));
+        Vertex_handle vB = eit->first->vertex(ccw(eit->second));
+
+        if (!vA->internalOrBoundaryPoint() || !vB->internalOrBoundaryPoint())
+        {
+            continue;
+        }
+
+        const point2D& dualV1 = dualVertices[eit->first->faceIndex()];
+        const point2D& dualV2 =
+            dualVertices[eit->first->neighbor(eit->second)->faceIndex()];
+
+        scalar dualEdgeLength = mag(dualV1 - dualV2);
+
+        point2D dVA = toPoint2D(vA->point());
+        point2D dVB = toPoint2D(vB->point());
+
+        Field<vector2D> alignmentDirsA(2);
+
+        alignmentDirsA[0] = alignments[vA->index()];
+        alignmentDirsA[1] = vector2D
+        (
+           -alignmentDirsA[0].y(),
+            alignmentDirsA[0].x()
+        );
+
+        Field<vector2D> alignmentDirsB(2);
+
+        alignmentDirsB[0] = alignments[vB->index()];
+        alignmentDirsB[1] = vector2D
+        (
+           -alignmentDirsB[0].y(),
+            alignmentDirsB[0].x()
+        );
+
+        Field<vector2D> alignmentDirs(2);
+
+        forAll(alignmentDirsA, aA)
+        {
+            const vector2D& a(alignmentDirsA[aA]);
+
+            scalar maxDotProduct = 0.0;
+
+            forAll(alignmentDirsB, aB)
+            {
+                const vector2D& b(alignmentDirsB[aB]);
+
+                scalar dotProduct = a & b;
+
+                if (mag(dotProduct) > maxDotProduct)
+                {
+                    maxDotProduct = mag(dotProduct);
+
+                    alignmentDirs[aA] = a + sign(dotProduct)*b;
+
+                    alignmentDirs[aA] /= mag(alignmentDirs[aA]);
+                }
+            }
+        }
+
+        vector2D rAB = dVA - dVB;
+
+        scalar rABMag = mag(rAB);
+
+        forAll(alignmentDirs, aD)
+        {
+            vector2D& alignmentDir = alignmentDirs[aD];
+
+            if ((rAB & alignmentDir) < 0)
+            {
+                // swap the direction of the alignment so that has the
+                // same sense as rAB
+                alignmentDir *= -1;
+            }
+
+            scalar alignmentDotProd = ((rAB/rABMag) & alignmentDir);
+
+            if (alignmentDotProd > cosAlignmentAcceptanceAngle)
+            {
+                scalar targetFaceSize =
+                    0.5*(sizes[vA->index()] + sizes[vB->index()]);
+
+                // Test for changing aspect ratio on second alignment (first
+                // alignment is neartest surface normal)
+                // if (aD == 1)
+                // {
+                //     targetFaceSize *= 2.0;
+                // }
+
+                alignmentDir *= 0.5*targetFaceSize;
+
+                vector2D delta = alignmentDir - 0.5*rAB;
+
+                if (dualEdgeLength < 0.7*targetFaceSize)
+                {
+                    delta *= 0;
+                }
+                else if (dualEdgeLength < targetFaceSize)
+                {
+                    delta *=
+                        (
+                            dualEdgeLength
+                           /(targetFaceSize*(u - l))
+                          - 1/((u/l) - 1)
+                        );
+                }
+
+                if
+                (
+                    vA->internalPoint()
+                 && vB->internalPoint()
+                 && rABMag > 1.75*targetFaceSize
+                 && dualEdgeLength > 0.05*targetFaceSize
+                 && alignmentDotProd > 0.93
+                )
+                {
+                    // Point insertion
+                    pointsToInsert.push_back(toPoint(0.5*(dVA + dVB)));
+                }
+                else if
+                (
+                    (vA->internalPoint() || vB->internalPoint())
+                 && rABMag < 0.65*targetFaceSize
+                )
+                {
+                    // Point removal
+
+                    // Only insert a point at the midpoint of the short edge
+                    // if neither attached point has already been identified
+                    // to be removed.
+                    if
+                    (
+                        pointToBeRetained[vA->index()] == true
+                     && pointToBeRetained[vB->index()] == true
+                    )
+                    {
+                        pointsToInsert.push_back(toPoint(0.5*(dVA + dVB)));
+                    }
+
+                    if (vA->internalPoint())
+                    {
+                        pointToBeRetained[vA->index()] = false;
+                    }
+
+                    if (vB->internalPoint())
+                    {
+                        pointToBeRetained[vB->index()] = false;
+                    }
+                }
+                else
+                {
+                    if (vA->internalPoint())
+                    {
+                        displacementAccumulator[vA->index()] += delta;
+                    }
+
+                    if (vB->internalPoint())
+                    {
+                        displacementAccumulator[vB->index()] += -delta;
+                    }
+                }
+            }
+        }
+    }
+
+    vector2D totalDisp = sum(displacementAccumulator);
+    scalar totalDist = sum(mag(displacementAccumulator));
+
+    // Relax the calculated displacement
+    displacementAccumulator *= relaxation;
+
+    label numberOfNewPoints = pointsToInsert.size();
+
+    for
+    (
+        Triangulation::Finite_vertices_iterator vit = finite_vertices_begin();
+        vit != finite_vertices_end();
+        ++vit
+    )
+    {
+        if (vit->internalPoint())
+        {
+            if (pointToBeRetained[vit->index()])
+            {
+                pointsToInsert.push_front
+                (
+                    toPoint
+                    (
+                        toPoint2D(vit->point())
+                      + displacementAccumulator[vit->index()]
+                    )
+                );
+            }
+        }
+    }
+
+    // Clear the triangulation and reinsert the bounding box and feature points.
+    // This is faster than removing and moving points.
+    this->clear();
+
+    insertBoundingBox();
+
+    reinsertFeaturePoints();
+
+    startOfInternalPoints_ = number_of_vertices();
+
+    label nVert = startOfInternalPoints_;
+
+    Info<< "Inserting " << numberOfNewPoints << " new points" << endl;
+
+    // Use the range insert as it is faster than individually inserting points.
+    insert(pointsToInsert.begin(), pointsToInsert.end());
+
+    for
+    (
+        Delaunay::Finite_vertices_iterator vit = finite_vertices_begin();
+        vit != finite_vertices_end();
+        ++vit
+    )
+    {
+        if
+        (
+            vit->type() == Vb::INTERNAL_POINT
+         && vit->index() == Vb::INTERNAL_POINT
+        )
+        {
+            vit->index() = nVert++;
+        }
+    }
+
+    Info<< "    Total displacement = " << totalDisp << nl
+        << "    Total distance = " << totalDist << nl
+        << "    Points added = " << pointsToInsert.size()
+        << endl;
+
+    write("internal");
+
+    insertSurfacePointPairs();
+
+    boundaryConform();
+
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Old Method
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+// for
+// (
+//     Triangulation::Finite_vertices_iterator vit = finite_vertices_begin();
+//     vit != finite_vertices_end();
+//     ++vit
+// )
+// {
+//     if (vit->internalPoint())
+//     {
+//         // Current dual-cell defining vertex ("centre")
+//         point2DFromPoint defVert0 = toPoint2D(vit->point());
+
+//         Triangulation::Edge_circulator ec = incident_edges(vit);
+//         Triangulation::Edge_circulator ecStart = ec;
+
+//         // Circulate around the edges to find the first which is not
+//         // infinite
+//         do
+//         {
+//             if (!is_infinite(ec)) break;
+//         } while (++ec != ecStart);
+
+//         // Store the start-end of the first non-infinte edge
+//         point2D de0 = toPoint2D(circumcenter(ec->first));
+
+//         // Keep track of the maximum edge length^2
+//         scalar maxEdgeLen2 = 0.0;
+
+//         // Keep track of the index of the longest edge
+//         label edgecd0i = -1;
+
+//         // Edge counter
+//         label edgei = 0;
+
+//         do
+//         {
+//             if (!is_infinite(ec))
+//             {
+//                 // Get the end of the current edge
+//                 point2D de1 = toPoint2D
+//                 (
+//                     circumcenter(ec->first->neighbor(ec->second))
+//                 );
+
+//                 // Store the current edge vector
+//                 edges[edgei] = de1 - de0;
+
+//                 // Store the edge mid-point in the vertices array
+//                 vertices[edgei] = 0.5*(de1 + de0);
+
+//                 // Move the current edge end into the edge start for the
+//                 // next iteration
+//                 de0 = de1;
+
+//                 // Keep track of the longest edge
+
+//                 scalar edgeLen2 = magSqr(edges[edgei]);
+
+//                 if (edgeLen2 > maxEdgeLen2)
+//                 {
+//                     maxEdgeLen2 = edgeLen2;
+//                     edgecd0i = edgei;
+//                 }
+
+//                 edgei++;
+//             }
+//         } while (++ec != ecStart);
+
+//         // Initialise cd0 such that the mesh will align
+//         // in in the x-y directions
+//         vector2D cd0(1, 0);
+
+//         if (meshControls().relaxOrientation())
+//         {
+//             // Get the longest edge from the array and use as the primary
+//             // direction of the coordinate system of the "square" cell
+//             cd0 = edges[edgecd0i];
+//         }
+
+//         if (meshControls().nearWallAlignedDist() > 0)
+//         {
+//             pointIndexHit pHit = qSurf_.tree().findNearest
+//             (
+//                 toPoint3D(defVert0),
+//                 meshControls().nearWallAlignedDist2()
+//             );
+
+//             if (pHit.hit())
+//             {
+//                 cd0 = toPoint2D(faceNormals[pHit.index()]);
+//             }
+//         }
+
+//         // Rotate by 45deg needed to create an averaging procedure which
+//         // encourages the cells to be square
+//         cd0 = vector2D(cd0.x() + cd0.y(), cd0.y() - cd0.x());
+
+//         // Normalise the primary coordinate direction
+//         cd0 /= mag(cd0);
+
+//         // Calculate the orthogonal coordinate direction
+//         vector2D cd1(-cd0.y(), cd0.x());
+
+
+//         // Restart the circulator
+//         ec = ecStart;
+
+//         // ... and the counter
+//         edgei = 0;
+
+//         // Initialise the displacement for the centre and sum-weights
+//         vector2D disp = vector2D::zero;
+//         scalar sumw = 0;
+
+//         do
+//         {
+//             if (!is_infinite(ec))
+//             {
+//                 // Pick up the current edge
+//                 const vector2D& ei = edges[edgei];
+
+//                 // Calculate the centre to edge-centre vector
+//                 vector2D deltai = vertices[edgei] - defVert0;
+
+//                 // Set the weight for this edge contribution
+//                 scalar w = 1;
+
+//                 if (meshControls().squares())
+//                 {
+//                     w = magSqr(deltai.x()*ei.y() - deltai.y()*ei.x());
+//                     // alternative weights
+//                     //w = mag(deltai.x()*ei.y() - deltai.y()*ei.x());
+//                     //w = magSqr(ei)*mag(deltai);
+
+//                     // Use the following for an ~square mesh
+//                     // Find the coordinate contributions for this edge delta
+//                     scalar cd0deltai = cd0 & deltai;
+//                     scalar cd1deltai = cd1 & deltai;
+
+//                     // Create a "square" displacement
+//                     if (mag(cd0deltai) > mag(cd1deltai))
+//                     {
+//                         disp += (w*cd0deltai)*cd0;
+//                     }
+//                     else
+//                     {
+//                         disp += (w*cd1deltai)*cd1;
+//                     }
+//                 }
+//                 else
+//                 {
+//                     // Use this for a hexagon/pentagon mesh
+//                     disp += w*deltai;
+//                 }
+
+//                 // Sum the weights
+//                 sumw += w;
+//             }
+//             else
+//             {
+//                 FatalErrorIn("CV2D::newPoints() const")
+//                     << "Infinite triangle found in internal mesh"
+//                     << exit(FatalError);
+//             }
+
+//             edgei++;
+
+//         } while (++ec != ecStart);
+
+//         // Calculate the average displacement
+//         disp /= sumw;
+//         totalDisp += disp;
+//         totalDist += mag(disp);
+
+//         // Move the point by a fraction of the average displacement
+//         movePoint(vit, defVert0 + relaxation*disp);
+//     }
+// }
+
+// Info << "\nTotal displacement = " << totalDisp
+//      << " total distance = " << totalDist << endl;
+}
+
+
+//void Foam::CV2D::moveInternalPoints(const point2DField& newPoints)
+//{
+//    label pointI = 0;
+
+//    for
+//    (
+//        Triangulation::Finite_vertices_iterator vit = finite_vertices_begin();
+//        vit != finite_vertices_end();
+//        ++vit
+//    )
+//    {
+//        if (vit->internalPoint())
+//        {
+//            movePoint(vit, newPoints[pointI++]);
+//        }
+//    }
+//}
+
+
+void Foam::CV2D::extractPatches
+(
+    wordList& patchNames,
+    labelList& patchSizes,
+    EdgeMap<label>& mapEdgesRegion
+) const
+{
+    label nPatches = qSurf_.patchNames().size() + 1;
+    label defaultPatchIndex = qSurf_.patchNames().size();
+
+    patchNames.setSize(nPatches);
+    patchSizes.setSize(nPatches, 0);
+    mapEdgesRegion.clear();
+
+    const wordList& existingPatches = qSurf_.patchNames();
+
+    forAll(existingPatches, sP)
+    {
+        patchNames[sP] = existingPatches[sP];
+    }
+
+    patchNames[defaultPatchIndex] = "CV2D_default_patch";
+
+    for
+    (
+        Triangulation::Finite_edges_iterator eit = finite_edges_begin();
+        eit != finite_edges_end();
+        ++eit
+    )
+    {
+        Face_handle fOwner = eit->first;
+        Face_handle fNeighbor = fOwner->neighbor(eit->second);
+
+        Vertex_handle vA = fOwner->vertex(cw(eit->second));
+        Vertex_handle vB = fOwner->vertex(ccw(eit->second));
+
+        if
+        (
+            (vA->internalOrBoundaryPoint() && !vB->internalOrBoundaryPoint())
+         || (vB->internalOrBoundaryPoint() && !vA->internalOrBoundaryPoint())
+        )
+        {
+            point ptA = toPoint3D(vA->point());
+            point ptB = toPoint3D(vB->point());
+
+            label patchIndex = qSurf_.findPatch(ptA, ptB);
+
+            if (patchIndex == -1)
+            {
+                patchIndex = defaultPatchIndex;
+
+                WarningIn("Foam::CV2D::extractPatches")
+                    << "Dual face found that is not on a surface "
+                    << "patch. Adding to CV2D_default_patch."
+                    << endl;
+            }
+
+            edge e(fOwner->faceIndex(), fNeighbor->faceIndex());
+            patchSizes[patchIndex]++;
+            mapEdgesRegion.insert(e, patchIndex);
+        }
+    }
+}
+
+
+void Foam::CV2D::write() const
+{
+    if (meshControls().objOutput())
+    {
+        writeFaces("allFaces.obj", false);
+        writeFaces("faces.obj", true);
+        writeTriangles("allTriangles.obj", false);
+        writeTriangles("triangles.obj", true);
+        writePatch("patch.pch");
+    }
+}
+
+
+void Foam::CV2D::write(const word& stage) const
+{
+    if (meshControls().objOutput())
+    {
+        Foam::mkDir(stage + "Faces");
+        Foam::mkDir(stage + "Triangles");
+
+        writeFaces
+        (
+            stage
+          + "Faces/allFaces_"
+          + runTime_.timeName()
+          + ".obj",
+            false
+        );
+
+        writeTriangles
+        (
+            stage
+          + "Triangles/allTriangles_"
+          + runTime_.timeName()
+          + ".obj",
+            false
+        );
+    }
+}
+
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/cv2DMesh/CV2D.H b/applications/utilities/mesh/generation/cv2DMesh/CV2D.H
new file mode 100644
index 0000000000000000000000000000000000000000..305420e73f9c6d6ffb3bbb5d784c40dd349c6bb0
--- /dev/null
+++ b/applications/utilities/mesh/generation/cv2DMesh/CV2D.H
@@ -0,0 +1,471 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2007-2011 OpenFOAM Foundation
+     \\/     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
+    CV2D
+
+Description
+    Conformal-Voronoi 2D automatic mesher with grid or read initial points
+    and point position relaxation with optional "squarification".
+
+    There are a substantial number of options to this mesher read from
+    CV2DMesherDict file e.g.:
+
+    // Min cell size used in tolerances when inserting points for
+    // boundary conforming.
+    // Also used to as the grid spacing usind in insertGrid.
+    minCellSize  0.05;
+
+    // Feature angle used to inser feature points
+    // 0 = all features, 180 = no features
+    featureAngle 45;
+
+    // Maximum quadrant angle allowed at a concave corner before
+    // additional "mitering" lines are added
+    maxQuadAngle 110;
+
+    // Should the mesh be square-dominated or of unbiased hexagons
+    squares      yes;
+
+    // Near-wall region where cells are aligned with the wall specified as a
+    // number of cell layers
+    nearWallAlignedDist 3;
+
+    // Chose if the cell orientation should relax during the iterations
+    //  or remain fixed to the x-y directions
+    relaxOrientation    no;
+
+    // Insert near-boundary point mirror or point-pairs
+    insertSurfaceNearestPointPairs yes;
+
+    // Mirror near-boundary points rather than insert point-pairs
+    mirrorPoints   no;
+
+    // Insert point-pairs vor dual-cell vertices very near the surface
+    insertSurfaceNearPointPairs yes;
+
+    // Choose if to randomise the initial grid created by insertGrid.
+    randomiseInitialGrid yes;
+
+    // Perturbation fraction, 1 = cell-size.
+    randomPurturbation   0.1;
+
+    // Number of relaxation iterations.
+    nIterations      5;
+
+    // Relaxation factor at the start of the iteration sequence.
+    // 0.5 is a sensible maximum and < 0.2 converges better.
+    relaxationFactorStart 0.8;
+
+    // Relaxation factor at the end of the iteration sequence.
+    // Should be <= relaxationFactorStart
+    relaxationFactorEnd   0;
+
+    writeInitialTriangulation no;
+    writeFeatureTriangulation no;
+    writeNearestTriangulation no;
+    writeInsertedPointPairs   no;
+    writeFinalTriangulation   yes;
+
+    // Maximum number of iterations used in boundaryConform.
+    maxBoundaryConformingIter 5;
+
+    minEdgeLenCoeff           0.5;
+    maxNotchLenCoeff          0.3;
+    minNearPointDistCoeff     0.25;
+    ppDistCoeff               0.05;
+
+SourceFiles
+    CGALTriangulation2Ddefs.H
+    indexedVertex.H
+    indexedFace.H
+    CV2DI.H
+    CV2D.C
+    CV2DIO.C
+    tolerances.C
+    controls.C
+    insertFeaturePoints.C
+    insertSurfaceNearestPointPairs.C
+    insertSurfaceNearPointPairs.C
+    insertBoundaryConformPointPairs.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef CV2D_H
+#define CV2D_H
+
+#define CGAL_INEXACT
+#define CGAL_HIERARCHY
+
+#include "CGALTriangulation2Ddefs.H"
+
+#include "Time.H"
+#include "point2DFieldFwd.H"
+#include "dictionary.H"
+#include "Switch.H"
+#include "PackedBoolList.H"
+#include "EdgeMap.H"
+#include "cv2DControls.H"
+#include "tolerances.H"
+#include "meshTools.H"
+#include "triSurface.H"
+#include "searchableSurfaces.H"
+#include "conformationSurfaces.H"
+#include "cellSizeControlSurfaces.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+/*---------------------------------------------------------------------------*\
+                           Class CV2D Declaration
+\*---------------------------------------------------------------------------*/
+
+class CV2D
+:
+    public Delaunay
+{
+
+private:
+
+    // Private data
+
+        //- The time registry of the application
+        const Time& runTime_;
+
+        mutable Random rndGen_;
+
+        //- The surface to mesh
+        //const querySurface& qSurf_;
+        //- All geometry of the meshing process, including surfaces to be
+        //  conformed to and those to be used for refinement
+        searchableSurfaces allGeometry_;
+
+        conformationSurfaces qSurf_;
+
+        //- Meshing controls
+        cv2DControls controls_;
+
+        //- The cell size control object
+        cellSizeControlSurfaces cellSizeControl_;
+
+        //- z-level
+        scalar z_;
+
+        //- Keep track of the start of the internal points
+        label startOfInternalPoints_;
+
+        //- Keep track of the start of the surface point-pairs
+        label startOfSurfacePointPairs_;
+
+        //- Keep track of the boundary conform point-pairs
+        //  stored after the insertion of the surface point-pairs in case
+        //  the boundary conform function is called more than once without
+        //  removing and insertin the surface point-pairs
+        label startOfBoundaryConformPointPairs_;
+
+        //- Store the feature points
+        std::list<Vb> featurePoints_;
+
+        //- Temporary storage for a dual-cell
+        static const label maxNvert = 20;
+        mutable point2D vertices[maxNvert+1];
+        mutable vector2D edges[maxNvert+1];
+
+
+    // Private Member Functions
+
+        //- Disallow default bitwise copy construct
+        CV2D(const CV2D&);
+
+        //- Disallow default bitwise assignment
+        void operator=(const CV2D&);
+
+
+        //- Insert point and return it's index
+        inline label insertPoint
+        (
+            const point2D& pt,
+            const label type
+        );
+
+        //- Insert point and return it's index
+        inline label insertPoint
+        (
+            const point2D& pt,
+            const label index,
+            const label type
+        );
+
+        inline label insertPoint
+        (
+            const Point& p,
+            const label index,
+            const label type
+        );
+
+        inline bool insertMirrorPoint
+        (
+            const point2D& nearSurfPt,
+            const point2D& surfPt
+        );
+
+        //- Insert a point-pair at a distance ppDist either side of
+        //  surface point point surfPt in the direction n
+        inline void insertPointPair
+        (
+            const scalar mirrorDist,
+            const point2D& surfPt,
+            const vector2D& n
+        );
+
+        //- Create the initial mesh from the bounding-box
+        void insertBoundingBox();
+
+        //- Check if a point is within a line.
+        bool on2DLine(const point2D& p, const linePointRef& line);
+
+        //- Insert point groups at the feature points.
+        void insertFeaturePoints();
+
+        //- Re-insert point groups at the feature points.
+        void reinsertFeaturePoints();
+
+        //- Insert point-pairs at the given set of points using the surface
+        //  normals corresponding to the given set of surface triangles
+        //  and write the inserted point locations to the given file.
+        void insertPointPairs
+        (
+            const DynamicList<point2D>& nearSurfacePoints,
+            const DynamicList<point2D>& surfacePoints,
+            const DynamicList<label>& surfaceTris,
+            const DynamicList<label>& surfaceHits,
+            const fileName fName
+        );
+
+        //- Check to see if dual cell specified by given vertex iterator
+        //  intersects the boundary and hence reqires a point-pair.
+        bool dualCellSurfaceIntersection
+        (
+            const Triangulation::Finite_vertices_iterator& vit
+        ) const;
+
+        //- Insert point-pairs at the nearest points on the surface to the
+        //  control vertex of dual-cells which intersect the boundary in order
+        //  to provide a boundary-layer mesh.
+        //  NB: This is not guaranteed to close the boundary
+        void insertSurfaceNearestPointPairs();
+
+        //- Insert point-pairs at small dual-cell edges on the surface in order
+        //  to improve the boundary-layer mesh generated by
+        //  insertSurfaceNearestPointPairs.
+        void insertSurfaceNearPointPairs();
+
+        //- Insert point-pair and correcting the Finite_vertices_iterator
+        //  to account for the additional vertices
+        void insertPointPair
+        (
+            Triangulation::Finite_vertices_iterator& vit,
+            const point2D& p,
+            const label trii,
+            const label hitSurface
+        );
+
+        //- Insert point-pair at the best intersection point between the lines
+        //  from the dual-cell real centroid and it's vertices and the surface.
+        bool insertPointPairAtIntersection
+        (
+            Triangulation::Finite_vertices_iterator& vit,
+            const point2D& defVert,
+            const point2D vertices[],
+            const scalar maxProtSize
+        );
+
+        //- Insert point-pairs corresponding to dual-cells which intersect
+        //  the boundary surface
+        label insertBoundaryConformPointPairs(const fileName& fName);
+
+        void markNearBoundaryPoints();
+
+        //- Restore the Delaunay contraint
+        void fast_restore_Delaunay(Vertex_handle vh);
+
+        // Flip operations used by fast_restore_Delaunay
+        void external_flip(Face_handle& f, int i);
+        bool internal_flip(Face_handle& f, int i);
+
+        //- Write all the faces and all the triangles at a particular stage.
+        void write(const word& stage) const;
+
+
+public:
+
+        //- Runtime type information
+        ClassName("CV2D");
+
+
+    // Constructors
+
+        //- Construct for given surface
+        CV2D
+        (
+            const Time& runTime,
+            const dictionary& controlDict
+        );
+
+
+    //- Destructor
+    ~CV2D();
+
+
+    // Member Functions
+
+        // Access
+
+            inline const cv2DControls& meshControls() const;
+
+
+        // Conversion functions between point2D, point and Point
+
+            inline const point2D& toPoint2D(const point&) const;
+            inline const point2DField toPoint2D(const pointField&) const;
+            inline point toPoint3D(const point2D&) const;
+
+            #ifdef CGAL_INEXACT
+                typedef const point2D& point2DFromPoint;
+                typedef const Point& PointFromPoint2D;
+            #else
+                typedef point2D point2DFromPoint;
+                typedef Point PointFromPoint2D;
+            #endif
+
+            inline point2DFromPoint toPoint2D(const Point&) const;
+            inline PointFromPoint2D toPoint(const point2D&) const;
+            inline point toPoint3D(const Point&) const;
+
+
+        // Point insertion
+
+            //- Create the initial mesh from the given internal points.
+            //  Points must be inside the boundary by at least nearness
+            //  otherwise they are ignored.
+            void insertPoints
+            (
+                const point2DField& points,
+                const scalar nearness
+            );
+
+            //- Create the initial mesh from the internal points in the given
+            //  file.  Points outside the geometry are ignored.
+            void insertPoints(const fileName& pointFileName);
+
+            //- Create the initial mesh as a regular grid of points.
+            //  Points outside the geometry are ignored.
+            void insertGrid();
+
+            //- Insert all surface point-pairs from
+            //  insertSurfaceNearestPointPairs and
+            //  findIntersectionForOutsideCentroid
+            void insertSurfacePointPairs();
+
+            //- Insert point-pairs where there are protrusions into
+            //  or out of the surface
+            void boundaryConform();
+
+
+        // Point removal
+
+            //- Remove the point-pairs introduced by insertSurfacePointPairs
+            //  and boundaryConform
+            void removeSurfacePointPairs();
+
+
+        // Point motion
+
+            inline void movePoint(const Vertex_handle& vh, const Point& P);
+
+            //- Move the internal points to the given new locations and update
+            //  the triangulation to ensure it is Delaunay
+            // void moveInternalPoints(const point2DField& newPoints);
+
+            //- Calculate the displacements to create the new points
+            void newPoints(const scalar relaxation);
+
+            //- Extract patch names and sizes.
+            void extractPatches
+            (
+                wordList& patchNames,
+                labelList& patchSizes,
+                EdgeMap<label>& mapEdgesRegion
+            ) const;
+
+        // Write
+
+            //- Write internal points to .obj file
+            void writePoints(const fileName& fName, bool internalOnly) const;
+
+            //- Write triangles as .obj file
+            void writeTriangles(const fileName& fName, bool internalOnly) const;
+
+            //- Write dual faces as .obj file
+            void writeFaces(const fileName& fName, bool internalOnly) const;
+
+            //- Calculates dual points (circumcentres of tets) and faces
+            //  (point-cell walk of tets).
+            //  Returns:
+            //  - dualPoints (in triangle ordering)
+            //  - dualFaces (compacted)
+            void calcDual
+            (
+                point2DField& dualPoints,
+                faceList& dualFaces,
+                wordList& patchNames,
+                labelList& patchSizes,
+                EdgeMap<label>& mapEdgesRegion
+            ) const;
+
+            //- Write patch
+            void writePatch(const fileName& fName) const;
+
+            void write() const;
+};
+
+
+inline bool boundaryTriangle(const CV2D::Face_handle fc);
+inline bool outsideTriangle(const CV2D::Face_handle fc);
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#include "CV2DI.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/cv2DMesh/CV2DI.H b/applications/utilities/mesh/generation/cv2DMesh/CV2DI.H
new file mode 100644
index 0000000000000000000000000000000000000000..c96f47ab45fe877ba77647c48a2ccba8c57af3ee
--- /dev/null
+++ b/applications/utilities/mesh/generation/cv2DMesh/CV2DI.H
@@ -0,0 +1,221 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2007-2011 OpenFOAM Foundation
+     \\/     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/>.
+
+\*---------------------------------------------------------------------------*/
+
+// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
+
+inline Foam::label Foam::CV2D::insertPoint
+(
+    const point2D& p,
+    const label type
+)
+{
+    uint nVert = number_of_vertices();
+
+    return insertPoint(toPoint(p), nVert, type);
+}
+
+
+inline Foam::label Foam::CV2D::insertPoint
+(
+    const point2D& p,
+    const label index,
+    const label type
+)
+{
+    return insertPoint(toPoint(p), index, type);
+}
+
+
+inline Foam::label Foam::CV2D::insertPoint
+(
+    const Point& p,
+    const label index,
+    const label type
+)
+{
+    uint nVert = number_of_vertices();
+
+    Vertex_handle vh = insert(p);
+
+    if (nVert == number_of_vertices())
+    {
+        WarningIn("Foam::CV2D::insertPoint")
+            << "Failed to insert point " << toPoint2D(p) << endl;
+    }
+    else
+    {
+        vh->index() = index;
+        vh->type() = type;
+    }
+
+    return vh->index();
+}
+
+
+inline bool Foam::CV2D::insertMirrorPoint
+(
+    const point2D& nearSurfPt,
+    const point2D& surfPt
+)
+{
+    point2D mirrorPoint(2*surfPt - nearSurfPt);
+
+    if (qSurf_.outside(toPoint3D(mirrorPoint)))
+    {
+        insertPoint(mirrorPoint, Vb::MIRROR_POINT);
+        return true;
+    }
+    else
+    {
+        return false;
+    }
+}
+
+
+inline void Foam::CV2D::insertPointPair
+(
+    const scalar ppDist,
+    const point2D& surfPt,
+    const vector2D& n
+)
+{
+    vector2D ppDistn = ppDist*n;
+
+    label master = insertPoint
+    (
+        surfPt - ppDistn,
+        number_of_vertices() + 1
+    );
+
+    insertPoint(surfPt + ppDistn, master);
+}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+inline const Foam::cv2DControls& Foam::CV2D::meshControls() const
+{
+    return controls_;
+}
+
+inline const Foam::point2D& Foam::CV2D::toPoint2D(const point& p) const
+{
+    return reinterpret_cast<const point2D&>(p);
+}
+
+inline const Foam::point2DField Foam::CV2D::toPoint2D(const pointField& p) const
+{
+    point2DField temp(p.size());
+    forAll(temp, pointI)
+    {
+        temp[pointI] = point2D(p[pointI].x(), p[pointI].y());
+    }
+    return temp;
+}
+
+inline Foam::point Foam::CV2D::toPoint3D(const point2D& p) const
+{
+    return point(p.x(), p.y(), z_);
+}
+
+
+#ifdef CGAL_INEXACT
+
+inline Foam::CV2D::point2DFromPoint Foam::CV2D::toPoint2D(const Point& P) const
+{
+    return reinterpret_cast<point2DFromPoint>(P);
+}
+
+inline Foam::CV2D::PointFromPoint2D Foam::CV2D::toPoint(const point2D& p) const
+{
+    return reinterpret_cast<PointFromPoint2D>(p);
+}
+
+#else
+
+inline Foam::CV2D::point2DFromPoint Foam::CV2D::toPoint2D(const Point& P) const
+{
+    return point2D(CGAL::to_double(P.x()), CGAL::to_double(P.y()));
+}
+
+inline Foam::CV2D::PointFromPoint2D Foam::CV2D::toPoint(const point2D& p) const
+{
+    return Point(p.x(), p.y());
+}
+
+#endif
+
+
+inline Foam::point Foam::CV2D::toPoint3D(const Point& P) const
+{
+    return point(CGAL::to_double(P.x()), CGAL::to_double(P.y()), z_);
+}
+
+
+inline void Foam::CV2D::movePoint(const Vertex_handle& vh, const Point& P)
+{
+    int i = vh->index();
+    int t = vh->type();
+
+    remove(vh);
+
+    Vertex_handle newVh = insert(P);
+
+    newVh->index() = i;
+    newVh->type() = t;
+
+    // label i = vh->index();
+    // move(vh, P);
+    // vh->index() = i;
+
+     //vh->set_point(P);
+     //fast_restore_Delaunay(vh);
+}
+
+
+// * * * * * * * * * * * * * * * Friend Functions  * * * * * * * * * * * * * //
+
+inline bool Foam::boundaryTriangle(const CV2D::Face_handle fc)
+{
+    return boundaryTriangle
+    (
+        *fc->vertex(0),
+        *fc->vertex(1),
+        *fc->vertex(2)
+    );
+}
+
+inline bool Foam::outsideTriangle(const CV2D::Face_handle fc)
+{
+    return outsideTriangle
+    (
+        *fc->vertex(0),
+        *fc->vertex(1),
+        *fc->vertex(2)
+    );
+}
+
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/cv2DMesh/CV2DIO.C b/applications/utilities/mesh/generation/cv2DMesh/CV2DIO.C
new file mode 100644
index 0000000000000000000000000000000000000000..60e4fa6113403596987e913b9bbdfc4c6348d6f9
--- /dev/null
+++ b/applications/utilities/mesh/generation/cv2DMesh/CV2DIO.C
@@ -0,0 +1,304 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2007-2011 OpenFOAM Foundation
+     \\/     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 "CV2D.H"
+#include "OFstream.H"
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+void Foam::CV2D::writePoints(const fileName& fName, bool internalOnly) const
+{
+    Info<< "Writing points to " << fName << nl << endl;
+    OFstream str(fName);
+
+    for
+    (
+        Triangulation::Finite_vertices_iterator vit = finite_vertices_begin();
+        vit != finite_vertices_end();
+        ++vit
+    )
+    {
+        if (!internalOnly || vit->internalOrBoundaryPoint())
+        {
+            meshTools::writeOBJ(str, toPoint3D(vit->point()));
+        }
+    }
+}
+
+
+void Foam::CV2D::writeTriangles(const fileName& fName, bool internalOnly) const
+{
+    Info<< "Writing triangles to " << fName << nl << endl;
+    OFstream str(fName);
+
+    labelList vertexMap(number_of_vertices(), -2);
+    label verti = 0;
+
+    for
+    (
+        Triangulation::Finite_vertices_iterator vit = finite_vertices_begin();
+        vit != finite_vertices_end();
+        ++vit
+    )
+    {
+        if (!internalOnly || !vit->farPoint())
+        {
+            vertexMap[vit->index()] = verti++;
+            meshTools::writeOBJ(str, toPoint3D(vit->point()));
+        }
+    }
+
+    for
+    (
+        Triangulation::Finite_faces_iterator fit = finite_faces_begin();
+        fit != finite_faces_end();
+        ++fit
+    )
+    {
+        if
+        (
+            !internalOnly
+         || (
+                fit->vertex(0)->internalOrBoundaryPoint()
+             || fit->vertex(1)->internalOrBoundaryPoint()
+             || fit->vertex(2)->internalOrBoundaryPoint()
+            )
+        )
+        {
+            str << "f";
+            for (label i = 0; i < 3; ++i)
+            {
+                str << " " << vertexMap[fit->vertex(i)->index()] + 1;
+            }
+            str << nl;
+        }
+    }
+}
+
+
+void Foam::CV2D::writeFaces(const fileName& fName, bool internalOnly) const
+{
+    Info<< "Writing dual faces to " << fName << nl << endl;
+    OFstream str(fName);
+
+    label dualVerti = 0;
+
+    for
+    (
+        Triangulation::Finite_faces_iterator fit = finite_faces_begin();
+        fit != finite_faces_end();
+        ++fit
+    )
+    {
+        if
+        (
+            !internalOnly
+         || (
+                fit->vertex(0)->internalOrBoundaryPoint()
+             || fit->vertex(1)->internalOrBoundaryPoint()
+             || fit->vertex(2)->internalOrBoundaryPoint()
+            )
+        )
+        {
+            fit->faceIndex() = dualVerti++;
+            meshTools::writeOBJ(str, toPoint3D(circumcenter(fit)));
+        }
+        else
+        {
+            fit->faceIndex() = -1;
+        }
+    }
+
+    for
+    (
+        Triangulation::Finite_vertices_iterator vit = finite_vertices_begin();
+        vit != finite_vertices_end();
+        ++vit
+    )
+    {
+        if (!internalOnly || vit->internalOrBoundaryPoint())
+        {
+            Face_circulator fcStart = incident_faces(vit);
+            Face_circulator fc = fcStart;
+
+            str<< 'f';
+
+            do
+            {
+                if (!is_infinite(fc))
+                {
+                    if (fc->faceIndex() < 0)
+                    {
+                        FatalErrorIn
+                        (
+                            "Foam::CV2D::writeFaces"
+                            "(const fileName& fName, bool internalOnly)"
+                        )<< "Dual face uses vertex defined by a triangle"
+                            " defined by an external point"
+                            << exit(FatalError);
+                    }
+
+                    str<< ' ' << fc->faceIndex() + 1;
+                }
+            } while (++fc != fcStart);
+
+            str<< nl;
+        }
+    }
+}
+
+
+void Foam::CV2D::calcDual
+(
+    point2DField& dualPoints,
+    faceList& dualFaces,
+    wordList& patchNames,
+    labelList& patchSizes,
+    EdgeMap<label>& mapEdgesRegion
+) const
+{
+    // Dual points stored in triangle order.
+    dualPoints.setSize(number_of_faces());
+    label dualVerti = 0;
+
+    for
+    (
+        Triangulation::Finite_faces_iterator fit = finite_faces_begin();
+        fit != finite_faces_end();
+        ++fit
+    )
+    {
+        if
+        (
+            fit->vertex(0)->internalOrBoundaryPoint()
+         || fit->vertex(1)->internalOrBoundaryPoint()
+         || fit->vertex(2)->internalOrBoundaryPoint()
+        )
+        {
+            fit->faceIndex() = dualVerti;
+
+            dualPoints[dualVerti++] = toPoint2D(circumcenter(fit));
+        }
+        else
+        {
+            fit->faceIndex() = -1;
+        }
+    }
+
+    dualPoints.setSize(dualVerti);
+
+    extractPatches(patchNames, patchSizes, mapEdgesRegion);
+
+    forAll(patchNames, patchI)
+    {
+        Info<< "Patch " << patchNames[patchI]
+            << " has size " << patchSizes[patchI] << endl;
+    }
+
+    // Create dual faces
+    // ~~~~~~~~~~~~~~~~~
+
+    dualFaces.setSize(number_of_vertices());
+    label dualFacei = 0;
+    labelList faceVerts(maxNvert);
+
+    for
+    (
+        Triangulation::Finite_vertices_iterator vit = finite_vertices_begin();
+        vit != finite_vertices_end();
+        ++vit
+    )
+    {
+        if (vit->internalOrBoundaryPoint())
+        {
+            Face_circulator fcStart = incident_faces(vit);
+            Face_circulator fc = fcStart;
+            label verti = 0;
+
+            do
+            {
+                if (!is_infinite(fc))
+                {
+                    if (fc->faceIndex() < 0)
+                    {
+                        FatalErrorIn
+                        (
+                            "Foam::CV2D::calcDual"
+                            "(point2DField& dualPoints, faceList& dualFaces)"
+                        )<< "Dual face uses vertex defined by a triangle"
+                            " defined by an external point"
+                            << exit(FatalError);
+                    }
+
+                    // Look up the index of the triangle
+                    faceVerts[verti++] = fc->faceIndex();
+                }
+            } while (++fc != fcStart);
+
+            if (faceVerts.size() > 2)
+            {
+                dualFaces[dualFacei++] =
+                    face(labelList::subList(faceVerts, verti));
+            }
+            else
+            {
+                Info<< "From triangle point:" << vit->index()
+                    << " coord:" << toPoint2D(vit->point())
+                    << " generated illegal dualFace:" << faceVerts
+                    << endl;
+            }
+        }
+    }
+
+    dualFaces.setSize(dualFacei);
+}
+
+
+void Foam::CV2D::writePatch(const fileName& fName) const
+{
+    point2DField dual2DPoints;
+    faceList dualFaces;
+    wordList patchNames;
+    labelList patchSizes;
+    EdgeMap<label> mapEdgesRegion;
+
+    calcDual(dual2DPoints, dualFaces, patchNames, patchSizes, mapEdgesRegion);
+    pointField dualPoints(dual2DPoints.size());
+    forAll(dualPoints, ip)
+    {
+        dualPoints[ip] = toPoint3D(dual2DPoints[ip]);
+    }
+
+    // Dump as primitive patch to be read by extrudeMesh.
+    OFstream str(fName);
+
+    Info<< "Writing patch to be used with extrudeMesh to file " << fName
+        << endl;
+
+    str << dualPoints << nl << dualFaces << nl;
+}
+
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/cv2DMesh/Make/files b/applications/utilities/mesh/generation/cv2DMesh/Make/files
new file mode 100755
index 0000000000000000000000000000000000000000..ddc8c9df9274934597248c74d55e313879f3a8da
--- /dev/null
+++ b/applications/utilities/mesh/generation/cv2DMesh/Make/files
@@ -0,0 +1,13 @@
+#include CGAL_FILES
+
+CV2D.C
+insertFeaturePoints.C
+insertSurfaceNearestPointPairs.C
+insertSurfaceNearPointPairs.C
+insertBoundaryConformPointPairs.C
+CV2DIO.C
+shortEdgeFilter2D.C
+cv2DMesh.C
+
+EXE = $(FOAM_APPBIN)/cv2DMesh
+
diff --git a/applications/utilities/mesh/generation/cv2DMesh/Make/options b/applications/utilities/mesh/generation/cv2DMesh/Make/options
new file mode 100755
index 0000000000000000000000000000000000000000..82659091b69ddf13c3ae892a944a9825a119ed93
--- /dev/null
+++ b/applications/utilities/mesh/generation/cv2DMesh/Make/options
@@ -0,0 +1,34 @@
+EXE_DEBUG = -DFULLDEBUG -g -O0
+EXE_FROUNDING_MATH = -frounding-math
+EXE_NDEBUG = -DNDEBUG
+
+include $(GENERAL_RULES)/CGAL
+FFLAGS = -DCGAL_FILES='"${CGAL_ARCH_PATH}/share/files"'
+
+EXE_INC = \
+    ${EXE_FROUNDING_MATH} \
+    ${EXE_NDEBUG} \
+    ${CGAL_INC} \
+    -I$(FOAM_APP)/utilities/mesh/generation/extrude2DMesh/extrude2DMesh/lnInclude \
+    -I$(FOAM_APP)/utilities/mesh/generation/extrude/extrudeModel/lnInclude \
+    -IconformalVoronoi2DMesh/lnInclude \
+    -I$(FOAM_APP)/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/lnInclude \
+    -I$(LIB_SRC)/finiteVolume/lnInclude \
+    -I$(LIB_SRC)/meshTools/lnInclude \
+    -I$(LIB_SRC)/surfMesh/lnInclude \
+    -I$(LIB_SRC)/edgeMesh/lnInclude \
+    -I$(LIB_SRC)/dynamicMesh/lnInclude \
+    -I$(LIB_SRC)/triSurface/lnInclude
+
+EXE_LIBS = \
+    $(CGAL_LIBS) \
+    -lextrude2DMesh \
+    -lextrudeModel \
+    -lcv2DMesh \
+    -lconformalVoronoiMesh \
+    -lmeshTools \
+    -lsurfMesh \
+    -ledgeMesh \
+    -ltriSurface \
+    -ldynamicMesh \
+    -ldecompositionMethods
diff --git a/applications/utilities/mesh/generation/cv2DMesh/conformalVoronoi2DMesh/Make/files b/applications/utilities/mesh/generation/cv2DMesh/conformalVoronoi2DMesh/Make/files
new file mode 100755
index 0000000000000000000000000000000000000000..b05aa47e45d0deb95d574ba8422510b294649d16
--- /dev/null
+++ b/applications/utilities/mesh/generation/cv2DMesh/conformalVoronoi2DMesh/Make/files
@@ -0,0 +1,4 @@
+cv2DControls/cv2DControls.C
+
+LIB = $(FOAM_LIBBIN)/libcv2DMesh
+
diff --git a/applications/utilities/mesh/generation/cv2DMesh/conformalVoronoi2DMesh/Make/options b/applications/utilities/mesh/generation/cv2DMesh/conformalVoronoi2DMesh/Make/options
new file mode 100755
index 0000000000000000000000000000000000000000..79be6f3a7dd8fa81ba203d5ab8572c446c43a6c7
--- /dev/null
+++ b/applications/utilities/mesh/generation/cv2DMesh/conformalVoronoi2DMesh/Make/options
@@ -0,0 +1,3 @@
+EXE_INC =
+
+LIB_LIBS =
diff --git a/applications/utilities/mesh/generation/cv2DMesh/conformalVoronoi2DMesh/cv2DControls/cv2DControls.C b/applications/utilities/mesh/generation/cv2DMesh/conformalVoronoi2DMesh/cv2DControls/cv2DControls.C
new file mode 100644
index 0000000000000000000000000000000000000000..b2b92a845f0b0c9263c19d640d00f164a8907de0
--- /dev/null
+++ b/applications/utilities/mesh/generation/cv2DMesh/conformalVoronoi2DMesh/cv2DControls/cv2DControls.C
@@ -0,0 +1,149 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2007-2011 OpenFOAM Foundation
+     \\/     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 "cv2DControls.H"
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+
+Foam::cv2DControls::cv2DControls
+(
+    const dictionary& controlDict,
+    const boundBox& bb
+)
+:
+    dict_(controlDict),
+
+    motionControl_(controlDict.subDict("motionControl")),
+    conformationControl_(controlDict.subDict("surfaceConformation")),
+
+    minCellSize_(readScalar(motionControl_.lookup("minCellSize"))),
+    minCellSize2_(Foam::sqr(minCellSize_)),
+
+    maxQuadAngle_(readScalar(conformationControl_.lookup("maxQuadAngle"))),
+
+    nearWallAlignedDist_
+    (
+        readScalar(motionControl_.lookup("nearWallAlignedDist"))*minCellSize_
+    ),
+    nearWallAlignedDist2_(Foam::sqr(nearWallAlignedDist_)),
+
+    insertSurfaceNearestPointPairs_
+    (
+            conformationControl_.lookup("insertSurfaceNearestPointPairs")
+    ),
+    mirrorPoints_(conformationControl_.lookup("mirrorPoints")),
+    insertSurfaceNearPointPairs_
+    (
+        conformationControl_.lookup("insertSurfaceNearPointPairs")
+    ),
+
+    objOutput_(motionControl_.lookupOrDefault<Switch>("objOutput", false)),
+
+    randomiseInitialGrid_(conformationControl_.lookup("randomiseInitialGrid")),
+    randomPerturbation_
+    (
+        readScalar(conformationControl_.lookup("randomPerturbation"))
+    ),
+
+    maxBoundaryConformingIter_
+    (
+        readLabel(conformationControl_.lookup("maxBoundaryConformingIter"))
+    ),
+
+    span_
+    (
+        max(mag(bb.max().x()), mag(bb.min().x()))
+      + max(mag(bb.max().y()), mag(bb.min().y()))
+    ),
+    span2_(Foam::sqr(span_)),
+
+    minEdgeLen_
+    (
+        readScalar(conformationControl_.lookup("minEdgeLenCoeff"))
+       *minCellSize_
+    ),
+    minEdgeLen2_(Foam::sqr(minEdgeLen_)),
+
+    maxNotchLen_
+    (
+        readScalar(conformationControl_.lookup("maxNotchLenCoeff"))
+       *minCellSize_
+    ),
+    maxNotchLen2_(Foam::sqr(maxNotchLen_)),
+
+    minNearPointDist_
+    (
+        readScalar(conformationControl_.lookup("minNearPointDistCoeff"))
+       *minCellSize_
+    ),
+    minNearPointDist2_(Foam::sqr(minNearPointDist_)),
+
+    ppDist_
+    (
+        readScalar(conformationControl_.lookup("pointPairDistanceCoeff"))
+       *minCellSize_
+    )
+{}
+
+
+// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
+
+Foam::cv2DControls::~cv2DControls()
+{}
+
+
+// * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * * //
+
+void Foam::cv2DControls::write(Ostream& os) const
+{
+    os.indentLevel() = 1;
+    os.precision(2);
+    os.flags(ios_base::scientific);
+
+    os << nl << "Outputting CV2D Mesher controls:" << nl
+       << token::BEGIN_BLOCK << nl
+       << indent << "minCellSize2_         : " << minCellSize2_ << nl
+       << indent << "span_ / span2_        : " << span_ << " / " << span2_ << nl
+       << indent << "maxNotchLen2_         : " << maxNotchLen2_ << nl
+       << indent << "minNearPointDist2_    : " << minNearPointDist2_ << nl
+       << indent << "nearWallAlignedDist2_ : " << nearWallAlignedDist2_ << nl
+       << indent << "ppDist_               : " << ppDist_ << nl
+       << indent << "minEdgeLen2_          : " << minEdgeLen2_ << nl
+       << token::END_BLOCK << endl;
+}
+
+
+// * * * * * * * * * * * * * * IOStream operators  * * * * * * * * * * * * * //
+
+Foam::Ostream& Foam::operator<<(Ostream& os, const cv2DControls& s)
+{
+    s.write(os);
+    return os;
+}
+
+
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/cv2DMesh/conformalVoronoi2DMesh/cv2DControls/cv2DControls.H b/applications/utilities/mesh/generation/cv2DMesh/conformalVoronoi2DMesh/cv2DControls/cv2DControls.H
new file mode 100644
index 0000000000000000000000000000000000000000..0d1f47b1ca0190a2bb9866adfffb971d0f4efde8
--- /dev/null
+++ b/applications/utilities/mesh/generation/cv2DMesh/conformalVoronoi2DMesh/cv2DControls/cv2DControls.H
@@ -0,0 +1,257 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2011-2011 OpenFOAM Foundation
+     \\/     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::cv2DControls
+
+Description
+    Controls for the 2D CV mesh generator.
+
+SourceFiles
+    cv2DControls.C
+    cv2DControlsI.H
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef cv2DControls_H
+#define cv2DControls_H
+
+#include "Switch.H"
+#include "dictionary.H"
+#include "boundBox.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+/*---------------------------------------------------------------------------*\
+                        Class cv2DControls Declaration
+\*---------------------------------------------------------------------------*/
+
+class cv2DControls
+{
+    // Private data
+
+        //- Description of data_
+        const dictionary& dict_;
+
+        const dictionary& motionControl_;
+
+        const dictionary& conformationControl_;
+
+
+    // Private Member Functions
+
+        //- Disallow default bitwise copy construct
+        cv2DControls(const cv2DControls&);
+
+        //- Disallow default bitwise assignment
+        void operator=(const cv2DControls&);
+
+
+public:
+
+        // Controls
+
+            //- Minimum cell size below which protusions through the surface are
+            //  not split
+            scalar minCellSize_;
+
+            //- Square of minCellSize
+            scalar minCellSize2_;
+
+            //- Maximum quadrant angle allowed at a concave corner before
+            //  additional "mitering" lines are added
+            scalar maxQuadAngle_;
+
+            //- Near-wall region where cells are aligned with the wall
+            scalar nearWallAlignedDist_;
+
+            //- Square of nearWallAlignedDist
+            scalar nearWallAlignedDist2_;
+
+            //- Insert near-boundary point mirror or point-pairs
+            Switch insertSurfaceNearestPointPairs_;
+
+            //- Mirror near-boundary points rather than insert point-pairs
+            Switch mirrorPoints_;
+
+            //- Insert point-pairs vor dual-cell vertices very near the surface
+            Switch insertSurfaceNearPointPairs_;
+
+            Switch objOutput_;
+
+            Switch randomiseInitialGrid_;
+
+            scalar randomPerturbation_;
+
+            label maxBoundaryConformingIter_;
+
+
+        // Tolerances
+
+            //- Maximum cartesian span of the geometry
+            scalar span_;
+
+            //- Square of span
+            scalar span2_;
+
+            //- Minumum edge-length of the cell size below which protusions
+            //  through the surface are not split
+            scalar minEdgeLen_;
+
+            //- Square of minEdgeLen
+            scalar minEdgeLen2_;
+
+            //- Maximum notch size below which protusions into the surface are
+            //  not filled
+            scalar maxNotchLen_;
+
+            //- Square of maxNotchLen
+            scalar maxNotchLen2_;
+
+            //- The minimum distance alowed between a dual-cell vertex
+            // and the surface before a point-pair is introduced
+            scalar minNearPointDist_;
+
+            //- Square of minNearPoint
+            scalar minNearPointDist2_;
+
+            //- Distance between boundary conforming point-pairs
+            scalar ppDist_;
+
+            //- Square of ppDist
+            scalar ppDist2_;
+
+
+    // Constructors
+
+        cv2DControls
+        (
+            const dictionary& controlDict,
+            const boundBox& bb
+        );
+
+
+    //- Destructor
+    ~cv2DControls();
+
+
+    // Member Functions
+
+        // Access
+
+            //- Return the minimum cell size
+            inline scalar minCellSize() const;
+
+            //- Return the square of the minimum cell size
+            inline scalar minCellSize2() const;
+
+            //- Return the maximum quadrant angle
+            inline scalar maxQuadAngle() const;
+
+            //- Return number of layers to align with the nearest wall
+            inline scalar nearWallAlignedDist() const;
+
+            //- Return square of nearWallAlignedDist
+            inline scalar nearWallAlignedDist2() const;
+
+            //- Return insertSurfaceNearestPointPairs Switch
+            inline Switch insertSurfaceNearestPointPairs() const;
+
+            //- Return mirrorPoints Switch
+            inline Switch mirrorPoints() const;
+
+            //- Return insertSurfaceNearPointPairs Switch
+            inline Switch insertSurfaceNearPointPairs() const;
+
+            //- Return the objOutput Switch
+            inline Switch objOutput() const;
+
+            //- Return the randomise initial point layout Switch
+            inline Switch randomiseInitialGrid() const;
+
+            //- Return the random perturbation factor
+            inline scalar randomPerturbation() const;
+
+            //- Return the maximum number of boundary conformation iterations
+            inline label maxBoundaryConformingIter() const;
+
+            //- Return the span
+            inline scalar span() const;
+
+            //- Return the span squared
+            inline scalar span2() const;
+
+            //- Return the minEdgeLen
+            inline scalar minEdgeLen() const;
+
+            //- Return the minEdgeLen squared
+            inline scalar minEdgeLen2() const;
+
+            //- Return the maxNotchLen
+            inline scalar maxNotchLen() const;
+
+            //- Return the maxNotchLen squared
+            inline scalar maxNotchLen2() const;
+
+            //- Return the minNearPointDist
+            inline scalar minNearPointDist() const;
+
+            //- Return the minNearPointDist squared
+            inline scalar minNearPointDist2() const;
+
+            //- Return the ppDist
+            inline scalar ppDist() const;
+
+
+        // Write
+
+            //- Write controls to output stream.
+            void write(Ostream& os) const;
+
+            //- Ostream Operator
+            friend Ostream& operator<<
+            (
+                Ostream& os,
+                const cv2DControls& s
+            );
+
+
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#include "cv2DControlsI.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* // 
diff --git a/applications/utilities/mesh/generation/cv2DMesh/conformalVoronoi2DMesh/cv2DControls/cv2DControlsI.H b/applications/utilities/mesh/generation/cv2DMesh/conformalVoronoi2DMesh/cv2DControls/cv2DControlsI.H
new file mode 100644
index 0000000000000000000000000000000000000000..3ff16735a8372fe6e2f1cd21981ced0a8a48cd01
--- /dev/null
+++ b/applications/utilities/mesh/generation/cv2DMesh/conformalVoronoi2DMesh/cv2DControls/cv2DControlsI.H
@@ -0,0 +1,153 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
+     \\/     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/>.
+
+\*---------------------------------------------------------------------------*/
+
+
+inline Foam::scalar Foam::cv2DControls::minCellSize() const
+{
+    return minCellSize_;
+}
+
+
+inline Foam::scalar Foam::cv2DControls::minCellSize2() const
+{
+    return minCellSize2_;
+}
+
+
+inline Foam::scalar Foam::cv2DControls::maxQuadAngle() const
+{
+    return maxQuadAngle_;
+}
+
+
+inline Foam::scalar Foam::cv2DControls::nearWallAlignedDist() const
+{
+    return nearWallAlignedDist_;
+}
+
+
+inline Foam::scalar Foam::cv2DControls::nearWallAlignedDist2() const
+{
+    return nearWallAlignedDist2_;
+}
+
+
+inline Foam::Switch Foam::cv2DControls::insertSurfaceNearestPointPairs() const
+{
+    return insertSurfaceNearestPointPairs_;
+}
+
+
+inline Foam::Switch Foam::cv2DControls::mirrorPoints() const
+{
+    return mirrorPoints_;
+}
+
+
+inline Foam::Switch Foam::cv2DControls::insertSurfaceNearPointPairs() const
+{
+    return insertSurfaceNearPointPairs_;
+}
+
+
+inline Foam::Switch Foam::cv2DControls::objOutput() const
+{
+    return objOutput_;
+}
+
+
+inline Foam::Switch Foam::cv2DControls::randomiseInitialGrid() const
+{
+    return randomiseInitialGrid_;
+}
+
+
+inline Foam::scalar Foam::cv2DControls::randomPerturbation() const
+{
+    return randomPerturbation_;
+}
+
+
+inline Foam::label Foam::cv2DControls::maxBoundaryConformingIter() const
+{
+    return maxBoundaryConformingIter_;
+}
+
+
+inline Foam::scalar Foam::cv2DControls::span() const
+{
+    return span_;
+}
+
+
+inline Foam::scalar Foam::cv2DControls::span2() const
+{
+    return span2_;
+}
+
+
+inline Foam::scalar Foam::cv2DControls::minEdgeLen() const
+{
+    return minEdgeLen_;
+}
+
+
+inline Foam::scalar Foam::cv2DControls::minEdgeLen2() const
+{
+    return minEdgeLen2_;
+}
+
+
+inline Foam::scalar Foam::cv2DControls::maxNotchLen() const
+{
+    return maxNotchLen_;
+}
+
+
+inline Foam::scalar Foam::cv2DControls::maxNotchLen2() const
+{
+    return maxNotchLen2_;
+}
+
+
+inline Foam::scalar Foam::cv2DControls::minNearPointDist() const
+{
+    return minNearPointDist_;
+}
+
+
+inline Foam::scalar Foam::cv2DControls::minNearPointDist2() const
+{
+    return minNearPointDist2_;
+}
+
+
+inline Foam::scalar Foam::cv2DControls::ppDist() const
+{
+    return ppDist_;
+}
+
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/cv2DMesh/cv2DMesh.C b/applications/utilities/mesh/generation/cv2DMesh/cv2DMesh.C
new file mode 100644
index 0000000000000000000000000000000000000000..09fe6261f67faab9d9128f2ac1936e7a5b06e5a0
--- /dev/null
+++ b/applications/utilities/mesh/generation/cv2DMesh/cv2DMesh.C
@@ -0,0 +1,251 @@
+/*---------------------------------------------------------------------------*\
+ =========                   |
+ \\      /   F ield          | OpenFOAM: The Open Source CFD Toolbox
+  \\    /    O peration      |
+   \\  /     A nd            | Copyright (C) 2007-2011 OpenFOAM Foundation
+    \\/      M anipulation   |
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+Application
+    cv2DMesh
+
+Description
+    Conformal-Voronoi 2D extruding automatic mesher with grid or read
+    initial points and point position relaxation with optional
+    "squarification".
+
+\*---------------------------------------------------------------------------*/
+
+#include "CV2D.H"
+#include "argList.H"
+
+#include "MeshedSurfaces.H"
+#include "shortEdgeFilter2D.H"
+#include "extrude2DMesh.H"
+#include "polyMesh.H"
+#include "patchToPoly2DMesh.H"
+#include "extrudeModel.H"
+#include "polyTopoChange.H"
+#include "edgeCollapser.H"
+#include "relaxationModel.H"
+
+using namespace Foam;
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+// Main program:
+
+int main(int argc, char *argv[])
+{
+    argList::noParallel();
+    argList::validArgs.clear();
+    argList::validOptions.insert("pointsFile", "<filename>");
+
+    #include "addOverwriteOption.H"
+
+    #include "setRootCase.H"
+    #include "createTime.H"
+
+    // Read control dictionary
+    // ~~~~~~~~~~~~~~~~~~~~~~~
+    dictionary controlDict(IFstream("system/" + args.executable() + "Dict")());
+    dictionary shortEdgeFilterDict(controlDict.subDict("shortEdgeFilter"));
+    dictionary extrusionDict(controlDict.subDict("extrusion"));
+
+    Switch extrude(extrusionDict.lookup("extrude"));
+    const bool overwrite = args.optionFound("overwrite");
+
+    autoPtr<relaxationModel> relax
+    (
+        relaxationModel::New
+        (
+            controlDict.subDict("motionControl"),
+            runTime
+        )
+    );
+
+    // Read and triangulation
+    // ~~~~~~~~~~~~~~~~~~~~~~
+    CV2D mesh(runTime, controlDict);
+    if (args.options().found("pointsFile"))
+    {
+        fileName pointFileName(IStringStream(args.options()["pointsFile"])());
+        mesh.insertPoints(pointFileName);
+        mesh.insertSurfacePointPairs();
+        mesh.boundaryConform();
+    }
+    else
+    {
+        mesh.insertGrid();
+        mesh.insertSurfacePointPairs();
+        mesh.boundaryConform();
+    }
+
+    while (runTime.loop())
+    {
+        Info<< nl << "Time = " << runTime.timeName() << endl;
+
+        Info<< "Relaxation = " << relax->relaxation() << endl;
+
+        mesh.newPoints(relax->relaxation());
+    }
+
+    mesh.write();
+
+    Info<< "Finished Delaunay in = "
+        << runTime.cpuTimeIncrement() << " s." << endl;
+
+    Info<< "Begin filtering short edges:" << endl;
+    shortEdgeFilter2D sef(mesh, shortEdgeFilterDict);
+
+    sef.filter();
+
+    Info<< "Meshed surface after edge filtering :" << endl;
+    sef.fMesh().writeStats(Info);
+
+    Info<< "Write .obj file of the 2D mesh: MeshedSurface.obj" << endl;
+    sef.fMesh().write("MeshedSurface.obj");
+
+    Info<< "Finished filtering in = "
+        << runTime.cpuTimeIncrement() << " s." << endl;
+
+    Info<< "Begin constructing a polyMesh:" << endl;
+
+    patchToPoly2DMesh poly2DMesh
+    (
+        sef.fMesh(),
+        sef.patchNames(),
+        sef.patchSizes(),
+        sef.mapEdgesRegion()
+    );
+
+    poly2DMesh.createMesh();
+
+    polyMesh pMesh
+    (
+        IOobject
+        (
+            polyMesh::defaultRegion,
+            runTime.constant(),
+            runTime,
+            IOobject::NO_READ,
+            IOobject::NO_WRITE,
+            false
+        ),
+        xferMove(poly2DMesh.points()),
+        xferMove(poly2DMesh.faces()),
+        xferMove(poly2DMesh.owner()),
+        xferMove(poly2DMesh.neighbour())
+    );
+
+    Info<< "Constructing patches." << endl;
+    List<polyPatch*> patches(poly2DMesh.patchNames().size());
+
+    forAll(patches, patchI)
+    {
+        patches[patchI] = new polyPatch
+        (
+            poly2DMesh.patchNames()[patchI],
+            poly2DMesh.patchSizes()[patchI],
+            poly2DMesh.patchStarts()[patchI],
+            patchI,
+            pMesh.boundaryMesh()
+        );
+    }
+
+    pMesh.addPatches(patches);
+
+    if (extrude)
+    {
+        Info<< "Begin extruding the polyMesh:" << endl;
+
+        {
+            // Point generator
+            autoPtr<extrudeModel> model(extrudeModel::New(extrusionDict));
+
+            extrude2DMesh extruder(pMesh, extrusionDict, model());
+
+            extruder.addFrontBackPatches();
+
+            polyTopoChange meshMod(pMesh.boundaryMesh().size());
+
+            extruder.setRefinement(meshMod);
+
+            autoPtr<mapPolyMesh> morphMap = meshMod.changeMesh(pMesh, false);
+
+            pMesh.updateMesh(morphMap);
+        }
+
+        {
+            edgeCollapser collapser(pMesh);
+
+            const edgeList& edges = pMesh.edges();
+            const pointField& points = pMesh.points();
+
+            const boundBox& bb = pMesh.bounds();
+            const scalar mergeDim = 1E-4 * bb.minDim();
+
+            forAll(edges, edgeI)
+            {
+                const edge& e = edges[edgeI];
+
+                scalar d = e.mag(points);
+
+                if (d < mergeDim)
+                {
+                    Info<< "Merging edge " << e << " since length " << d
+                        << " << " << mergeDim << endl;
+
+                    // Collapse edge to e[0]
+                    collapser.collapseEdge(edgeI, e[0]);
+                }
+            }
+
+            polyTopoChange meshModCollapse(pMesh);
+
+            collapser.setRefinement(meshModCollapse);
+
+            // Create a mesh from topo changes.
+            autoPtr<mapPolyMesh> morphMap =
+                meshModCollapse.changeMesh(pMesh, false);
+
+            pMesh.updateMesh(morphMap);
+        }
+
+        if (!overwrite)
+        {
+            runTime++;
+        }
+        else
+        {
+            pMesh.setInstance("constant");
+        }
+
+    }
+
+    pMesh.write();
+
+    Info<< "Finished extruding in = "
+        << runTime.cpuTimeIncrement() << " s." << endl;
+
+    Info<< nl << "End\n" << endl;
+
+    return 0;
+}
+
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/cv2DMesh/cv2DMeshDict b/applications/utilities/mesh/generation/cv2DMesh/cv2DMeshDict
new file mode 100644
index 0000000000000000000000000000000000000000..0ef6d2a0c4794677e257056a9a23d3b1e59975d2
--- /dev/null
+++ b/applications/utilities/mesh/generation/cv2DMesh/cv2DMeshDict
@@ -0,0 +1,208 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  dev                                   |
+|   \\  /    A nd           | Web:      www.OpenFOAM.org                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+
+FoamFile
+{
+    version         2.0;
+    format          ascii;
+
+    root            "";
+    case            "";
+    instance        "";
+    local           "";
+
+    class           dictionary;
+    object          cv2DMeshDict;
+}
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+
+geometry
+{
+    laurence_clean_preciser.stl
+    {
+        name laurence_clean_preciser;
+        type closedTriSurfaceMesh;
+        //type triSurfaceMesh;
+    }
+//    refinementBox
+//    {
+//        type searchableBox;
+//        min (-0.5 0.35 -1000);
+//        max (-0.5 0.35 1000);
+//    }
+//    refinementSphere
+//    {
+//        type searchableSphere;
+//        centre (0.85 0.4 0.0);
+//        radius 0.01;
+//    }
+}
+
+surfaceConformation
+{
+    locationInMesh (-2.8 0.7 0.5);
+
+    pointPairDistanceCoeff    0.005;
+
+    minEdgeLenCoeff           0.005;
+
+    maxNotchLenCoeff          0.003;
+
+    minNearPointDistCoeff     0.0025;
+
+    maxQuadAngle 125;
+
+    // Insert near-boundary point mirror or point-pairs
+    insertSurfaceNearestPointPairs yes;
+
+    // Mirror near-boundary points rather than insert point-pairs
+    mirrorPoints   no;
+
+    // Insert point-pairs vor dual-cell vertices very near the surface
+    insertSurfaceNearPointPairs yes;
+
+    // Maximum number of iterations used in boundaryConform.
+    maxBoundaryConformingIter 5;
+
+    geometryToConformTo
+    {
+        laurence_clean_preciser
+        {
+            featureMethod extendedFeatureEdgeMesh;
+            extendedFeatureEdgeMesh "laurence_clean_preciser.extendedFeatureEdgeMesh";
+        }
+    }
+
+    additionalFeatures
+    {
+    }
+
+    // Choose if to randomise the initial grid created by insertGrid.
+    randomiseInitialGrid yes;
+
+    // Perturbation fraction, 1 = cell-size.
+    randomPerturbation   0.1;
+
+}
+
+
+motionControl
+{
+    defaultCellSize     0.05;
+
+    // Assign a priority to all requests for cell sizes, the highest overrules.
+    defaultPriority     0;
+
+    cellSizeControlGeometry
+    {
+        laurence_clean_preciser
+        {
+            priority              1;
+            mode                  bothSides;
+            cellSizeFunction      linearDistance;
+            linearDistanceCoeffs
+            {
+                distanceCellSize  0.05;
+                surfaceCellSize   0.01;
+                distance          0.5;
+            }
+            uniformCoeffs
+            {
+                cellSize          0.01;
+            }
+        }
+//        refinementBox
+//        {
+//            priority            1;
+//            mode                outside;
+//            cellSizeFunction    linearDistance;
+//            linearDistanceCoeffs
+//            {
+//                distanceCellSize 0.04;
+//                surfaceCellSize 0.005;
+//                distance        0.2;
+//            }
+//        }
+//        refinementSphere
+//        {
+//            priority            1;
+//            mode                outside;
+//            cellSizeFunction    linearDistance;
+//            linearDistanceCoeffs
+//            {
+//                distanceCellSize 0.04;
+//                surfaceCellSize 0.005;
+//                distance        0.2;
+//            }
+//        }
+    }
+
+    relaxationModel     adaptiveLinear;
+
+    adaptiveLinearCoeffs
+    {
+        relaxationStart 0.5;
+        relaxationEnd   0.0;
+    }
+
+    objOutput                   no;
+
+    // Near-wall region where cells are aligned with the wall specified as a number
+    // of cell layers
+    nearWallAlignedDist 3;
+
+}
+
+shortEdgeFilter
+{
+    // Factor to multiply the average of a face's edge lengths by.
+    // If an edge of that face is smaller than that value then delete it.
+    shortEdgeFilterFactor     0.2;
+
+    // Weighting for the lengths of edges that are attached to the boundaries.
+    // Used when calculating the length of an edge. Default 2.0.
+    edgeAttachedToBoundaryFactor 2.0;
+}
+
+extrusion
+{
+    extrude         on;
+
+    extrudeModel        linearDirection;
+    //extrudeModel        wedge;
+
+    patchInfo
+    {
+        //type empty;
+        //startFace
+    }
+
+    patchType           empty;
+    //patchType           wedge;
+
+    nLayers             1;
+
+    expansionRatio      1.0;    //0.9;
+
+    linearDirectionCoeffs
+    {
+        direction       (0 0 1);
+        thickness       0.1;
+    }
+
+    wedgeCoeffs
+    {
+        axisPt      (0 0 0);
+        axis        (1 0 0);
+        angle       10;
+    }
+
+    thickness       0.1;
+}
diff --git a/applications/utilities/mesh/generation/cv2DMesh/featuresMissingFrom2D.org b/applications/utilities/mesh/generation/cv2DMesh/featuresMissingFrom2D.org
new file mode 100644
index 0000000000000000000000000000000000000000..857c41f31c3293d52b5e7f7105e524e9285399aa
--- /dev/null
+++ b/applications/utilities/mesh/generation/cv2DMesh/featuresMissingFrom2D.org
@@ -0,0 +1,3 @@
+* Displacement limiting
+
+http://en.wikipedia.org/wiki/Geometric_algebra
diff --git a/applications/utilities/mesh/generation/cv2DMesh/indexedFace.H b/applications/utilities/mesh/generation/cv2DMesh/indexedFace.H
new file mode 100644
index 0000000000000000000000000000000000000000..4cea4a7c51f6f11f83a861b017154350b7d8de4b
--- /dev/null
+++ b/applications/utilities/mesh/generation/cv2DMesh/indexedFace.H
@@ -0,0 +1,147 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2007-2011 OpenFOAM Foundation
+     \\/     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
+    indexedFace
+
+Description
+    An indexed form of CGAL::Triangulation_face_base_2<K> used to keep
+    track of the vertices in the triangulation.
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef indexedFace_H
+#define indexedFace_H
+
+#include <CGAL/Triangulation_2.h>
+#include "indexedVertex.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace CGAL
+{
+
+/*---------------------------------------------------------------------------*\
+                       Class indexedFace Declaration
+\*---------------------------------------------------------------------------*/
+
+template<class Gt, class Fb=CGAL::Triangulation_face_base_2<Gt> >
+class indexedFace 
+:
+    public Fb
+{
+    // Private data
+
+        //- The index for this triangle face
+        //  -1: triangle and changed and associated data needs updating
+        // >=0: index of triangles, set by external update algorithm
+        int index_;
+
+
+public:
+
+    enum faceTypes
+    {
+        UNCHANGED           = 0,
+        CHANGED             = -1,
+        SAVE_CHANGED        = -2
+    };
+
+    typedef typename Fb::Vertex_handle                   Vertex_handle;
+    typedef typename Fb::Face_handle                     Face_handle;
+
+    template < typename TDS2 >
+    struct Rebind_TDS
+    {
+        typedef typename Fb::template Rebind_TDS<TDS2>::Other Fb2;
+        typedef indexedFace<Gt, Fb2>  Other;
+    };
+
+
+    indexedFace()
+    :
+        Fb(),
+        index_(CHANGED)
+    {}
+
+    indexedFace(Vertex_handle v0, Vertex_handle v1, Vertex_handle v2)
+    :
+        Fb(v0, v1, v2),
+        index_(CHANGED)
+    {}
+
+    indexedFace
+    (
+        Vertex_handle v0, 
+        Vertex_handle v1,
+        Vertex_handle v2, 
+        Face_handle n0, 
+        Face_handle n1,
+        Face_handle n2
+    )
+    :
+        Fb(v0, v1, v2, n0, n1, n2),
+        index_(CHANGED)
+    {}
+
+
+    void set_vertex(int i, Vertex_handle v)
+    {
+        index_ = CHANGED;
+        Fb::set_vertex(i, v);
+    }
+
+    void set_vertices()
+    {
+        index_ = CHANGED;
+        Fb::set_vertices();
+    }
+
+    void set_vertices(Vertex_handle v0, Vertex_handle v1, Vertex_handle v2)
+    {
+        index_ = CHANGED;
+        Fb::set_vertices(v0, v1, v2);
+    }
+
+
+    int& faceIndex()
+    {
+        return index_;
+    }
+
+    int faceIndex() const
+    {
+        return index_;
+    }
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace CGAL
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/cv2DMesh/indexedVertex.H b/applications/utilities/mesh/generation/cv2DMesh/indexedVertex.H
new file mode 100644
index 0000000000000000000000000000000000000000..cda593840d98c9f22da247940af5fedd1701270f
--- /dev/null
+++ b/applications/utilities/mesh/generation/cv2DMesh/indexedVertex.H
@@ -0,0 +1,268 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2007-2011 OpenFOAM Foundation
+     \\/     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
+    indexedVertex
+
+Description
+    An indexed form of CGAL::Triangulation_vertex_base_2<K> used to keep
+    track of the vertices in the triangulation.
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef indexedVertex_H
+#define indexedVertex_H
+
+#include <CGAL/Triangulation_2.h>
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace CGAL
+{
+
+/*---------------------------------------------------------------------------*\
+                       Class indexedVertex Declaration
+\*---------------------------------------------------------------------------*/
+
+template<class Gt, class Vb=CGAL::Triangulation_vertex_base_2<Gt> >
+class indexedVertex
+:
+    public Vb
+{
+    // Private data
+
+        //- The index for this triangle vertex
+        int index_;
+
+        //- Index of pair-point :
+        //  NEAR_BOUNDARY_POINT : internal near boundary point.
+        //  INTERNAL_POINT      : internal point.
+        //  FAR_POINT           : far-point.
+        //  >= 0                : part of point-pair. Index of other point.
+        //                        Lowest numbered is inside one (master).
+        int type_;
+
+
+public:
+
+    enum pointTypes
+    {
+        NEAR_BOUNDARY_POINT = -4,
+        INTERNAL_POINT      = -3,
+        MIRROR_POINT        = -2,
+        FAR_POINT           = -1
+    };
+
+    typedef typename Vb::Vertex_handle      Vertex_handle;
+    typedef typename Vb::Face_handle        Face_handle;
+    typedef typename Vb::Point              Point;
+
+    template<typename TDS2>
+    struct Rebind_TDS
+    {
+        typedef typename Vb::template Rebind_TDS<TDS2>::Other    Vb2;
+        typedef indexedVertex<Gt,Vb2>                           Other;
+    };
+
+
+    indexedVertex()
+    :
+        Vb(),
+        index_(INTERNAL_POINT),
+        type_(INTERNAL_POINT)
+    {}
+
+    indexedVertex(const Point& p)
+    :
+        Vb(p),
+        index_(INTERNAL_POINT),
+        type_(INTERNAL_POINT)
+    {}
+
+    indexedVertex(const Point& p, const int index, const int& type)
+    :
+        Vb(p),
+        index_(index),
+        type_(type)
+    {}
+
+    indexedVertex(const Point& p, Face_handle f)
+    :
+        Vb(f, p),
+        index_(INTERNAL_POINT),
+        type_(INTERNAL_POINT)
+    {}
+
+    indexedVertex(Face_handle f)
+    :
+        Vb(f),
+        index_(INTERNAL_POINT),
+        type_(INTERNAL_POINT)
+    {}
+
+
+    int& index()
+    {
+        return index_;
+    }
+
+    int index() const
+    {
+        return index_;
+    }
+
+
+    int& type()
+    {
+        return type_;
+    }
+
+    int type() const
+    {
+        return type_;
+    }
+
+
+    //- Is point a far-point
+    inline bool farPoint() const
+    {
+        return type_ == FAR_POINT;
+    }
+
+    //- Is point internal, i.e. not on boundary
+    inline bool internalPoint() const
+    {
+        return type_ <= INTERNAL_POINT;
+    }
+
+    //- Is point internal and near the boundary
+    inline bool nearBoundary() const
+    {
+        return type_ == NEAR_BOUNDARY_POINT;
+    }
+
+    //- Set the point to be near the boundary
+    inline void setNearBoundary()
+    {
+        type_ = NEAR_BOUNDARY_POINT;
+    }
+
+    //- Is point a mirror point
+    inline bool mirrorPoint() const
+    {
+        return type_ == MIRROR_POINT;
+    }
+
+    //- Either master or slave of pointPair.
+    inline bool pairPoint() const
+    {
+        return type_ >= 0;
+    }
+
+    //- Master of a pointPair is the lowest numbered one.
+    inline bool ppMaster() const
+    {
+        if (type_ > index_)
+        {
+            return true;
+        }
+        else
+        {
+            return false;
+        }
+    }
+
+    //- Slave of a pointPair is the highest numbered one.
+    inline bool ppSlave() const
+    {
+        if (type_ >= 0 && type_ < index_)
+        {
+            return true;
+        }
+        else
+        {
+            return false;
+        }
+    }
+
+    //- Either original internal point or master of pointPair.
+    inline bool internalOrBoundaryPoint() const
+    {
+        return internalPoint() || ppMaster();
+    }
+
+    //- Is point near the boundary or part of the boundary definition
+    inline bool nearOrOnBoundary() const
+    {
+        return pairPoint() || mirrorPoint() || nearBoundary();
+    }
+
+    //- Do the two given vertices consitute a boundary point-pair
+    inline friend bool pointPair
+    (
+        const indexedVertex& v0,
+        const indexedVertex& v1
+    )
+    {
+        return v0.index_ == v1.type_ || v1.index_ == v0.type_;
+    }
+
+    //- Do the three given vertices consitute a boundary triangle
+    inline friend bool boundaryTriangle
+    (
+        const indexedVertex& v0,
+        const indexedVertex& v1,
+        const indexedVertex& v2
+    )
+    {
+        return (v0.pairPoint() && pointPair(v1, v2))
+            || (v1.pairPoint() && pointPair(v2, v0))
+            || (v2.pairPoint() && pointPair(v0, v1));
+    }
+
+    //- Do the three given vertices consitute an outside triangle
+    inline friend bool outsideTriangle
+    (
+        const indexedVertex& v0,
+        const indexedVertex& v1,
+        const indexedVertex& v2
+    )
+    {
+        return (v0.farPoint() || v0.ppSlave())
+            || (v1.farPoint() || v1.ppSlave())
+            || (v2.farPoint() || v2.ppSlave());
+    }
+
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace CGAL
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/cv2DMesh/insertBoundaryConformPointPairs.C b/applications/utilities/mesh/generation/cv2DMesh/insertBoundaryConformPointPairs.C
new file mode 100644
index 0000000000000000000000000000000000000000..b4cf64091c92aa83937c057366d0b758401d9131
--- /dev/null
+++ b/applications/utilities/mesh/generation/cv2DMesh/insertBoundaryConformPointPairs.C
@@ -0,0 +1,323 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2007-2011 OpenFOAM Foundation
+     \\/     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 "CV2D.H"
+
+// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
+
+void Foam::CV2D::insertPointPair
+(
+    Triangulation::Finite_vertices_iterator& vit,
+    const point2D& p,
+    const label trii,
+    const label hitSurface
+)
+{
+    if
+    (
+        !meshControls().mirrorPoints()
+     || !insertMirrorPoint(toPoint2D(vit->point()), p)
+    )
+    {
+        pointIndexHit pHit
+        (
+            true,
+            toPoint3D(p),
+            trii
+        );
+
+        vectorField norm(1);
+        qSurf_.geometry()[hitSurface].getNormal
+        (
+            List<pointIndexHit>(1, pHit),
+            norm
+        );
+
+        insertPointPair
+        (
+            meshControls().ppDist(),
+            p,
+            toPoint2D(norm[0])
+        );
+    }
+
+    vit = Triangulation::Finite_vertices_iterator
+    (
+        CGAL::Filter_iterator
+        <
+            Triangulation::All_vertices_iterator,
+            Triangulation::Infinite_tester
+        >(finite_vertices_end(), vit.predicate(), vit.base())
+    );
+}
+
+
+bool Foam::CV2D::insertPointPairAtIntersection
+(
+    Triangulation::Finite_vertices_iterator& vit,
+    const point2D& defVert,
+    const point2D vertices[],
+    const scalar maxProtSize2
+)
+{
+    bool found = false;
+    point2D interPoint;
+    label interTri = -1;
+    label interHitSurface = -1;
+    scalar interDist2 = 0;
+
+    Face_circulator fcStart = incident_faces(vit);
+    Face_circulator fc = fcStart;
+    label vi = 0;
+
+    do
+    {
+        if (!is_infinite(fc))
+        {
+            pointIndexHit pHit;
+            label hitSurface = -1;
+
+            qSurf_.findSurfaceNearestIntersection
+            (
+                toPoint3D(defVert),
+                toPoint3D(vertices[vi]),
+                pHit,
+                hitSurface
+            );
+
+            if (pHit.hit())
+            {
+                scalar dist2 =
+                    magSqr(toPoint2D(pHit.hitPoint()) - vertices[vi]);
+
+                // Check the point is further away than the furthest so far
+                if (dist2 > interDist2)
+                {
+                    scalar mps2 = maxProtSize2;
+
+                    // If this is a boundary triangle reset the tolerance
+                    // to avoid finding a hit point very close to a boundary
+                    // vertex
+                    if (boundaryTriangle(fc))
+                    {
+                        mps2 = meshControls().maxNotchLen2();
+                    }
+
+                    if (dist2 > mps2)
+                    {
+                        found = true;
+                        interPoint = toPoint2D(pHit.hitPoint());
+                        interTri = pHit.index();
+                        interDist2 = dist2;
+                        interHitSurface = hitSurface;
+                    }
+                }
+            }
+
+            vi++;
+        }
+    } while (++fc != fcStart);
+
+    if (found)
+    {
+        insertPointPair(vit, interPoint, interTri, interHitSurface);
+        return true;
+    }
+    else
+    {
+        return false;
+    }
+}
+
+
+Foam::label Foam::CV2D::insertBoundaryConformPointPairs
+(
+    const fileName& fName
+)
+{
+    label nIntersections = 0;
+
+    for
+    (
+        Triangulation::Finite_vertices_iterator vit = finite_vertices_begin();
+        vit != finite_vertices_end();
+        vit++
+    )
+    {
+        // Consider only those points part of point-pairs or near boundary
+        if (!vit->nearOrOnBoundary())
+        {
+            continue;
+        }
+
+        // Counter-clockwise circulator
+        Face_circulator fcStart = incident_faces(vit);
+        Face_circulator fc = fcStart;
+
+        bool infinite = false;
+        bool changed = false;
+
+        do
+        {
+            if (is_infinite(fc))
+            {
+                infinite = true;
+                break;
+            }
+            else if (fc->faceIndex() < Fb::UNCHANGED)
+            {
+                changed = true;
+                break;
+            }
+        } while (++fc != fcStart);
+
+        // If the dual-cell is connected to the infinite point or none of the
+        // faces whose circumcentres it uses have changed ignore
+        if (infinite || !changed) continue;
+
+        fc = fcStart;
+        label nVerts = 0;
+
+        do
+        {
+            vertices[nVerts++] = toPoint2D(circumcenter(fc));
+
+            if (nVerts == maxNvert)
+            {
+                break;
+            }
+        } while (++fc != fcStart);
+
+        // Check if dual-cell has a large number of faces in which case
+        // assumed to be in the far-field and reject
+        if (nVerts == maxNvert) continue;
+
+        // Set n+1 vertex to the first vertex for easy circulating
+        vertices[nVerts] = vertices[0];
+
+        // Convert triangle vertex to OpenFOAM point
+        point2DFromPoint defVert = toPoint2D(vit->point());
+
+        scalar maxProtSize2 = meshControls().maxNotchLen2();
+
+        if (vit->internalOrBoundaryPoint())
+        {
+            // Calculate metrics of the dual-cell
+            // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+            // The perimeter of the dual-cell
+            scalar perimeter = 0;
+
+            // Twice the area of the dual-cell
+            scalar areaT2 = 0;
+
+            for (int vi=0; vi<nVerts; vi++)
+            {
+                vector2D edge(vertices[vi+1] - vertices[vi]);
+                perimeter += mag(edge);
+                vector2D otherEdge = defVert - vertices[vi];
+                areaT2 += mag(edge.x()*otherEdge.y() - edge.y()*otherEdge.x());
+            }
+
+            // If the dual-cell is very small reject refinement
+            if (areaT2 < meshControls().minEdgeLen2()) continue;
+
+            // Estimate the cell width
+            scalar cellWidth = areaT2/perimeter;
+
+
+            // Check dimensions of dual-cell
+            /*
+            // Quick rejection of dual-cell refinement based on it's perimeter
+            if (perimeter < 2*meshControls().minCellSize()) continue;
+
+            // Also check the area of the cell and reject refinement
+            // if it is less than that allowed
+            if (areaT2 < meshControls().minCellSize2()) continue;
+
+            // Estimate the cell width and reject refinement if it is less than
+            // that allowed
+            if (cellWidth < 0.5*meshControls().minEdgeLen()) continue;
+            */
+
+            if
+            (
+                perimeter > 2*meshControls().minCellSize()
+             && areaT2 > meshControls().minCellSize2()
+             && cellWidth > 0.5*meshControls().minEdgeLen()
+            )
+            {
+                maxProtSize2 = 0.25*meshControls().maxNotchLen2();
+            }
+        }
+
+        if (insertPointPairAtIntersection(vit, defVert, vertices, maxProtSize2))
+        {
+            nIntersections++;
+        }
+    }
+
+    return nIntersections;
+}
+
+
+void Foam::CV2D::markNearBoundaryPoints()
+{
+    label count = 0;
+    for
+    (
+        Triangulation::Finite_vertices_iterator vit = finite_vertices_begin();
+        vit != finite_vertices_end();
+        vit++
+    )
+    {
+        if (vit->internalPoint())
+        {
+            point vert(toPoint3D(vit->point()));
+
+            pointIndexHit pHit;
+            label hitSurface = -1;
+
+            qSurf_.findSurfaceNearest
+            (
+                vert,
+                4*meshControls().minCellSize2(),
+                pHit,
+                hitSurface
+            );
+
+            if (pHit.hit())
+            {
+                vit->setNearBoundary();
+                ++count;
+            }
+        }
+    }
+
+    Info<< count << " points marked as being near a boundary" << endl;
+}
+
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/cv2DMesh/insertFeaturePoints.C b/applications/utilities/mesh/generation/cv2DMesh/insertFeaturePoints.C
new file mode 100644
index 0000000000000000000000000000000000000000..4765dc28bb9e847a1dbf229fa377729fbb8e3789
--- /dev/null
+++ b/applications/utilities/mesh/generation/cv2DMesh/insertFeaturePoints.C
@@ -0,0 +1,397 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2007-2011 OpenFOAM Foundation
+     \\/     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 "CV2D.H"
+#include "plane.H"
+#include "triSurfaceTools.H"
+#include "unitConversion.H"
+
+
+// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
+
+
+bool Foam::CV2D::on2DLine(const point2D& p, const linePointRef& line)
+{
+    const point2D& a = toPoint2D(line.start());
+    const point2D& b = toPoint2D(line.end());
+
+    if
+    (
+        p.x() < min(a.x(), b.x())
+     || p.x() > max(a.x(), b.x())
+     || p.y() < min(a.y(), b.y())
+     || p.y() > max(a.y(), b.y())
+    )
+    {
+        return false;
+    }
+
+    return true;
+}
+
+
+// Create feature points/edges by creating a triplet in the corner.
+// (this triplet will have as its circumcentre the feature)
+void Foam::CV2D::insertFeaturePoints()
+{
+    featurePoints_.clear();
+    label nVert = number_of_vertices();
+
+    const PtrList<extendedFeatureEdgeMesh>& feMeshes
+    (
+        qSurf_.features()
+    );
+
+    if (feMeshes.empty())
+    {
+        WarningIn("CV2D::insertFeaturePoints")
+            << "Extended Feature Edge Mesh is empty so no feature points will "
+            << "be found." << nl
+            << "    Use: featureMethod extendedFeatureEdgeMesh;" << nl
+            << endl;
+    }
+
+    forAll(feMeshes, i)
+    {
+        const extendedFeatureEdgeMesh& feMesh(feMeshes[i]);
+        const edgeList& edges = feMesh.edges();
+        const pointField& points = feMesh.points();
+
+        if (debug)
+        {
+            label nConvex = feMesh.concaveStart() - feMesh.convexStart();
+            label nConcave = feMesh.mixedStart() - feMesh.concaveStart();
+            label nMixed = feMesh.nonFeatureStart() - feMesh.mixedStart();
+            label nExternal = feMesh.internalStart() - feMesh.externalStart();
+            label nInternal = feMesh.flatStart() - feMesh.internalStart();
+            label nFlat = feMesh.openStart() - feMesh.flatStart();
+            label nOpen = feMesh.multipleStart() - feMesh.openStart();
+            label nMultiple = edges.size() - feMesh.multipleStart();
+
+            Info<< "Inserting Feature Points:" << nl
+                << "    Convex points: " << nConvex << nl
+                << "   Concave points: " << nConcave << nl
+                << "     Mixed points: " << nMixed << nl
+                << "   External edges: " << nExternal << nl
+                << "   Internal edges: " << nInternal << nl
+                << "       Flat edges: " << nFlat << nl
+                << "       Open edges: " << nOpen << nl
+                << "   Multiple edges: " << nMultiple << endl;
+        }
+
+        // Args: (base point, normal)
+        // @todo allow user to input this
+        plane zPlane(vector(0, 0, z_), vector(0, 0, 1));
+
+        if (debug)
+        {
+            Info<< "    plane: " << zPlane << " " << z_ << endl;
+        }
+
+        forAll(edges, edgeI)
+        {
+            const edge& e = feMesh.edges()[edgeI];
+
+            const point& ep0 = points[e.start()];
+            const point& ep1 = points[e.end()];
+
+            const linePointRef line(ep0, ep1);
+
+            scalar intersect = zPlane.lineIntersect(line);
+
+            point2D featPoint = toPoint2D(intersect * (ep1 - ep0) + ep0);
+
+            if (on2DLine(featPoint, line))
+            {
+                vector2DField fpn = toPoint2D(feMesh.edgeNormals(edgeI));
+
+                vector2D cornerNormal = sum(fpn);
+                cornerNormal /= mag(cornerNormal);
+
+                if (debug)
+                {
+                    Info<< nl << "    line: " << line << nl
+                        << "        vec: " << line.vec() << nl
+                        << "    featurePoint: " << featPoint << nl
+                        << "    line length: " << line.mag() << nl
+                        << "    intersect: " << intersect << endl;
+                }
+
+                if
+                (
+                    feMesh.getEdgeStatus(edgeI)
+                 == extendedFeatureEdgeMesh::EXTERNAL
+                )
+                {
+                    // Convex Point
+                    Foam::point2D internalPt =
+                        featPoint - meshControls().ppDist()*cornerNormal;
+
+                    if (debug)
+                    {
+                        Info<< "PREC: " << internalPt << nl
+                            << "    : " << featPoint << nl
+                            << "    : " << meshControls().ppDist() << nl
+                            << "    : " << cornerNormal << endl;
+                    }
+
+                    featurePoints_.push_back
+                    (
+                        Vb
+                        (
+                            toPoint(internalPt),
+                            nVert,
+                            nVert + 1
+                        )
+                    );
+                    label masterPtIndex = nVert++;
+
+                    forAll(fpn, nI)
+                    {
+                        const vector n3D(fpn[nI][0], fpn[nI][1], 0.0);
+
+                        plane planeN = plane(toPoint3D(featPoint), n3D);
+
+                        Foam::point2D externalPt =
+                            internalPt
+                          + (
+                                2.0
+                              * planeN.distance(toPoint3D(internalPt))
+                              * fpn[nI]
+                            );
+
+                        featurePoints_.push_back
+                        (
+                            Vb
+                            (
+                                toPoint(externalPt),
+                                nVert++,
+                                masterPtIndex
+                            )
+                        );
+
+                        if (debug)
+                        {
+                            Info<< "  side point: " << externalPt << endl;
+                        }
+                    }
+
+                    if (debug)
+                    {
+                        Info<< "Convex Point: " << featPoint << nl
+                            << "  corner norm: " << cornerNormal << nl
+                            << "    reference: " << internalPt << endl;
+                    }
+                }
+                else if
+                (
+                    feMesh.getEdgeStatus(edgeI)
+                 == extendedFeatureEdgeMesh::INTERNAL
+                )
+                {
+                    // Concave Point
+                    Foam::point2D externalPt =
+                        featPoint + meshControls().ppDist()*cornerNormal;
+
+                    Foam::point2D refPt =
+                        featPoint - meshControls().ppDist()*cornerNormal;
+
+                    label slavePointIndex = 0;
+
+                    scalar totalAngle =
+                        radToDeg
+                        (
+                            constant::mathematical::pi
+                          + acos(mag(fpn[0] & fpn[1]))
+                        );
+
+                    // Number of quadrants the angle should be split into
+                    int nQuads =
+                        int(totalAngle/meshControls().maxQuadAngle()) + 1;
+
+                    // The number of additional master points needed to
+                    //obtain the required number of quadrants.
+                    int nAddPoints = min(max(nQuads - 2, 0), 2);
+
+                    // index of reflMaster
+                    label reflectedMaster = nVert + 2 + nAddPoints;
+
+                    if (debug)
+                    {
+                        Info<< "Concave Point: " <<  featPoint << nl
+                            << "  corner norm: " << cornerNormal << nl
+                            << "     external: " << externalPt << nl
+                            << "    reference: " << refPt << nl
+                            << "        angle: " << totalAngle << nl
+                            << "       nQuads: " << nQuads << nl
+                            << "   nAddPoints: " << nAddPoints << endl;
+                    }
+
+                    forAll(fpn, nI)
+                    {
+                        const vector n3D(fpn[nI][0], fpn[nI][1], 0.0);
+
+                        plane planeN = plane(toPoint3D(featPoint), n3D);
+
+                        Foam::point2D internalPt =
+                            externalPt
+                          - (
+                                2.0
+                              * planeN.distance(toPoint3D(externalPt))
+                              * fpn[nI]
+                            );
+
+                        featurePoints_.push_back
+                        (
+                            Vb
+                            (
+                                toPoint(internalPt),
+                                nVert,
+                                reflectedMaster
+                            )
+                        );
+                        slavePointIndex = nVert++;
+
+                        if (debug)
+                        {
+                            Info<< "Internal Point: " <<  internalPt << endl;
+                        }
+                    }
+
+                    if (nAddPoints == 1)
+                    {
+                        // One additional point is the reflection of the slave
+                        // point, i.e., the original reference point
+                        featurePoints_.push_back
+                        (
+                            Vb
+                            (
+                                toPoint(refPt),
+                                nVert++,
+                                reflectedMaster
+                            )
+                        );
+
+                        if (debug)
+                        {
+                           Info<< "ref Point: " <<  refPt << endl;
+                        }
+                    }
+                    else if (nAddPoints == 2)
+                    {
+                       point2D reflectedAa =
+                           refPt - ((featPoint - externalPt) & fpn[1])*fpn[1];
+
+                       featurePoints_.push_back
+                       (
+                           Vb
+                           (
+                               toPoint(reflectedAa),
+                               nVert++,
+                               reflectedMaster
+                           )
+                       );
+
+                       point2D reflectedBb =
+                           refPt - ((featPoint - externalPt) & fpn[0])*fpn[0];
+
+                       featurePoints_.push_back
+                       (
+                           Vb
+                           (
+                               toPoint(reflectedBb),
+                               nVert++,
+                               reflectedMaster
+                           )
+                       );
+
+                       if (debug)
+                       {
+                           Info<< "refA Point: " <<  reflectedAa << nl
+                               << "refb Point: " <<  reflectedBb << endl;
+                       }
+                    }
+
+                    featurePoints_.push_back
+                    (
+                        Vb
+                        (
+                            toPoint(externalPt),
+                            nVert++,
+                            slavePointIndex
+                        )
+                    );
+                }
+                else
+                {
+                    WarningIn("void Foam::CV2D::insertFeaturePoints()")
+                        << "Feature Edge " << edges[edgeI] << nl
+                        << "    points(" << points[edges[edgeI].start()]
+                        << ", " << points[edges[edgeI].end()] << ")" << nl
+                        << "    is not labelled as either concave or convex, it"
+                        << " is labelled as (#2 = flat): "
+                        << feMesh.getEdgeStatus(edgeI) << endl;
+                }
+            }
+            else
+            {
+                WarningIn("void Foam::CV2D::insertFeaturePoints()")
+                      << "Point " << featPoint << " is not on the line "
+                      << line << endl;
+            }
+        }
+    }
+
+    // Insert the feature points.
+    reinsertFeaturePoints();
+
+    if (meshControls().objOutput())
+    {
+        writePoints("feat_allPoints.obj", false);
+        writeFaces("feat_allFaces.obj", false);
+        writeFaces("feat_faces.obj", true);
+        writeTriangles("feat_triangles.obj", true);
+    }
+}
+
+
+void Foam::CV2D::reinsertFeaturePoints()
+{
+    for
+    (
+        std::list<Vb>::iterator vit=featurePoints_.begin();
+        vit != featurePoints_.end();
+        ++vit
+    )
+    {
+        insertPoint
+        (
+            toPoint2D(vit->point()),
+            vit->index(),
+            vit->type()
+        );
+    }
+}
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/cv2DMesh/insertSurfaceNearPointPairs.C b/applications/utilities/mesh/generation/cv2DMesh/insertSurfaceNearPointPairs.C
new file mode 100644
index 0000000000000000000000000000000000000000..0773e41138dc75e0940c4f759d60bfb595fd6f34
--- /dev/null
+++ b/applications/utilities/mesh/generation/cv2DMesh/insertSurfaceNearPointPairs.C
@@ -0,0 +1,114 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2007-2011 OpenFOAM Foundation
+     \\/     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 "CV2D.H"
+
+// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
+
+void Foam::CV2D::insertSurfaceNearPointPairs()
+{
+    Info<< "insertSurfaceNearPointPairs: ";
+
+    label nNearPoints = 0;
+
+    for
+    (
+        Triangulation::Finite_edges_iterator eit = finite_edges_begin();
+        eit != finite_edges_end();
+        eit++
+    )
+    {
+        Vertex_handle v0h = eit->first->vertex(cw(eit->second));
+        Vertex_handle v1h = eit->first->vertex(ccw(eit->second));
+
+        if (v0h->ppMaster() && v1h->ppMaster())
+        {
+            point2DFromPoint v0(toPoint2D(v0h->point()));
+            point2DFromPoint v1(toPoint2D(v1h->point()));
+
+            // Check that the two triangle vertices are further apart than the
+            // minimum cell size
+            if (magSqr(v1 - v0) > meshControls().minCellSize2())
+            {
+                point2D e0(toPoint2D(circumcenter(eit->first)));
+
+                point2D e1
+                (
+                    toPoint2D(circumcenter(eit->first->neighbor(eit->second)))
+                );
+
+                // Calculate the length^2 of the edge normal to the surface
+                scalar edgeLen2 = magSqr(e0 - e1);
+
+                if (edgeLen2 < meshControls().minNearPointDist2())
+                {
+                    pointIndexHit pHit;
+                    label hitSurface = -1;
+
+                    qSurf_.findSurfaceNearest
+                    (
+                        toPoint3D(e0),
+                        meshControls().minEdgeLen2(),
+                        pHit,
+                        hitSurface
+                    );
+
+                    if (pHit.hit())
+                    {
+                        vectorField norm(1);
+                        qSurf_.geometry()[hitSurface].getNormal
+                        (
+                            List<pointIndexHit>(1, pHit),
+                            norm
+                        );
+
+                        insertPointPair
+                        (
+                            meshControls().ppDist(),
+                            toPoint2D(pHit.hitPoint()),
+                            toPoint2D(norm[0])
+                        );
+
+                        nNearPoints++;
+
+                        // Correct the edge iterator for the change in the 
+                        // number of edges following the point-pair insertion
+                        eit = Finite_edges_iterator
+                        (
+                            finite_edges_end().base(),
+                            eit.predicate(),
+                            eit.base()
+                        );
+                    }
+                }
+            }
+        }
+    }
+
+    Info<< nNearPoints << " point-pairs inserted" << endl;
+}
+
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/cv2DMesh/insertSurfaceNearestPointPairs.C b/applications/utilities/mesh/generation/cv2DMesh/insertSurfaceNearestPointPairs.C
new file mode 100644
index 0000000000000000000000000000000000000000..e04955ab0886f9886e2c6f9865505f8e069233e3
--- /dev/null
+++ b/applications/utilities/mesh/generation/cv2DMesh/insertSurfaceNearestPointPairs.C
@@ -0,0 +1,244 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2007-2011 OpenFOAM Foundation
+     \\/     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 "CV2D.H"
+
+// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
+
+bool Foam::CV2D::dualCellSurfaceIntersection
+(
+    const Triangulation::Finite_vertices_iterator& vit
+) const
+{
+    Triangulation::Edge_circulator ecStart = incident_edges(vit);
+    Triangulation::Edge_circulator ec = ecStart;
+
+    do
+    {
+        if (!is_infinite(ec))
+        {
+            point e0 = toPoint3D(circumcenter(ec->first));
+
+            // If edge end is outside bounding box then edge cuts boundary
+            if (!qSurf_.globalBounds().contains(e0))
+            {
+                return true;
+            }
+
+            point e1 = toPoint3D(circumcenter(ec->first->neighbor(ec->second)));
+
+            // If other edge end is ouside bounding box then edge cuts boundary
+            if (!qSurf_.globalBounds().contains(e1))
+            {
+                return true;
+            }
+
+            if (magSqr(e1 - e0) > meshControls().minEdgeLen2())
+            {
+                if (qSurf_.findSurfaceAnyIntersection(e0, e1))
+                {
+                    return true;
+                }
+            }
+        }
+
+    } while (++ec != ecStart);
+
+    return false;
+}
+
+
+void Foam::CV2D::insertPointPairs
+(
+    const DynamicList<point2D>& nearSurfacePoints,
+    const DynamicList<point2D>& surfacePoints,
+    const DynamicList<label>& surfaceTris,
+    const DynamicList<label>& surfaceHits,
+    const fileName fName
+)
+{
+    if (meshControls().mirrorPoints())
+    {
+        forAll(surfacePoints, ppi)
+        {
+            insertMirrorPoint
+            (
+                nearSurfacePoints[ppi],
+                surfacePoints[ppi]
+            );
+        }
+    }
+    else
+    {
+        forAll(surfacePoints, ppi)
+        {
+            pointIndexHit pHit
+            (
+                true,
+                toPoint3D(surfacePoints[ppi]),
+                surfaceTris[ppi]
+            );
+
+            vectorField norm(1);
+            qSurf_.geometry()[surfaceHits[ppi]].getNormal
+            (
+                List<pointIndexHit>(1, pHit),
+                norm
+            );
+
+            insertPointPair
+            (
+                meshControls().ppDist(),
+                surfacePoints[ppi],
+                toPoint2D(norm[0])
+            );
+        }
+    }
+
+    Info<< surfacePoints.size() << " point-pairs inserted" << endl;
+
+    if (meshControls().objOutput())
+    {
+        OFstream str(fName);
+        label vertI = 0;
+
+        forAll(surfacePoints, ppi)
+        {
+            meshTools::writeOBJ(str, toPoint3D(surfacePoints[ppi]));
+            vertI++;
+        }
+
+        Info<< "insertPointPairs: Written " << surfacePoints.size()
+            << " inserted point-pair locations to file "
+            << str.name() << endl;
+    }
+}
+
+
+void Foam::CV2D::insertSurfaceNearestPointPairs()
+{
+    Info<< "insertSurfaceNearestPointPairs: ";
+
+    label nSurfacePointsEst =
+        min
+        (
+            number_of_vertices(),
+            size_t(10*sqrt(scalar(number_of_vertices())))
+        );
+
+    DynamicList<point2D> nearSurfacePoints(nSurfacePointsEst);
+    DynamicList<point2D> surfacePoints(nSurfacePointsEst);
+    DynamicList<label> surfaceTris(nSurfacePointsEst);
+    DynamicList<label> surfaceHits(nSurfacePointsEst);
+
+    // Local references to surface mesh addressing
+//    const pointField& localPoints = qSurf_.localPoints();
+//    const labelListList& edgeFaces = qSurf_.edgeFaces();
+//    const vectorField& faceNormals = qSurf_.faceNormals();
+//    const labelListList& faceEdges = qSurf_.faceEdges();
+
+    for
+    (
+        Triangulation::Finite_vertices_iterator vit = finite_vertices_begin();
+        vit != finite_vertices_end();
+        vit++
+    )
+    {
+        if (vit->internalPoint())
+        {
+            point2DFromPoint vert(toPoint2D(vit->point()));
+
+            pointIndexHit pHit;
+            label hitSurface = -1;
+
+            qSurf_.findSurfaceNearest
+            (
+                toPoint3D(vert),
+                4*meshControls().minCellSize2(),
+                pHit,
+                hitSurface
+            );
+
+            if (pHit.hit())
+            {
+                vit->setNearBoundary();
+
+                // Reference to the nearest triangle
+//                const labelledTri& f = qSurf_[hitSurface];
+
+//                // Find where point is on triangle.
+//                // Note tolerance needed is relative one
+//                // (used in comparing normalized [0..1] triangle coordinates).
+//                label nearType, nearLabel;
+//                triPointRef
+//                (
+//                    localPoints[f[0]],
+//                    localPoints[f[1]],
+//                    localPoints[f[2]]
+//                ).classify(pHit.hitPoint(), nearType, nearLabel);
+
+//                // If point is on a edge check if it is an internal feature
+
+//                bool internalFeatureEdge = false;
+
+//                if (nearType == triPointRef::EDGE)
+//                {
+//                    label edgeI = faceEdges[hitSurface][nearLabel];
+//                    const labelList& eFaces = edgeFaces[edgeI];
+
+//                    if
+//                    (
+//                        eFaces.size() == 2
+//                     && (faceNormals[eFaces[0]] & faceNormals[eFaces[1]])
+//                       < -0.2
+//                    )
+//                    {
+//                        internalFeatureEdge = true;
+//                    }
+//                }
+
+                if (dualCellSurfaceIntersection(vit)) //&& !internalFeatureEdge)
+                {
+                    nearSurfacePoints.append(vert);
+                    surfacePoints.append(toPoint2D(pHit.hitPoint()));
+                    surfaceTris.append(pHit.index());
+                    surfaceHits.append(hitSurface);
+                }
+            }
+        }
+    }
+
+    insertPointPairs
+    (
+        nearSurfacePoints,
+        surfacePoints,
+        surfaceTris,
+        surfaceHits,
+        "surfaceNearestIntersections.obj"
+    );
+}
+
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/cv2DMesh/shortEdgeFilter2D.C b/applications/utilities/mesh/generation/cv2DMesh/shortEdgeFilter2D.C
new file mode 100644
index 0000000000000000000000000000000000000000..5e960cb558fe3118f9eaf3df280c6be05a69d965
--- /dev/null
+++ b/applications/utilities/mesh/generation/cv2DMesh/shortEdgeFilter2D.C
@@ -0,0 +1,505 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
+     \\/     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 "shortEdgeFilter2D.H"
+
+namespace Foam
+{
+
+defineTypeNameAndDebug(shortEdgeFilter2D, 0);
+
+}
+
+// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
+
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::shortEdgeFilter2D::shortEdgeFilter2D
+(
+    const Foam::CV2D& cv2Dmesh,
+    const dictionary& dict
+)
+:
+    cv2Dmesh_(cv2Dmesh),
+    shortEdgeFilterFactor_(readScalar(dict.lookup("shortEdgeFilterFactor"))),
+    edgeAttachedToBoundaryFactor_
+    (
+        dict.lookupOrDefault<scalar>("edgeAttachedToBoundaryFactor", 2.0)
+    ),
+    patchNames_(wordList()),
+    patchSizes_(labelList()),
+    mapEdgesRegion_()
+{
+    point2DField points2D;
+    faceList faces;
+
+    cv2Dmesh.calcDual
+    (
+        points2D,
+        faces,
+        patchNames_,
+        patchSizes_,
+        mapEdgesRegion_
+    );
+
+    pointField points(points2D.size());
+    forAll(points, ip)
+    {
+        points[ip] = cv2Dmesh.toPoint3D(points2D[ip]);
+    }
+
+    points2D.clear();
+
+    ms_ = MeshedSurface<face>(xferMove(points), xferMove(faces));
+
+    Info<< "Meshed surface stats before edge filtering :" << endl;
+    ms_.writeStats(Info);
+
+    if (debug)
+    {
+        writeInfo(Info);
+
+        ms_.write("MeshedSurface_preFilter.obj");
+    }
+}
+
+
+// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
+
+Foam::shortEdgeFilter2D::~shortEdgeFilter2D()
+{}
+
+
+// * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * * //
+
+void
+Foam::shortEdgeFilter2D::filter()
+{
+    // These are global indices.
+    const pointField& points = ms_.points();
+    const edgeList& edges = ms_.edges();
+    const faceList& faces = ms_.faces();
+    const labelList& meshPoints = ms_.meshPoints();
+    const labelList& boundaryPoints = ms_.boundaryPoints();
+
+    label maxChain = 0;
+    label nPointsToRemove = 0;
+
+    labelList pointsToRemove(ms_.points().size(), -1);
+
+    // List of number of vertices in a face.
+    labelList newFaceVertexCount(faces.size(), -1);
+    forAll(faces, faceI)
+    {
+        newFaceVertexCount[faceI] = faces[faceI].size();
+    }
+
+    // Check if the point is a boundary point. Flag if it is so that
+    // it will not be deleted.
+    boolList boundaryPointFlags(points.size(), false);
+    // This has been removed, otherwise small edges on the boundary are not
+    // removed.
+    /*  forAll(boundaryPointFlags, pointI)
+    {
+        forAll(boundaryPoints, bPoint)
+        {
+            if (meshPoints[boundaryPoints[bPoint]] == pointI)
+            {
+                boundaryPointFlags[pointI] = true;
+            }
+        }
+    }*/
+
+    // Check if an edge has a boundary point. It it does the edge length
+    // will be doubled when working out its length.
+    Info<< "    Marking edges attached to boundaries." << endl;
+    boolList edgeAttachedToBoundary(edges.size(), false);
+    forAll(edges, edgeI)
+    {
+        const edge& e = edges[edgeI];
+        const label startVertex = e.start();
+        const label endVertex = e.end();
+
+        forAll(boundaryPoints, bPoint)
+        {
+            if
+            (
+                boundaryPoints[bPoint] == startVertex
+             || boundaryPoints[bPoint] == endVertex
+            )
+            {
+                edgeAttachedToBoundary[edgeI] = true;
+            }
+        }
+    }
+
+    forAll(edges, edgeI)
+    {
+        const edge& e = edges[edgeI];
+
+        // get the vertices of that edge.
+        const label startVertex = e.start();
+        const label endVertex = e.end();
+
+        scalar edgeLength =
+            mag
+            (
+                points[meshPoints[e.start()]]
+              - points[meshPoints[e.end()]]
+            );
+
+        if (edgeAttachedToBoundary[edgeI])
+        {
+            edgeLength *= edgeAttachedToBoundaryFactor_;
+        }
+
+        scalar shortEdgeFilterValue = 0.0;
+
+        const labelList& psEdges = ms_.pointEdges()[startVertex];
+        const labelList& peEdges = ms_.pointEdges()[endVertex];
+
+        forAll(psEdges, psEdgeI)
+        {
+            const edge& psE = edges[psEdges[psEdgeI]];
+            if (edgeI != psEdges[psEdgeI])
+            {
+                shortEdgeFilterValue +=
+                    mag
+                    (
+                        points[meshPoints[psE.start()]]
+                       -points[meshPoints[psE.end()]]
+                    );
+            }
+        }
+
+        forAll(peEdges, peEdgeI)
+        {
+            const edge& peE = edges[peEdges[peEdgeI]];
+            if (edgeI != peEdges[peEdgeI])
+            {
+                shortEdgeFilterValue +=
+                    mag
+                    (
+                        points[meshPoints[peE.start()]]
+                       -points[meshPoints[peE.end()]]
+                    );
+            }
+        }
+
+        shortEdgeFilterValue *=
+            shortEdgeFilterFactor_
+           /(psEdges.size() + peEdges.size() - 2);
+
+        if (edgeLength < shortEdgeFilterValue)
+        {
+            bool flagDegenerateFace = false;
+            const labelList& pFaces = ms_.pointFaces()[startVertex];
+
+            forAll(pFaces, pFaceI)
+            {
+                const face& f = ms_.localFaces()[pFaces[pFaceI]];
+                forAll(f, fp)
+                {
+                    // If the edge is part of this face...
+                    if (f[fp] == endVertex)
+                    {
+                        // If deleting vertex would create a triangle, don't!
+                        if (newFaceVertexCount[pFaces[pFaceI]] < 4)
+                        {
+                            flagDegenerateFace = true;
+                        }
+                        else
+                        {
+                            newFaceVertexCount[pFaces[pFaceI]]--;
+                        }
+                    }
+                    // If the edge is not part of this face...
+                    else
+                    {
+                        // Deleting vertex of a triangle...
+                        if (newFaceVertexCount[pFaces[pFaceI]] < 3)
+                        {
+                            flagDegenerateFace = true;
+                        }
+                    }
+                }
+            }
+
+            // This if statement determines whether a point should be deleted.
+            if
+            (
+                pointsToRemove[meshPoints[startVertex]] == -1
+             && pointsToRemove[meshPoints[endVertex]] == -1
+             && !boundaryPointFlags[meshPoints[startVertex]]
+             && !flagDegenerateFace
+            )
+            {
+                pointsToRemove[meshPoints[startVertex]] =
+                    meshPoints[endVertex];
+                ++nPointsToRemove;
+            }
+        }
+    }
+
+    label totalNewPoints = points.size() - nPointsToRemove;
+
+    pointField newPoints(totalNewPoints, vector(0, 0, 0));
+    labelList newPointNumbers(points.size(), -1);
+    label numberRemoved=0;
+
+    forAll(points, pointI)
+    {
+        // If the point is NOT going to be removed.
+        if (pointsToRemove[pointI] == -1)
+        {
+            newPoints[pointI-numberRemoved] = points[pointI];
+            newPointNumbers[pointI] =  pointI-numberRemoved;
+        }
+        else
+        {
+            numberRemoved++;
+        }
+    }
+
+    // Need a new faceList
+    faceList newFaces(faces.size());
+    label newFaceI = 0;
+
+    labelList newFace;
+    label newFaceSize = 0;
+
+    // Now need to iterate over the faces and remove points. Global index.
+    forAll(faces, faceI)
+    {
+        const face& f = faces[faceI];
+
+        newFace.clear();
+        newFace.setSize(f.size());
+        newFaceSize = 0;
+
+        forAll(f, fp)
+        {
+            label pointI = f[fp];
+            // If not removing the point, then add it to the new face.
+            if (pointsToRemove[pointI] == -1)
+            {
+                newFace[newFaceSize++] = newPointNumbers[pointI];
+            }
+            else
+            {
+                label newPointI = pointsToRemove[pointI];
+                // Replace deleted point with point that it is being
+                // collapsed to.
+                if
+                (
+                    f.nextLabel(fp) != newPointI
+                 && f.prevLabel(fp) != newPointI
+                )
+                {
+                    label pChain = newPointI;
+                    label totalChain = 0;
+                    for (label nChain = 0; nChain <= totalChain; ++nChain)
+                    {
+                        if (newPointNumbers[pChain] != -1)
+                        {
+                            newFace[newFaceSize++] = newPointNumbers[pChain];
+                            newPointNumbers[pointI]
+                                = newPointNumbers[pChain];
+                            maxChain = max(totalChain, maxChain);
+                        }
+                        else
+                        {
+                            WarningIn("shortEdgeFilter")
+                                << "Point " << pChain
+                                << " marked for deletion as well as point "
+                                << pointI << nl
+                                << "    Incrementing maxChain by 1 from "
+                                << totalChain << " to " << totalChain + 1
+                                << endl;
+                            totalChain++;
+                        }
+                        pChain = pointsToRemove[pChain];
+                    }
+                }
+                else
+                {
+                    if (newPointNumbers[newPointI] != -1)
+                    {
+                        newPointNumbers[pointI] = newPointNumbers[newPointI];
+                    }
+                }
+            }
+        }
+
+        newFace.setSize(newFaceSize);
+
+        if (newFace.size() > 2)
+        {
+            newFaces[newFaceI++] = face(newFace);
+        }
+        else
+        {
+            FatalErrorIn("shortEdgeFilter")
+                << "Only " << newFace.size() << " in face " << faceI
+                << exit(FatalError);
+        }
+    }
+
+    newFaces.setSize(newFaceI);
+
+    MeshedSurface<face> fMesh
+    (
+        xferMove(newPoints),
+        xferMove(newFaces),
+        xferCopy(List<surfZone>())
+    );
+
+    const Map<int>& fMeshPointMap = fMesh.meshPointMap();
+
+    // Reset patchSizes_
+    patchSizes_.clear();
+    patchSizes_.setSize(patchNames_.size(), 0);
+
+    label equalEdges = 0;
+    label notFound = 0;
+    label matches = 0;
+    label negativeLabels = 0;
+
+    forAll(newPointNumbers, pointI)
+    {
+        if (newPointNumbers[pointI] == -1)
+        {
+            WarningIn("shortEdgeFilter")
+                << pointI << " will be deleted and " << newPointNumbers[pointI]
+                << ", so it will not be replaced. "
+                << "This will cause edges to be deleted." << endl;
+        }
+    }
+
+    // Create new EdgeMap.
+    Info<< "Creating new EdgeMap." << endl;
+    EdgeMap<label> newMapEdgesRegion(mapEdgesRegion_.size());
+
+    for
+    (
+        label bEdgeI = ms_.nInternalEdges();
+        bEdgeI < edges.size();
+        ++bEdgeI
+    )
+    {
+        label p1 = meshPoints[edges[bEdgeI][0]];
+        label p2 = meshPoints[edges[bEdgeI][1]];
+
+        edge e(p1, p2);
+
+        if (mapEdgesRegion_.found(e))
+        {
+            if
+            (
+                newPointNumbers[p1] != -1
+             && newPointNumbers[p2] != -1
+            )
+            {
+                if (newPointNumbers[p1] != newPointNumbers[p2])
+                {
+                    label region = mapEdgesRegion_.find(e)();
+                    newMapEdgesRegion.insert
+                    (
+                        edge
+                        (
+                            fMeshPointMap[newPointNumbers[p1]],
+                            fMeshPointMap[newPointNumbers[p2]]
+                        ),
+                        region
+                    );
+                    patchSizes_[region]++;
+                    matches++;
+                }
+                else
+                {
+                    equalEdges++;
+                }
+            }
+            else
+            {
+                negativeLabels++;
+            }
+        }
+        else
+        {
+            notFound++;
+        }
+    }
+
+    if (debug)
+    {
+        Info<< "EdgeMapping  :" << nl
+            << "    Matches  : " << matches << nl
+            << "    Equal    : " << equalEdges << nl
+            << "    Negative : " << negativeLabels << nl
+            << "    Not Found: " << notFound << endl;
+    }
+
+    mapEdgesRegion_.transfer(newMapEdgesRegion);
+
+    ms_.transfer(fMesh);
+
+    Info<< "    Maximum number of chained collapses = " << maxChain << endl;
+
+    if (debug)
+    {
+        writeInfo(Info);
+    }
+}
+
+
+void Foam::shortEdgeFilter2D::writeInfo(Ostream& os)
+{
+    os  << "Short Edge Filtering Information:" << nl
+        << "           shortEdgeFilterFactor: " << shortEdgeFilterFactor_ << nl
+        << "    edgeAttachedToBoundaryFactor: " << edgeAttachedToBoundaryFactor_
+        << endl;
+
+    forAll(patchNames_, patchI)
+    {
+        os  << "    Patch " << patchNames_[patchI]
+            << ", size " << patchSizes_[patchI] << endl;
+    }
+
+    os  << "    There are " << mapEdgesRegion_.size()
+        << " boundary edges." << endl;
+
+    os  << "    Mesh Info:" << nl
+        << "        Points:       " << ms_.nPoints() << nl
+        << "        Faces:        " << ms_.size() << nl
+        << "        Edges:        " << ms_.nEdges() << nl
+        << "            Internal: " << ms_.nInternalEdges() << nl
+        << "            External: " << ms_.nEdges() - ms_.nInternalEdges()
+        << endl;
+}
+
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/cv2DMesh/shortEdgeFilter2D.H b/applications/utilities/mesh/generation/cv2DMesh/shortEdgeFilter2D.H
new file mode 100644
index 0000000000000000000000000000000000000000..1a100bcb200d6dd604f4fa25bd2a3dc904cf3989
--- /dev/null
+++ b/applications/utilities/mesh/generation/cv2DMesh/shortEdgeFilter2D.H
@@ -0,0 +1,136 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2011-2011 OpenFOAM Foundation
+     \\/     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::shortEdgeFilter2D
+
+Description
+    This class filters short edges generated by the CV2D mesher.
+
+SourceFiles
+    shortEdgeFilter2D.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef shortEdgeFilter2D_H
+#define shortEdgeFilter2D_H
+
+#include "MeshedSurfaces.H"
+#include "CV2D.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+/*---------------------------------------------------------------------------*\
+                     Class shortEdgeFilter2D Declaration
+\*---------------------------------------------------------------------------*/
+
+class shortEdgeFilter2D
+{
+    // Private data
+
+        //- Description of data_
+        const CV2D& cv2Dmesh_;
+
+        MeshedSurface<face> ms_;
+
+        const scalar shortEdgeFilterFactor_;
+
+        const scalar edgeAttachedToBoundaryFactor_;
+
+        wordList patchNames_;
+
+        labelList patchSizes_;
+
+        EdgeMap<label> mapEdgesRegion_;
+
+
+    // Private Member Functions
+
+        //- Disallow default bitwise copy construct
+        shortEdgeFilter2D(const shortEdgeFilter2D&);
+
+        //- Disallow default bitwise assignment
+        void operator=(const shortEdgeFilter2D&);
+
+
+public:
+
+    //- Runtime type information
+    ClassName("shortEdgeFilter2D");
+
+    // Constructors
+
+        shortEdgeFilter2D
+        (
+            const CV2D& cv2Dmesh,
+            const dictionary& dict
+        );
+
+
+    //- Destructor
+    ~shortEdgeFilter2D();
+
+
+    // Access Functions
+
+        const wordList& patchNames() const
+        {
+            return patchNames_;
+        }
+
+        const labelList& patchSizes() const
+        {
+            return patchSizes_;
+        }
+
+        const EdgeMap<label>& mapEdgesRegion() const
+        {
+            return mapEdgesRegion_;
+        }
+
+        const MeshedSurface<face>& fMesh() const
+        {
+            return ms_;
+        }
+
+    // Member Functions
+
+        void filter();
+
+        void writeInfo(Ostream& os);
+
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/cvMesh/changesLaurence b/applications/utilities/mesh/generation/cvMesh/changesLaurence
new file mode 100644
index 0000000000000000000000000000000000000000..5f55eff4624d66db182879be4d9a515a9c1ac581
--- /dev/null
+++ b/applications/utilities/mesh/generation/cvMesh/changesLaurence
@@ -0,0 +1,5 @@
+wmake/rules/General/CGAL
+
+    -lboost_thread
+    -lboost_thread-mt
+
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeControlSurfaces.C b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeControlSurfaces.C
index 8f7ed466732363fe5f9e54131bf5f3781239ac69..0fa17fc86aeabf8e950ea5c791a7e17e178e0da1 100644
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeControlSurfaces.C
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeControlSurfaces.C
@@ -152,12 +152,10 @@ bool Foam::cellSizeControlSurfaces::evalCellSizeFunctions
 
 Foam::cellSizeControlSurfaces::cellSizeControlSurfaces
 (
-    const conformalVoronoiMesh& cvMesh,
     const searchableSurfaces& allGeometry,
     const dictionary& motionControlDict
 )
 :
-    cvMesh_(cvMesh),
     allGeometry_(allGeometry),
     surfaces_(),
     cellSizeFunctions_(),
@@ -223,7 +221,6 @@ Foam::cellSizeControlSurfaces::cellSizeControlSurfaces
             cellSizeFunction::New
             (
                 surfaceSubDict,
-                cvMesh,
                 surface
             )
         );
@@ -284,40 +281,41 @@ Foam::scalar Foam::cellSizeControlSurfaces::cellSize
 {
     scalar size = defaultCellSize_;
 
-    bool anyFunctionFound = evalCellSizeFunctions(pt, size);
-
-    if (!anyFunctionFound)
-    {
-        // Check if the point in question was actually inside the domain, if
-        // not, then it may be falling back to an inappropriate default size.
-
-        if (cvMesh_.geometryToConformTo().outside(pt))
-        {
-            pointIndexHit surfHit;
-            label hitSurface;
-
-            cvMesh_.geometryToConformTo().findSurfaceNearest
-            (
-                pt,
-                sqr(GREAT),
-                surfHit,
-                hitSurface
-            );
-
-            if (!surfHit.hit())
-            {
-                FatalErrorIn
-                (
-                    "Foam::scalar Foam::cellSizeControlSurfaces::cellSize"
-                    "("
-                        "const point& pt"
-                    ") const"
-                )
-                    << "Point " << pt << " did not find a nearest surface point"
-                    << nl << exit(FatalError) << endl;
-            }
-        }
-    }
+//  bool anyFunctionFound = evalCellSizeFunctions(pt, size);
+    evalCellSizeFunctions(pt, size);
+
+//if (!anyFunctionFound)
+//{
+//    // Check if the point in question was actually inside the domain, if
+//    // not, then it may be falling back to an inappropriate default size.
+
+//    if (cvMesh_.geometryToConformTo().outside(pt))
+//    {
+//        pointIndexHit surfHit;
+//        label hitSurface;
+
+//        cvMesh_.geometryToConformTo().findSurfaceNearest
+//        (
+//            pt,
+//            sqr(GREAT),
+//            surfHit,
+//            hitSurface
+//        );
+
+//        if (!surfHit.hit())
+//        {
+//            FatalErrorIn
+//            (
+//                "Foam::scalar Foam::cellSizeControlSurfaces::cellSize"
+//                "("
+//                    "const point& pt"
+//                ") const"
+//            )
+//                << "Point " << pt << " did not find a nearest surface point"
+//                << nl << exit(FatalError) << endl;
+//        }
+//    }
+//}
 
     return size;
 }
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeControlSurfaces.H b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeControlSurfaces.H
index 17dfd10325bf73d011b6f27c0092f4836e1901f6..4b6c53bc2acb1eae64104a600358f67585e159dc 100644
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeControlSurfaces.H
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeControlSurfaces.H
@@ -57,9 +57,6 @@ class cellSizeControlSurfaces
 {
     // Private data
 
-        //- Reference to the conformalVoronoiMesh holding this object
-        const conformalVoronoiMesh& cvMesh_;
-
         //- Reference to the searchableSurfaces object holding all geometry data
         const searchableSurfaces& allGeometry_;
 
@@ -106,7 +103,6 @@ public:
         //  searchableSurfaces
         cellSizeControlSurfaces
         (
-            const conformalVoronoiMesh& cvMesh,
             const searchableSurfaces& allGeometry,
             const dictionary& motionControlDict
         );
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeFunction/cellSizeFunction/cellSizeFunction.C b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeFunction/cellSizeFunction/cellSizeFunction.C
index 9d7cc3084ab5ee02cdf4b5c978a25589dd43c0ba..37d6c7825ae74b4df60a6e540f9332a443efc41a 100644
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeFunction/cellSizeFunction/cellSizeFunction.C
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeFunction/cellSizeFunction/cellSizeFunction.C
@@ -45,12 +45,10 @@ cellSizeFunction::cellSizeFunction
 (
     const word& type,
     const dictionary& cellSizeFunctionDict,
-    const conformalVoronoiMesh& cvMesh,
     const searchableSurface& surface
 )
 :
     dictionary(cellSizeFunctionDict),
-    cvMesh_(cvMesh),
     surface_(surface),
     coeffsDict_(subDict(type + "Coeffs")),
     sideMode_(),
@@ -99,7 +97,6 @@ cellSizeFunction::cellSizeFunction
 autoPtr<cellSizeFunction> cellSizeFunction::New
 (
     const dictionary& cellSizeFunctionDict,
-    const conformalVoronoiMesh& cvMesh,
     const searchableSurface& surface
 )
 {
@@ -130,7 +127,7 @@ autoPtr<cellSizeFunction> cellSizeFunction::New
 
     return autoPtr<cellSizeFunction>
     (
-        cstrIter()(cellSizeFunctionDict, cvMesh, surface)
+        cstrIter()(cellSizeFunctionDict, surface)
     );
 }
 
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeFunction/cellSizeFunction/cellSizeFunction.H b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeFunction/cellSizeFunction/cellSizeFunction.H
index 82535194a85e63a7c52cae10d534bdfa3d6299e9..6b33ec7ca7714c676d04e39a636f439e29da817a 100644
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeFunction/cellSizeFunction/cellSizeFunction.H
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeFunction/cellSizeFunction/cellSizeFunction.H
@@ -81,9 +81,6 @@ protected:
 
     // Protected data
 
-        //- Reference to the conformalVoronoiMesh holding this cvs object
-        const conformalVoronoiMesh& cvMesh_;
-
         //- Reference to the searchableSurface that cellSizeFunction
         //  relates to
         const searchableSurface& surface_;
@@ -120,10 +117,9 @@ public:
             dictionary,
             (
                 const dictionary& cellSizeFunctionDict,
-                const conformalVoronoiMesh& cvMesh,
                 const searchableSurface& surface
             ),
-            (cellSizeFunctionDict, cvMesh, surface)
+            (cellSizeFunctionDict, surface)
         );
 
 
@@ -134,7 +130,6 @@ public:
         (
             const word& type,
             const dictionary& cellSizeFunctionDict,
-            const conformalVoronoiMesh& cvMesh,
             const searchableSurface& surface
         );
 
@@ -145,7 +140,6 @@ public:
         static autoPtr<cellSizeFunction> New
         (
             const dictionary& cellSizeFunctionDict,
-            const conformalVoronoiMesh& cvMesh,
             const searchableSurface& surface
         );
 
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeFunction/linearDistance/linearDistance.C b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeFunction/linearDistance/linearDistance.C
index 702ac53bc6827e864a6c72a8d4e9b23069f89f0f..0874d9fc8231a9745f923ff4039aac41139cd4bc 100644
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeFunction/linearDistance/linearDistance.C
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeFunction/linearDistance/linearDistance.C
@@ -42,11 +42,10 @@ addToRunTimeSelectionTable(cellSizeFunction, linearDistance, dictionary);
 linearDistance::linearDistance
 (
     const dictionary& initialPointsDict,
-    const conformalVoronoiMesh& cvMesh,
     const searchableSurface& surface
 )
 :
-    cellSizeFunction(typeName, initialPointsDict, cvMesh, surface),
+    cellSizeFunction(typeName, initialPointsDict, surface),
     surfaceCellSize_(readScalar(coeffsDict().lookup("surfaceCellSize"))),
     distanceCellSize_(readScalar(coeffsDict().lookup("distanceCellSize"))),
     distance_(readScalar(coeffsDict().lookup("distance"))),
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeFunction/linearDistance/linearDistance.H b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeFunction/linearDistance/linearDistance.H
index 9799a1f7d069eb61859fed0c3240348df6ead35f..0906680150b6e0d9a61d92c4164e5f248fb42dc2 100644
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeFunction/linearDistance/linearDistance.H
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeFunction/linearDistance/linearDistance.H
@@ -87,7 +87,6 @@ public:
         linearDistance
         (
             const dictionary& initialPointsDict,
-            const conformalVoronoiMesh& cvMesh,
             const searchableSurface& surface
         );
 
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeFunction/linearSpatial/linearSpatial.C b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeFunction/linearSpatial/linearSpatial.C
index 1caeca1ffa242fb6ff31b00f93703e42e8fccd55..d877ffee64504a81848c7e3fe019415a977871f4 100644
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeFunction/linearSpatial/linearSpatial.C
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeFunction/linearSpatial/linearSpatial.C
@@ -42,11 +42,10 @@ addToRunTimeSelectionTable(cellSizeFunction, linearSpatial, dictionary);
 linearSpatial::linearSpatial
 (
     const dictionary& initialPointsDict,
-    const conformalVoronoiMesh& cvMesh,
     const searchableSurface& surface
 )
 :
-    cellSizeFunction(typeName, initialPointsDict, cvMesh, surface),
+    cellSizeFunction(typeName, initialPointsDict, surface),
     referencePoint_(coeffsDict().lookup("referencePoint")),
     referenceCellSize_(readScalar(coeffsDict().lookup("referenceCellSize"))),
     direction_(coeffsDict().lookup("direction")),
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeFunction/linearSpatial/linearSpatial.H b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeFunction/linearSpatial/linearSpatial.H
index 177f92fdf9326d9dccd9354fb4950dbe3dc3bd94..faf4d52359422eba3afd2bd94d86fba0d687f90f 100644
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeFunction/linearSpatial/linearSpatial.H
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeFunction/linearSpatial/linearSpatial.H
@@ -85,7 +85,6 @@ public:
         linearSpatial
         (
             const dictionary& initialPointsDict,
-            const conformalVoronoiMesh& cvMesh,
             const searchableSurface& surface
         );
 
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeFunction/surfaceOffsetLinearDistance/surfaceOffsetLinearDistance.C b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeFunction/surfaceOffsetLinearDistance/surfaceOffsetLinearDistance.C
index 40960a81238608a670303554ee2418313dfc040d..bb7ffa6a9a11417c097897ca35701f6ad76de1f1 100644
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeFunction/surfaceOffsetLinearDistance/surfaceOffsetLinearDistance.C
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeFunction/surfaceOffsetLinearDistance/surfaceOffsetLinearDistance.C
@@ -46,11 +46,10 @@ addToRunTimeSelectionTable
 surfaceOffsetLinearDistance::surfaceOffsetLinearDistance
 (
     const dictionary& initialPointsDict,
-    const conformalVoronoiMesh& cvMesh,
     const searchableSurface& surface
 )
 :
-    cellSizeFunction(typeName, initialPointsDict, cvMesh, surface),
+    cellSizeFunction(typeName, initialPointsDict, surface),
     surfaceCellSize_(readScalar(coeffsDict().lookup("surfaceCellSize"))),
     distanceCellSize_(readScalar(coeffsDict().lookup("distanceCellSize"))),
     surfaceOffset_(readScalar(coeffsDict().lookup("surfaceOffset"))),
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeFunction/surfaceOffsetLinearDistance/surfaceOffsetLinearDistance.H b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeFunction/surfaceOffsetLinearDistance/surfaceOffsetLinearDistance.H
index 2b341181028472f5a77c1bb27aa9996b9f75cd0b..2b1d3a6f0e293dbbccf86cca27fabf8f721a9c61 100644
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeFunction/surfaceOffsetLinearDistance/surfaceOffsetLinearDistance.H
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeFunction/surfaceOffsetLinearDistance/surfaceOffsetLinearDistance.H
@@ -94,7 +94,6 @@ public:
         surfaceOffsetLinearDistance
         (
             const dictionary& initialPointsDict,
-            const conformalVoronoiMesh& cvMesh,
             const searchableSurface& surface
         );
 
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeFunction/uniform/uniform.C b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeFunction/uniform/uniform.C
index b8f3ffa6f4612dbebc35e0779d045778c6a797d6..e9a06786b48e28d65f2909c23f93062b6a7d997d 100644
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeFunction/uniform/uniform.C
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeFunction/uniform/uniform.C
@@ -41,11 +41,10 @@ addToRunTimeSelectionTable(cellSizeFunction, uniform, dictionary);
 uniform::uniform
 (
     const dictionary& initialPointsDict,
-    const conformalVoronoiMesh& cvMesh,
     const searchableSurface& surface
 )
 :
-    cellSizeFunction(typeName, initialPointsDict, cvMesh, surface),
+    cellSizeFunction(typeName, initialPointsDict, surface),
     cellSize_(readScalar(coeffsDict().lookup("cellSize")))
 {}
 
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeFunction/uniform/uniform.H b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeFunction/uniform/uniform.H
index 156e09a24fbd58dd39d5de1d2b2eac5e2f2dab18..ea3031aad1aa6f45742a3a9a7e77200282467773 100644
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeFunction/uniform/uniform.H
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeFunction/uniform/uniform.H
@@ -69,7 +69,6 @@ public:
         uniform
         (
             const dictionary& initialPointsDict,
-            const conformalVoronoiMesh& cvMesh,
             const searchableSurface& surface
         );
 
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeFunction/uniformDistance/uniformDistance.C b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeFunction/uniformDistance/uniformDistance.C
index cba741fce2a0d6e09d541486e48a709e3c34d70a..e67eceaa8cd331c8009c5ccd98306de7d11196cf 100644
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeFunction/uniformDistance/uniformDistance.C
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeFunction/uniformDistance/uniformDistance.C
@@ -41,11 +41,10 @@ addToRunTimeSelectionTable(cellSizeFunction, uniformDistance, dictionary);
 uniformDistance::uniformDistance
 (
     const dictionary& initialPointsDict,
-    const conformalVoronoiMesh& cvMesh,
     const searchableSurface& surface
 )
 :
-    cellSizeFunction(typeName, initialPointsDict, cvMesh, surface),
+    cellSizeFunction(typeName, initialPointsDict, surface),
     cellSize_(readScalar(coeffsDict().lookup("cellSize"))),
     distance_(readScalar(coeffsDict().lookup("distance"))),
     distanceSqr_(sqr(distance_))
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeFunction/uniformDistance/uniformDistance.H b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeFunction/uniformDistance/uniformDistance.H
index 78f06a2054f382a865da8b0cbae6a880a30a25e2..bbd87fd548cf4f7713607e27b612731772f30962 100644
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeFunction/uniformDistance/uniformDistance.H
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeFunction/uniformDistance/uniformDistance.H
@@ -75,7 +75,6 @@ public:
         uniformDistance
         (
             const dictionary& initialPointsDict,
-            const conformalVoronoiMesh& cvMesh,
             const searchableSurface& surface
         );
 
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMesh.C b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMesh.C
index 3c7720e92ac94d3119e0ec9eef8a7725c85415c8..dd58fc5141707e9f78bad63d01d6bb5ecf5bd1b6 100644
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMesh.C
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMesh.C
@@ -1925,13 +1925,13 @@ Foam::conformalVoronoiMesh::conformalVoronoiMesh
     ),
     geometryToConformTo_
     (
-        *this,
+        runTime_,
+        rndGen_,
         allGeometry_,
         cvMeshDict.subDict("surfaceConformation")
     ),
     cellSizeControl_
     (
-        *this,
         allGeometry_,
         cvMeshDict.subDict("motionControl")
     ),
@@ -1958,7 +1958,7 @@ Foam::conformalVoronoiMesh::conformalVoronoiMesh
         relaxationModel::New
         (
             cvMeshDict.subDict("motionControl"),
-            *this
+            runTime_
         )
     ),
     faceAreaWeightModel_
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformationSurfaces/conformationSurfaces.C b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformationSurfaces/conformationSurfaces.C
index 9ad5ab6b3e02e25a089c8f2cf681e4f5cf991c6c..5e8a8d729746c8bf0c29a6203f56ca15a1e92521 100644
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformationSurfaces/conformationSurfaces.C
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformationSurfaces/conformationSurfaces.C
@@ -30,12 +30,14 @@ License
 
 Foam::conformationSurfaces::conformationSurfaces
 (
-    const conformalVoronoiMesh& cvMesh,
+    const Time& runTime,
+    Random& rndGen,
     const searchableSurfaces& allGeometry,
     const dictionary& surfaceConformationDict
 )
 :
-    cvMesh_(cvMesh),
+    runTime_(runTime),
+    rndGen_(rndGen),
     allGeometry_(allGeometry),
     features_(),
     locationInMesh_(surfaceConformationDict.lookup("locationInMesh")),
@@ -139,9 +141,9 @@ Foam::conformationSurfaces::conformationSurfaces
                     IOobject
                     (
                         feMeshName,
-                        cvMesh_.time().constant(),
+                        runTime_.time().constant(),
                         "extendedFeatureEdgeMesh",
-                        cvMesh_.time(),
+                        runTime_.time(),
                         IOobject::MUST_READ,
                         IOobject::NO_WRITE
                     )
@@ -211,9 +213,9 @@ Foam::conformationSurfaces::conformationSurfaces
                     IOobject
                     (
                         feMeshName,
-                        cvMesh_.time().constant(),
+                        runTime_.time().constant(),
                         "extendedFeatureEdgeMesh",
-                        cvMesh_.time(),
+                        runTime_.time(),
                         IOobject::MUST_READ,
                         IOobject::NO_WRITE
                     )
@@ -232,7 +234,7 @@ Foam::conformationSurfaces::conformationSurfaces
 
     // Extend the global bounds to stop the bound box sitting on the surfaces
     // to be conformed to
-    globalBounds_ = globalBounds_.extend(cvMesh_.rndGen(), 1e-4);
+    globalBounds_ = globalBounds_.extend(rndGen_, 1e-4);
 
     // Look at all surfaces at determine whether the locationInMesh point is
     // inside or outside each, to establish a signature for the domain to be
@@ -730,7 +732,7 @@ void Foam::conformationSurfaces::findEdgeNearestByType
 
 void Foam::conformationSurfaces::writeFeatureObj(const fileName& prefix) const
 {
-    OFstream ftStr(cvMesh_.time().path()/prefix + "_allFeatures.obj");
+    OFstream ftStr(runTime_.time().path()/prefix + "_allFeatures.obj");
 
     Pout<< nl << "Writing all features to " << ftStr.name() << endl;
 
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformationSurfaces/conformationSurfaces.H b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformationSurfaces/conformationSurfaces.H
index 4db3f15862634fedd23045500f0271b05341c21f..b541bed0032027034eaf4a4d77a73df8af49fdf6 100644
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformationSurfaces/conformationSurfaces.H
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformationSurfaces/conformationSurfaces.H
@@ -56,8 +56,9 @@ class conformationSurfaces
 {
     // Private data
 
-        //- Reference to the conformalVoronoiMesh holding this object
-        const conformalVoronoiMesh& cvMesh_;
+        const Time& runTime_;
+
+        Random& rndGen_;
 
         //- Reference to the searchableSurfaces object holding all geometry data
         const searchableSurfaces& allGeometry_;
@@ -114,7 +115,8 @@ public:
         //  searchableSurfaces
         conformationSurfaces
         (
-            const conformalVoronoiMesh& cvMesh,
+            const Time& runTime,
+            Random& rndGen,
             const searchableSurfaces& allGeometry,
             const dictionary& surfaceConformationDict
         );
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/relaxationModel/adaptiveLinear/adaptiveLinear.C b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/relaxationModel/adaptiveLinear/adaptiveLinear.C
index e5589a92e1a4164f05f741f2413a4319b4a15609..a1967da49da35ff489c7995a2dc0ea002c6085c5 100644
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/relaxationModel/adaptiveLinear/adaptiveLinear.C
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/relaxationModel/adaptiveLinear/adaptiveLinear.C
@@ -41,13 +41,13 @@ addToRunTimeSelectionTable(relaxationModel, adaptiveLinear, dictionary);
 adaptiveLinear::adaptiveLinear
 (
     const dictionary& relaxationDict,
-    const conformalVoronoiMesh& cvMesh
+    const Time& runTime
 )
 :
-    relaxationModel(typeName, relaxationDict, cvMesh),
+    relaxationModel(typeName, relaxationDict, runTime),
     relaxationStart_(readScalar(coeffDict().lookup("relaxationStart"))),
     relaxationEnd_(readScalar(coeffDict().lookup("relaxationEnd"))),
-    lastTimeValue_(cvMesh_.time().timeOutputValue()),
+    lastTimeValue_(runTime_.time().timeOutputValue()),
     relaxation_(relaxationStart_)
 {}
 
@@ -56,24 +56,24 @@ adaptiveLinear::adaptiveLinear
 
 scalar adaptiveLinear::relaxation()
 {
-    if (cvMesh_.time().timeOutputValue() > lastTimeValue_)
+    if (runTime_.time().timeOutputValue() > lastTimeValue_)
     {
-        scalar currentRelxation = relaxation_;
+        scalar currentRelaxation = relaxation_;
 
         relaxation_ -=
             (relaxation_ - relaxationEnd_)
            /(
                 (
-                    cvMesh_.time().endTime().value()
-                  - cvMesh_.time().timeOutputValue()
+                    runTime_.time().endTime().value()
+                  - runTime_.time().timeOutputValue()
                 )
-               /(cvMesh_.time().timeOutputValue() - lastTimeValue_)
+               /(runTime_.time().timeOutputValue() - lastTimeValue_)
               + 1
             );
 
-        lastTimeValue_ = cvMesh_.time().timeOutputValue();
+        lastTimeValue_ = runTime_.time().timeOutputValue();
 
-        return currentRelxation;
+        return currentRelaxation;
     }
 
     return relaxation_;
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/relaxationModel/adaptiveLinear/adaptiveLinear.H b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/relaxationModel/adaptiveLinear/adaptiveLinear.H
index 11a79c39d33447a6b877376e711c5d71b3b02a6d..ecb4c32d4d483e0b3da7fd82117c90a2853ccc65 100644
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/relaxationModel/adaptiveLinear/adaptiveLinear.H
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/relaxationModel/adaptiveLinear/adaptiveLinear.H
@@ -83,7 +83,7 @@ public:
         adaptiveLinear
         (
             const dictionary& relaxationDict,
-            const conformalVoronoiMesh& cvMesh
+            const Time& runTime
         );
 
 
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/relaxationModel/rampHoldFall/rampHoldFall.C b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/relaxationModel/rampHoldFall/rampHoldFall.C
index 17ffeab33f7fcef0bc87c0f3eefb1b4e04642edb..92b42313deda759a91ea9ae69c7a03f02d591e4e 100644
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/relaxationModel/rampHoldFall/rampHoldFall.C
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/relaxationModel/rampHoldFall/rampHoldFall.C
@@ -41,10 +41,10 @@ addToRunTimeSelectionTable(relaxationModel, rampHoldFall, dictionary);
 rampHoldFall::rampHoldFall
 (
     const dictionary& relaxationDict,
-    const conformalVoronoiMesh& cvMesh
+    const Time& runTime
 )
 :
-    relaxationModel(typeName, relaxationDict, cvMesh),
+    relaxationModel(typeName, relaxationDict, runTime),
     rampStartRelaxation_(readScalar(coeffDict().lookup("rampStartRelaxation"))),
     holdRelaxation_(readScalar(coeffDict().lookup("holdRelaxation"))),
     fallEndRelaxation_(readScalar(coeffDict().lookup("fallEndRelaxation"))),
@@ -62,10 +62,10 @@ rampHoldFall::rampHoldFall
 
 scalar rampHoldFall::relaxation()
 {
-    scalar t = cvMesh_.time().timeOutputValue();
+    scalar t = runTime_.time().timeOutputValue();
 
-    scalar tStart = cvMesh_.time().startTime().value();
-    scalar tEnd = cvMesh_.time().endTime().value();
+    scalar tStart = runTime_.time().startTime().value();
+    scalar tEnd = runTime_.time().endTime().value();
     scalar tSpan = tEnd - tStart;
 
     if (tSpan < VSMALL)
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/relaxationModel/rampHoldFall/rampHoldFall.H b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/relaxationModel/rampHoldFall/rampHoldFall.H
index 6c65e15880f7c38bbc07c4ecff055f5629217b04..db814749f122a5cd7541383a167854cdc23a2107 100644
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/relaxationModel/rampHoldFall/rampHoldFall.H
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/relaxationModel/rampHoldFall/rampHoldFall.H
@@ -88,7 +88,7 @@ public:
         rampHoldFall
         (
             const dictionary& relaxationDict,
-            const conformalVoronoiMesh& cvMesh
+            const Time& runTime
         );
 
 
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/relaxationModel/relaxationModel/relaxationModel.C b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/relaxationModel/relaxationModel/relaxationModel.C
index dd7aee89809e7919c9ba76476851525edb0353ee..91daf73f355cb8d38fc700a92485793c8bb93b3f 100644
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/relaxationModel/relaxationModel/relaxationModel.C
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/relaxationModel/relaxationModel/relaxationModel.C
@@ -43,11 +43,11 @@ relaxationModel::relaxationModel
 (
     const word& type,
     const dictionary& relaxationDict,
-    const conformalVoronoiMesh& cvMesh
+    const Time& runTime
 )
 :
     dictionary(relaxationDict),
-    cvMesh_(cvMesh),
+    runTime_(runTime),
     coeffDict_(subDict(type + "Coeffs"))
 {}
 
@@ -57,7 +57,7 @@ relaxationModel::relaxationModel
 autoPtr<relaxationModel> relaxationModel::New
 (
     const dictionary& relaxationDict,
-    const conformalVoronoiMesh& cvMesh
+    const Time& runTime
 )
 {
     word relaxationModelTypeName
@@ -85,7 +85,7 @@ autoPtr<relaxationModel> relaxationModel::New
             << exit(FatalError);
     }
 
-    return autoPtr<relaxationModel>(cstrIter()(relaxationDict, cvMesh));
+    return autoPtr<relaxationModel>(cstrIter()(relaxationDict, runTime));
 }
 
 
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/relaxationModel/relaxationModel/relaxationModel.H b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/relaxationModel/relaxationModel/relaxationModel.H
index d60390ae9a62fb2dd11fb608adad80524d64ffb1..5517098f0596d7264e950e8f3a97b58ec1a860fd 100644
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/relaxationModel/relaxationModel/relaxationModel.H
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/relaxationModel/relaxationModel/relaxationModel.H
@@ -37,7 +37,7 @@ SourceFiles
 #define relaxationModel_H
 
 #include "point.H"
-#include "conformalVoronoiMesh.H"
+#include "Time.H"
 #include "dictionary.H"
 #include "autoPtr.H"
 #include "runTimeSelectionTables.H"
@@ -61,7 +61,7 @@ protected:
     // Protected data
 
         //- Reference to the conformalVoronoiMesh holding this cvControls object
-        const conformalVoronoiMesh& cvMesh_;
+        const Time& runTime_;
 
         //- Method coeffs dictionary
         dictionary coeffDict_;
@@ -92,9 +92,9 @@ public:
             dictionary,
             (
                 const dictionary& relaxationDict,
-                const conformalVoronoiMesh& cvMesh
+                const Time& runTime
             ),
-            (relaxationDict, cvMesh)
+            (relaxationDict, runTime)
         );
 
 
@@ -105,7 +105,7 @@ public:
         (
             const word& type,
             const dictionary& relaxationDict,
-            const conformalVoronoiMesh& cvMesh
+            const Time& runTime
         );
 
 
@@ -115,7 +115,7 @@ public:
         static autoPtr<relaxationModel> New
         (
             const dictionary& relaxationDict,
-            const conformalVoronoiMesh& cvMesh
+            const Time& runTime
         );
 
 
diff --git a/applications/utilities/mesh/generation/extrude/Allwmake b/applications/utilities/mesh/generation/extrude/Allwmake
index 091ec04743818a08fa9bb59f76c73b547f2174be..5f09893321f37f8063e6e976ac8f809f841a48bb 100755
--- a/applications/utilities/mesh/generation/extrude/Allwmake
+++ b/applications/utilities/mesh/generation/extrude/Allwmake
@@ -4,6 +4,8 @@ set -x
 
 wmake libso extrudeModel
 wmake extrudeMesh
+
+wmake libso extrudeToRegionMesh/createShellMesh
 wmake extrudeToRegionMesh
 
 
diff --git a/applications/utilities/mesh/generation/extrude/extrudeToRegionMesh/Make/files b/applications/utilities/mesh/generation/extrude/extrudeToRegionMesh/Make/files
index 28ac7de544f74c5f83b46a863cf0647a8179800a..22606204b5d1c68e7ed507b72c0e2b0c952529d6 100644
--- a/applications/utilities/mesh/generation/extrude/extrudeToRegionMesh/Make/files
+++ b/applications/utilities/mesh/generation/extrude/extrudeToRegionMesh/Make/files
@@ -1,4 +1,3 @@
-createShellMesh.C
 extrudeToRegionMesh.C
 
 EXE = $(FOAM_APPBIN)/extrudeToRegionMesh
diff --git a/applications/utilities/mesh/generation/extrude/extrudeToRegionMesh/Make/options b/applications/utilities/mesh/generation/extrude/extrudeToRegionMesh/Make/options
index 201089b74fc76ccd7b4e8fd02aeefac0ef788857..5732f9761dbd1621922793350690be076fe144b3 100644
--- a/applications/utilities/mesh/generation/extrude/extrudeToRegionMesh/Make/options
+++ b/applications/utilities/mesh/generation/extrude/extrudeToRegionMesh/Make/options
@@ -1,11 +1,13 @@
 EXE_INC = \
     -I../extrudeModel/lnInclude \
+    -IcreateShellMesh/lnInclude \
     -I$(LIB_SRC)/finiteVolume/lnInclude \
     -I$(LIB_SRC)/meshTools/lnInclude \
     -I$(LIB_SRC)/dynamicMesh/lnInclude
 
 EXE_LIBS = \
     -lextrudeModel \
+    -lcreateShellMesh \
     -lfiniteVolume \
     -lmeshTools \
     -ldynamicMesh
diff --git a/applications/utilities/mesh/generation/extrude/extrudeToRegionMesh/createShellMesh/Make/files b/applications/utilities/mesh/generation/extrude/extrudeToRegionMesh/createShellMesh/Make/files
new file mode 100644
index 0000000000000000000000000000000000000000..4aa716f0220d590095857d4d07940c486a3b4ea3
--- /dev/null
+++ b/applications/utilities/mesh/generation/extrude/extrudeToRegionMesh/createShellMesh/Make/files
@@ -0,0 +1,3 @@
+createShellMesh.C
+
+LIB = $(FOAM_LIBBIN)/libcreateShellMesh
diff --git a/applications/utilities/mesh/generation/extrude/extrudeToRegionMesh/createShellMesh/Make/options b/applications/utilities/mesh/generation/extrude/extrudeToRegionMesh/createShellMesh/Make/options
new file mode 100644
index 0000000000000000000000000000000000000000..295f0b0bc956185f982b81ddf6eaa4e2869850e1
--- /dev/null
+++ b/applications/utilities/mesh/generation/extrude/extrudeToRegionMesh/createShellMesh/Make/options
@@ -0,0 +1,9 @@
+EXE_INC = \
+    -I$(LIB_SRC)/finiteVolume/lnInclude \
+    -I$(LIB_SRC)/meshTools/lnInclude \
+    -I$(LIB_SRC)/dynamicMesh/lnInclude -DFULLDEBUG -g -O0
+
+LIB_LIBS = \
+    -lfiniteVolume \
+    -lmeshTools \
+    -ldynamicMesh
diff --git a/applications/utilities/mesh/generation/extrude/extrudeToRegionMesh/createShellMesh.C b/applications/utilities/mesh/generation/extrude/extrudeToRegionMesh/createShellMesh/createShellMesh.C
similarity index 99%
rename from applications/utilities/mesh/generation/extrude/extrudeToRegionMesh/createShellMesh.C
rename to applications/utilities/mesh/generation/extrude/extrudeToRegionMesh/createShellMesh/createShellMesh.C
index 6bfe6ca62e7c64c6960609011f282335aa4d653c..13aefeac1060812e0264e8b87e2c7606bf254e96 100644
--- a/applications/utilities/mesh/generation/extrude/extrudeToRegionMesh/createShellMesh.C
+++ b/applications/utilities/mesh/generation/extrude/extrudeToRegionMesh/createShellMesh/createShellMesh.C
@@ -509,7 +509,6 @@ void Foam::createShellMesh::setRefinement
         }
     }
 
-
     // Introduce original points
     // ~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -526,13 +525,12 @@ void Foam::createShellMesh::setRefinement
         );
         pointToPointMap.append(pointI);
 
-        //Pout<< "Added bottom point " << addedPointI
-        //    << " at " << patch_.localPoints()[pointI]
-        //    << "  from point " << pointI
-        //    << endl;
+//        Pout<< "Added bottom point " << pointToPointMap[pointI]
+//            << " at " << patch_.localPoints()[pointI]
+//            << "  from point " << pointI
+//            << endl;
     }
 
-
     // Introduce new points (one for every region)
     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -543,6 +541,7 @@ void Foam::createShellMesh::setRefinement
 
         point pt = patch_.localPoints()[pointI];
         point disp = firstLayerDisp[regionI];
+
         for (label layerI = 0; layerI < nLayers; layerI++)
         {
             pt += disp;
@@ -676,7 +675,7 @@ void Foam::createShellMesh::setRefinement
             {
                 FatalErrorIn("createShellMesh::setRefinement(..)")
                     << "external/feature edge:" << edgeI
-                    << " has " << eFaces.size() << " connected extruded faces "
+                    << " has " << eFaces.size() << " connected extruded faces"
                     << " but only " << ePatches.size()
                     << " boundary faces defined." << exit(FatalError);
             }
diff --git a/applications/utilities/mesh/generation/extrude/extrudeToRegionMesh/createShellMesh.H b/applications/utilities/mesh/generation/extrude/extrudeToRegionMesh/createShellMesh/createShellMesh.H
similarity index 100%
rename from applications/utilities/mesh/generation/extrude/extrudeToRegionMesh/createShellMesh.H
rename to applications/utilities/mesh/generation/extrude/extrudeToRegionMesh/createShellMesh/createShellMesh.H
diff --git a/applications/utilities/mesh/generation/extrude2DMesh/Allwclean b/applications/utilities/mesh/generation/extrude2DMesh/Allwclean
new file mode 100755
index 0000000000000000000000000000000000000000..44537ed68bad409595e8570f7fa983e0753c6928
--- /dev/null
+++ b/applications/utilities/mesh/generation/extrude2DMesh/Allwclean
@@ -0,0 +1,8 @@
+#!/bin/sh
+cd ${0%/*} || exit 1    # run from this directory
+set -x
+
+wclean libso extrude2DMesh
+wclean
+
+# ----------------------------------------------------------------- end-of-file
diff --git a/applications/utilities/mesh/generation/extrude2DMesh/Allwmake b/applications/utilities/mesh/generation/extrude2DMesh/Allwmake
new file mode 100755
index 0000000000000000000000000000000000000000..6f54612ffe710adcc912c9baed4eb8a97cae1f91
--- /dev/null
+++ b/applications/utilities/mesh/generation/extrude2DMesh/Allwmake
@@ -0,0 +1,8 @@
+#!/bin/sh
+cd ${0%/*} || exit 1    # run from this directory
+set -x
+
+wmake libso extrude2DMesh
+wmake
+
+# ----------------------------------------------------------------- end-of-file
diff --git a/applications/utilities/mesh/generation/extrude2DMesh/Make/files b/applications/utilities/mesh/generation/extrude2DMesh/Make/files
index 8cc4bd86cdfe7a24a9eefb19037eeabc80556be6..a30e03b5b777b11c704ab5af3823045c1c112a72 100644
--- a/applications/utilities/mesh/generation/extrude2DMesh/Make/files
+++ b/applications/utilities/mesh/generation/extrude2DMesh/Make/files
@@ -1,4 +1,3 @@
-extrude2DMesh.C
 extrude2DMeshApp.C
 
 EXE = $(FOAM_APPBIN)/extrude2DMesh
diff --git a/applications/utilities/mesh/generation/extrude2DMesh/Make/options b/applications/utilities/mesh/generation/extrude2DMesh/Make/options
index ef62d4a7c3c65d44da1fa188e10f07e081fd35c1..8adfe67b36e15e255eb2af9850933535e3f8b3b4 100644
--- a/applications/utilities/mesh/generation/extrude2DMesh/Make/options
+++ b/applications/utilities/mesh/generation/extrude2DMesh/Make/options
@@ -1,10 +1,12 @@
 EXE_INC = \
-    /* -DFULLDEBUG -g -O0 */ \
-    -I$(LIB_SRC)/meshTools/lnInclude \
+    -I$(LIB_SRC)/finiteVolume/lnInclude \
+    -I$(LIB_SRC)/surfMesh/lnInclude \
     -I$(LIB_SRC)/dynamicMesh/lnInclude \
-    -I$(LIB_SRC)/finiteVolume/lnInclude
+    -Iextrude2DMesh/lnInclude \
+    -I../extrude/extrudeModel/lnInclude
 
 EXE_LIBS = \
-    -lmeshTools \
+    -lsurfMesh \
     -ldynamicMesh \
-    -lfiniteVolume
+    -lextrude2DMesh \
+    -lextrudeModel
diff --git a/applications/utilities/mesh/generation/extrude2DMesh/extrude2DMesh.C b/applications/utilities/mesh/generation/extrude2DMesh/extrude2DMesh.C
deleted file mode 100644
index 69dc8d66ba4d22a2e9afad83cad279405b5602b7..0000000000000000000000000000000000000000
--- a/applications/utilities/mesh/generation/extrude2DMesh/extrude2DMesh.C
+++ /dev/null
@@ -1,263 +0,0 @@
-/*---------------------------------------------------------------------------*\
-  =========                 |
-  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
-   \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
-     \\/     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 "extrude2DMesh.H"
-#include "polyMesh.H"
-#include "polyTopoChange.H"
-
-// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
-
-namespace Foam
-{
-
-defineTypeNameAndDebug(extrude2DMesh, 0);
-
-}
-
-// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
-
-
-// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
-
-// Construct from mesh
-Foam::extrude2DMesh::extrude2DMesh(const polyMesh& mesh)
-:
-    mesh_(mesh)
-{}
-
-
-// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
-
-void Foam::extrude2DMesh::setRefinement
-(
-    const direction extrudeDir,
-    const scalar thickness,
-    const label frontPatchI,
-    polyTopoChange& meshMod
-) const
-{
-    for (label cellI = 0; cellI < mesh_.nCells(); cellI++)
-    {
-        meshMod.addCell
-        (
-            -1,     //masterPointID,
-            -1,     //masterEdgeID,
-            -1,     //masterFaceID,
-            cellI,  //masterCellID,
-            mesh_.cellZones().whichZone(cellI)  //zoneID
-        );
-    }
-
-
-    // Generate points
-    // ~~~~~~~~~~~~~~~
-
-    forAll(mesh_.points(), pointI)
-    {
-        meshMod.addPoint
-        (
-            mesh_.points()[pointI],
-            pointI,
-            -1,             // zoneID
-            true            // inCell
-        );
-    }
-
-    //Info<< "Adding offsetted points." << nl << endl;
-    forAll(mesh_.points(), pointI)
-    {
-        point newPoint(mesh_.points()[pointI]);
-        newPoint[extrudeDir] += thickness;
-
-        meshMod.addPoint
-        (
-            newPoint,
-            pointI,
-            -1,             // zoneID
-            true            // inCell
-        );
-    }
-
-
-    // Generate faces
-    // ~~~~~~~~~~~~~~
-
-    const faceList& faces = mesh_.faces();
-    const polyBoundaryMesh& patches = mesh_.boundaryMesh();
-
-    for (label faceI = 0; faceI < mesh_.nInternalFaces(); faceI++)
-    {
-        label zoneID = mesh_.faceZones().whichZone(faceI);
-        bool zoneFlip = false;
-        if (zoneID != -1)
-        {
-            const faceZone& fZone = mesh_.faceZones()[zoneID];
-            zoneFlip = fZone.flipMap()[fZone.whichFace(faceI)];
-        }
-
-        face newFace(4);
-        const face& f = faces[faceI];
-        newFace[0] = f[0];
-        newFace[1] = f[1];
-        newFace[2] = f[1]+mesh_.nPoints();
-        newFace[3] = f[0]+mesh_.nPoints();
-
-        meshMod.addFace
-        (
-            newFace,
-            mesh_.faceOwner()[faceI],       // own
-            mesh_.faceNeighbour()[faceI],   // nei
-            -1,                             // masterPointID
-            -1,                             // masterEdgeID
-            faceI,                          // masterFaceID
-            false,                          // flipFaceFlux
-            -1,                             // patchID
-            zoneID,                         // zoneID
-            zoneFlip                        // zoneFlip
-        );
-    }
-
-    forAll(patches, patchI)
-    {
-        label startFaceI = patches[patchI].start();
-        label endFaceI = startFaceI + patches[patchI].size();
-
-        for (label faceI = startFaceI; faceI < endFaceI; faceI++)
-        {
-            label zoneID = mesh_.faceZones().whichZone(faceI);
-            bool zoneFlip = false;
-            if (zoneID != -1)
-            {
-                const faceZone& fZone = mesh_.faceZones()[zoneID];
-                zoneFlip = fZone.flipMap()[fZone.whichFace(faceI)];
-            }
-
-            face newFace(4);
-            const face& f = faces[faceI];
-            newFace[0] = f[0];
-            newFace[1] = f[1];
-            newFace[2] = f[1]+mesh_.nPoints();
-            newFace[3] = f[0]+mesh_.nPoints();
-
-            meshMod.addFace
-            (
-                newFace,
-                mesh_.faceOwner()[faceI],       // own
-                -1,                             // nei
-                -1,                             // masterPointID
-                -1,                             // masterEdgeID
-                faceI,                          // masterFaceID
-                false,                          // flipFaceFlux
-                patchI,                         // patchID
-                zoneID,                         // zoneID
-                zoneFlip                        // zoneFlip
-            );
-        }
-    }
-
-
-    // Generate front and back faces
-    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-    forAll(mesh_.cells(), cellI)
-    {
-        const cell& cFaces = mesh_.cells()[cellI];
-
-        // Make a loop out of faces.
-        const face& f = faces[cFaces[0]];
-
-        face frontFace(cFaces.size());
-        frontFace[0] = f[0];
-
-        label nextPointI = f[1];
-        label nextFaceI = cFaces[0];
-
-        for (label i = 1; i < frontFace.size(); i++)
-        {
-            frontFace[i] = nextPointI;
-
-            // Find face containing pointI
-            forAll(cFaces, cFaceI)
-            {
-                label faceI = cFaces[cFaceI];
-                if (faceI != nextFaceI)
-                {
-                    const face& f = faces[faceI];
-
-                    if (f[0] == nextPointI)
-                    {
-                        nextPointI = f[1];
-                        nextFaceI = faceI;
-                        break;
-                    }
-                    else if (f[1] == nextPointI)
-                    {
-                        nextPointI = f[0];
-                        nextFaceI = faceI;
-                        break;
-                    }
-                }
-            }
-        }
-
-
-        // Add back face.
-        meshMod.addFace
-        (
-            frontFace.reverseFace(),
-            cellI,                          // own
-            -1,                             // nei
-            -1,                             // masterPointID
-            -1,                             // masterEdgeID
-            cFaces[0],                      // masterFaceID
-            false,                          // flipFaceFlux
-            frontPatchI,                    // patchID
-            -1,                             // zoneID
-            false                           // zoneFlip
-        );
-
-        // Offset to create front face.
-        forAll(frontFace, fp)
-        {
-            frontFace[fp] += mesh_.nPoints();
-        }
-        meshMod.addFace
-        (
-            frontFace,
-            cellI,                          // own
-            -1,                             // nei
-            -1,                             // masterPointID
-            -1,                             // masterEdgeID
-            cFaces[0],                      // masterFaceID
-            false,                          // flipFaceFlux
-            frontPatchI,                    // patchID
-            -1,                             // zoneID
-            false                           // zoneFlip
-        );
-    }
-}
-
-
-// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/extrude2DMesh/extrude2DMesh/Make/files b/applications/utilities/mesh/generation/extrude2DMesh/extrude2DMesh/Make/files
new file mode 100644
index 0000000000000000000000000000000000000000..95083a24fbdedcb18bc4db8aa7ed1739a0e4d3e6
--- /dev/null
+++ b/applications/utilities/mesh/generation/extrude2DMesh/extrude2DMesh/Make/files
@@ -0,0 +1,5 @@
+extrude2DMesh/extrude2DMesh.C
+
+patchToPoly2DMesh/patchToPoly2DMesh.C
+
+LIB = $(FOAM_LIBBIN)/libextrude2DMesh
diff --git a/applications/utilities/mesh/generation/extrude2DMesh/extrude2DMesh/Make/options b/applications/utilities/mesh/generation/extrude2DMesh/extrude2DMesh/Make/options
new file mode 100644
index 0000000000000000000000000000000000000000..8ace7c50daad576ef0b060bf048908f4cf8d073a
--- /dev/null
+++ b/applications/utilities/mesh/generation/extrude2DMesh/extrude2DMesh/Make/options
@@ -0,0 +1,13 @@
+EXE_INC = \
+    /* -DFULLDEBUG -g -O0 */ \
+    -I$(LIB_SRC)/meshTools/lnInclude \
+    -I$(LIB_SRC)/dynamicMesh/lnInclude \
+    -I$(LIB_SRC)/finiteVolume/lnInclude \
+    -I$(LIB_SRC)/surfMesh/lnInclude \
+    -I$(FOAM_APP)/utilities/mesh/generation/extrude/extrudeModel/lnInclude
+
+LIB_LIBS = \
+    -lmeshTools \
+    -ldynamicMesh \
+    -lsurfMesh \
+    -lfiniteVolume
diff --git a/applications/utilities/mesh/generation/extrude2DMesh/extrude2DMesh/extrude2DMesh/extrude2DMesh.C b/applications/utilities/mesh/generation/extrude2DMesh/extrude2DMesh/extrude2DMesh/extrude2DMesh.C
new file mode 100644
index 0000000000000000000000000000000000000000..ff1a4aeacca079fb35108e9f386b3ff0381e8efd
--- /dev/null
+++ b/applications/utilities/mesh/generation/extrude2DMesh/extrude2DMesh/extrude2DMesh/extrude2DMesh.C
@@ -0,0 +1,588 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
+     \\/     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 "extrude2DMesh.H"
+#include "polyMesh.H"
+#include "polyTopoChange.H"
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+defineTypeNameAndDebug(extrude2DMesh, 0);
+
+}
+
+// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
+
+void Foam::extrude2DMesh::check2D() const
+{
+    const faceList& faces = mesh_.faces();
+    forAll(faces, faceI)
+    {
+        if (faces[faceI].size() != 2)
+        {
+            FatalErrorIn("extrude2DMesh.C")
+                << "Face " << faceI << " size " << faces[faceI].size()
+                << " is not of size 2 so mesh is not proper two-dimensional."
+                << exit(FatalError);
+        }
+    }
+}
+
+
+//void Foam::extrude2DMesh::findExtrudeDirection()
+//{
+//    scalar minRange = GREAT;
+
+//    for (direction dir = 0; dir < 3; dir++)
+//    {
+//        scalarField cmpts(mesh_.points().component(dir));
+
+//        scalar range = max(cmpts)-min(cmpts);
+
+//        Info<< "Direction:" << dir << " range:" << range << endl;
+
+//        if (range < minRange)
+//        {
+//            minRange = range;
+//            extrudeDir_ = dir;
+//        }
+//    }
+
+//    Info<< "Extruding in direction " << extrudeDir_
+//        << " with thickness " << thickness_ << nl
+//        << endl;
+//}
+
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::extrude2DMesh::extrude2DMesh
+(
+    polyMesh& mesh,
+    const dictionary& dict,
+    const extrudeModel& model
+)
+:
+    mesh_(mesh),
+    dict_(dict),
+    //patchDict_(dict.subDict("patchInfo")),
+    model_(model),
+    modelType_(dict.lookup("extrudeModel")),
+    patchType_(dict.lookup("patchType")),
+    frontPatchI_(-1),
+    backPatchI_(-1)
+{
+    check2D();
+}
+
+
+// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
+
+Foam::extrude2DMesh::~extrude2DMesh()
+{}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+void Foam::extrude2DMesh::addFrontBackPatches()
+{
+    const polyBoundaryMesh& patches = mesh_.boundaryMesh();
+
+    frontPatchI_ = patches.findPatchID("front");
+    backPatchI_ = patches.findPatchID("back");
+
+    // Add patch.
+    List<polyPatch*> newPatches(patches.size() + 2);
+
+    forAll(patches, patchI)
+    {
+        const polyPatch& pp = patches[patchI];
+
+        newPatches[patchI] =
+            pp.clone
+            (
+                patches,
+                newPatches.size(),
+                pp.size(),
+                pp.start()
+            ).ptr();
+    }
+
+    if (frontPatchI_ == -1)
+    {
+        frontPatchI_ = patches.size();
+
+        newPatches[frontPatchI_] =
+            polyPatch::New
+            (
+                patchType_,
+                "front",
+                0,
+                mesh_.nFaces(),
+                frontPatchI_,
+                patches
+            ).ptr();
+
+//        newPatches[frontPatchI_] = polyPatch::New
+//        (
+//            "front",
+//            patchDict_,
+//            frontPatchI_,
+//            patches
+//        ).ptr();
+
+        Info<< "Adding patch " << newPatches[frontPatchI_]->name()
+            << " at index " << frontPatchI_
+            << " for front faces." << nl << endl;
+    }
+
+    if (backPatchI_ == -1)
+    {
+        backPatchI_ = patches.size() + 1;
+
+        newPatches[backPatchI_] =
+            polyPatch::New
+            (
+                patchType_,
+                "back",
+                0,
+                mesh_.nFaces(),
+                backPatchI_,
+                patches
+            ).ptr();
+
+//        newPatches[frontPatchI_] = polyPatch::New
+//        (
+//            "back",
+//            patchDict_,
+//            backPatchI_,
+//            patches
+//        ).ptr();
+
+        Info<< "Adding patch " << newPatches[backPatchI_]->name()
+            << " at index " << backPatchI_
+            << " for back faces." << nl << endl;
+    }
+
+    mesh_.removeBoundary();
+    mesh_.addPatches(newPatches);
+}
+
+
+void Foam::extrude2DMesh::setRefinement
+(
+    polyTopoChange& meshMod
+)
+{
+    const label nLayers = model_.nLayers();
+    const pointField& points = mesh_.points();
+    label nFaces = 0;
+
+    for (label layer = 0; layer < nLayers; ++layer)
+    {
+        label offset = layer * mesh_.nCells();
+
+        forAll(mesh_.cells(), cellI)
+        {
+            meshMod.addCell
+            (
+                -1,     //masterPointID,
+                -1,     //masterEdgeID,
+                -1,     //masterFaceID,
+                cellI + offset,  //masterCellID,
+                mesh_.cellZones().whichZone(cellI)  //zoneID
+            );
+        }
+    }
+
+
+    // Generate points
+    // ~~~~~~~~~~~~~~~
+
+    for (label layer = 0; layer <= nLayers; ++layer)
+    {
+        label offset = layer * points.size();
+
+        forAll(points, pointI)
+        {
+            // Don't need the surface normal for either linearDirection or
+            // wedge. Will need to add to be able to use others.
+            point newPoint = model_
+            (
+                points[pointI],
+                vector(),
+                layer
+            );
+
+            meshMod.addPoint
+            (
+                newPoint,
+                pointI + offset,
+                -1,             // zoneID
+                true            // inCell
+            );
+        }
+
+        Pout<< "Added " << points.size() << " points to layer "
+            << layer << endl;
+    }
+
+
+    // Generate faces
+    // ~~~~~~~~~~~~~~
+
+    const faceList& faces = mesh_.faces();
+    const polyBoundaryMesh& patches = mesh_.boundaryMesh();
+
+    for (label layer = 0; layer < nLayers; ++layer)
+    {
+        label currentLayerOffset = layer * mesh_.nPoints();
+        label nextLayerOffset = currentLayerOffset + mesh_.nPoints();
+
+        for (label faceI = 0; faceI < mesh_.nInternalFaces(); faceI++)
+        {
+            label zoneID = mesh_.faceZones().whichZone(faceI);
+            bool zoneFlip = false;
+            if (zoneID != -1)
+            {
+                const faceZone& fZone = mesh_.faceZones()[zoneID];
+                zoneFlip = fZone.flipMap()[fZone.whichFace(faceI)];
+            }
+
+            face newFace(4);
+            const face& f = faces[faceI];
+            newFace[0] = f[0] + currentLayerOffset;
+            newFace[1] = f[1] + currentLayerOffset;
+            newFace[2] = f[1] + nextLayerOffset;
+            newFace[3] = f[0] + nextLayerOffset;
+
+//{
+//    vector n = newFace.normal(pointField(meshMod.points()));
+//    label own = mesh_.faceOwner()[faceI];
+//    const labelList& ownPoints = mesh_.cellPoints()[own];
+//    point ownCc = sum(pointField(mesh_.points(), ownPoints))/ownPoints.size();
+//    label nei = mesh_.faceNeighbour()[faceI];
+//    const labelList& neiPoints = mesh_.cellPoints()[nei];
+//    point neiCc = sum(pointField(mesh_.points(), neiPoints))/neiPoints.size();
+//    vector d = neiCc - ownCc;
+
+//    Pout<< "face:" << faceI << " at:" << f.centre(mesh_.points()) << endl
+//        << "    own:" << own << " at:" << ownCc << endl
+//        << "    nei:" << nei << " at:" << neiCc << endl
+//        << "    sign:" << (n & d) << endl
+//        << endl;
+//}
+
+            label offset = layer * mesh_.nCells();
+
+            meshMod.addFace
+            (
+                newFace,
+                mesh_.faceOwner()[faceI] + offset,       // own
+                mesh_.faceNeighbour()[faceI] + offset,   // nei
+                -1,                             // masterPointID
+                -1,                             // masterEdgeID
+                nFaces++,    // masterFaceID
+                false,                          // flipFaceFlux
+                -1,                             // patchID
+                zoneID,                         // zoneID
+                zoneFlip                        // zoneFlip
+            );
+
+            if (debug)
+            {
+                Info<< newFace << " "
+                    << mesh_.faceOwner()[faceI] + offset << " "
+                    << mesh_.faceNeighbour()[faceI] + offset << " "
+                    << nFaces - 1
+                    << endl;
+            }
+        }
+    }
+
+    forAll(patches, patchI)
+    {
+        for (label layer=0; layer < nLayers; layer++)
+        {
+            label currentLayerOffset = layer*mesh_.nPoints();
+            label nextLayerOffset = currentLayerOffset + mesh_.nPoints();
+
+            label startFaceI = patches[patchI].start();
+            label endFaceI = startFaceI + patches[patchI].size();
+
+            for (label faceI = startFaceI; faceI < endFaceI; faceI++)
+            {
+                label zoneID = mesh_.faceZones().whichZone(faceI);
+                bool zoneFlip = false;
+                if (zoneID != -1)
+                {
+                    const faceZone& fZone = mesh_.faceZones()[zoneID];
+                    zoneFlip = fZone.flipMap()[fZone.whichFace(faceI)];
+                }
+
+                face newFace(4);
+                const face& f = faces[faceI];
+                newFace[0] = f[0] + currentLayerOffset;
+                newFace[1] = f[1] + currentLayerOffset;
+                newFace[2] = f[1] + nextLayerOffset;
+                newFace[3] = f[0] + nextLayerOffset;
+
+                label offset = layer * mesh_.nCells();
+
+                meshMod.addFace
+                (
+                    newFace,
+                    mesh_.faceOwner()[faceI] + offset,       // own
+                    -1,                                      // nei
+                    -1,                                      // masterPointID
+                    -1,                                      // masterEdgeID
+                    nFaces++,                                // masterFaceID
+                    false,                                   // flipFaceFlux
+                    patchI,                                  // patchID
+                    zoneID,                                  // zoneID
+                    zoneFlip                                 // zoneFlip
+                );
+
+                if (debug)
+                {
+                    Info<< newFace << " "
+                        << mesh_.faceOwner()[faceI] + offset << " "
+                        << nFaces - 1
+                        << endl;
+                }
+            }
+        }
+    }
+
+    // Add extra internal faces that need special treatment for owners and
+    // neighbours.
+    forAll(mesh_.cells(), cellI)
+    {
+        const cell& cFaces = mesh_.cells()[cellI];
+
+        face frontFace(cFaces.size());
+
+        // Make a loop out of faces.
+        label nextFaceI = cFaces[0];
+
+        const face& f = faces[nextFaceI];
+
+        label nextPointI;
+        if (mesh_.faceOwner()[nextFaceI] == cellI)
+        {
+            frontFace[0] = f[0];
+            nextPointI = f[1];
+        }
+        else
+        {
+            frontFace[0] = f[1];
+            nextPointI = f[0];
+        }
+
+
+        for (label i = 1; i < frontFace.size(); i++)
+        {
+            frontFace[i] = nextPointI;
+
+            // Find face containing pointI
+            forAll(cFaces, cFaceI)
+            {
+                label faceI = cFaces[cFaceI];
+                if (faceI != nextFaceI)
+                {
+                    const face& f = faces[faceI];
+
+                    if (f[0] == nextPointI)
+                    {
+                        nextPointI = f[1];
+                        nextFaceI = faceI;
+                        break;
+                    }
+                    else if (f[1] == nextPointI)
+                    {
+                        nextPointI = f[0];
+                        nextFaceI = faceI;
+                        break;
+                    }
+                }
+            }
+        }
+
+        for (label layer = 0; layer < nLayers - 1; ++layer)
+        {
+            // Offset to create front face.
+            forAll(frontFace, fp)
+            {
+                frontFace[fp] += mesh_.nPoints();
+            }
+
+            label offset = layer * mesh_.nCells();
+
+            label nei = -1;
+            if (layer != nLayers - 1)
+            {
+                nei = cellI + offset + mesh_.nCells();
+            }
+
+            meshMod.addFace
+            (
+                frontFace,
+                cellI + offset,                 // own
+                nei,                            // nei
+                -1,                             // masterPointID
+                -1,                             // masterEdgeID
+                nFaces++,                       // masterFaceID
+                false,                          // flipFaceFlux
+                -1,                             // patchID
+                -1,                             // zoneID
+                false                           // zoneFlip
+            );
+
+            if (debug)
+            {
+                Info<< frontFace << " "
+                    << cellI + offset << " "
+                    << nei << " "
+                    << nFaces - 1
+                    << endl;
+            }
+        }
+    }
+
+    // Generate front and back faces
+    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    forAll(mesh_.cells(), cellI)
+    {
+        const cell& cFaces = mesh_.cells()[cellI];
+
+        face frontFace(cFaces.size());
+
+        // Make a loop out of faces.
+        label nextFaceI = cFaces[0];
+
+        const face& f = faces[nextFaceI];
+
+        label nextPointI;
+        if (mesh_.faceOwner()[nextFaceI] == cellI)
+        {
+            frontFace[0] = f[0];
+            nextPointI = f[1];
+        }
+        else
+        {
+            frontFace[0] = f[1];
+            nextPointI = f[0];
+        }
+
+
+        for (label i = 1; i < frontFace.size(); i++)
+        {
+            frontFace[i] = nextPointI;
+
+            // Find face containing pointI
+            forAll(cFaces, cFaceI)
+            {
+                label faceI = cFaces[cFaceI];
+                if (faceI != nextFaceI)
+                {
+                    const face& f = faces[faceI];
+
+                    if (f[0] == nextPointI)
+                    {
+                        nextPointI = f[1];
+                        nextFaceI = faceI;
+                        break;
+                    }
+                    else if (f[1] == nextPointI)
+                    {
+                        nextPointI = f[0];
+                        nextFaceI = faceI;
+                        break;
+                    }
+                }
+            }
+        }
+
+        // Add back face.
+        meshMod.addFace
+        (
+            frontFace.reverseFace(),
+            cellI,                          // own
+            -1,                             // nei
+            -1,                             // masterPointID
+            -1,                             // masterEdgeID
+            nFaces++,                      // masterFaceID
+            false,                          // flipFaceFlux
+            backPatchI_,                    // patchID
+            -1,                             // zoneID
+            false                           // zoneFlip
+        );
+
+        if (debug)
+        {
+            Info<< nl<<frontFace.reverseFace() << " "
+                << cellI << " "
+                << nFaces - 1
+                << endl;
+        }
+
+        // Offset to create front face.
+        forAll(frontFace, fp)
+        {
+            frontFace[fp] += mesh_.nPoints()* (nLayers);
+        }
+
+        label offset = (nLayers - 1) * mesh_.nCells();
+
+        meshMod.addFace
+        (
+            frontFace,
+            cellI + offset,                 // own
+            -1,                             // nei
+            -1,                             // masterPointID
+            -1,                             // masterEdgeID
+            nFaces++, // masterFaceID
+            false,                          // flipFaceFlux
+            frontPatchI_,                   // patchID
+            -1,                             // zoneID
+            false                           // zoneFlip
+        );
+
+        if (debug)
+        {
+            Info<< frontFace << " "
+                << cellI + offset << " "
+                << nFaces - 1
+                << endl;
+        }
+    }
+}
+
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/extrude2DMesh/extrude2DMesh.H b/applications/utilities/mesh/generation/extrude2DMesh/extrude2DMesh/extrude2DMesh/extrude2DMesh.H
similarity index 67%
rename from applications/utilities/mesh/generation/extrude2DMesh/extrude2DMesh.H
rename to applications/utilities/mesh/generation/extrude2DMesh/extrude2DMesh/extrude2DMesh/extrude2DMesh.H
index cdeb787946ec1595a17cdd4a1e82df37f5443a41..0733b5e236b3bece57412e1bb9f88208b1d86975 100644
--- a/applications/utilities/mesh/generation/extrude2DMesh/extrude2DMesh.H
+++ b/applications/utilities/mesh/generation/extrude2DMesh/extrude2DMesh/extrude2DMesh/extrude2DMesh.H
@@ -25,8 +25,8 @@ Class
     Foam::extrude2DMesh
 
 Description
-    Given 2D mesh insert all the topology changes to extrude. Does not work
-    in parallel
+    Given a 2D mesh insert all the topology changes to extrude. Does not work
+    in parallel.
 
 SourceFiles
     extrude2DMesh.C
@@ -36,9 +36,12 @@ SourceFiles
 #ifndef extrude2DMesh_H
 #define extrude2DMesh_H
 
+#include "typeInfo.H"
 #include "label.H"
 #include "scalar.H"
-#include "typeInfo.H"
+#include "labelList.H"
+#include "dictionary.H"
+#include "extrudeModel.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
@@ -50,6 +53,7 @@ class polyMesh;
 class polyTopoChange;
 class mapPolyMesh;
 class mapDistributePolyMesh;
+class polyBoundaryMesh;
 
 /*---------------------------------------------------------------------------*\
                            Class extrude2DMesh Declaration
@@ -60,8 +64,34 @@ class extrude2DMesh
     // Private data
 
         //- Reference to 2D mesh
-        const polyMesh& mesh_;
+        polyMesh& mesh_;
+
+        const dictionary dict_;
+
+        //const dictionary patchDict_;
+
+        const extrudeModel& model_;
+
+        const word modelType_;
+
+        const word patchType_;
+
+        label frontPatchI_;
+        label backPatchI_;
+
+    // Private Member Functions
+
+        //- Check the mesh is 2D
+        void check2D() const;
 
+        //- Find extrusion direction
+        //void findExtrudeDirection();
+
+        //- Disallow default bitwise copy construct
+        extrude2DMesh(const extrude2DMesh&);
+
+        //- Disallow default bitwise assignment
+        void operator=(const extrude2DMesh&);
 
 public:
 
@@ -70,21 +100,25 @@ public:
 
 
     // Constructors
+        extrude2DMesh
+        (
+            polyMesh&,
+            const dictionary& dict,
+            const extrudeModel& model
+        );
 
-        //- Construct from mesh
-        extrude2DMesh(const polyMesh&);
+
+    //- Destructor
+    ~extrude2DMesh();
 
 
     // Member Functions
 
+        //- Add front and back patches
+        void addFrontBackPatches();
+
         //- Play commands into polyTopoChange to extrude mesh.
-        void setRefinement
-        (
-            const direction extrudeDir,
-            const scalar thickness,
-            const label frontPatchI,
-            polyTopoChange&
-        ) const;
+        void setRefinement(polyTopoChange&);
 
         //- Force recalculation of locally stored data on topological change
         void updateMesh(const mapPolyMesh&)
@@ -93,6 +127,17 @@ public:
         //- Force recalculation of locally stored data for mesh distribution
         void distribute(const mapDistributePolyMesh&)
         {}
+
+        label frontPatchI() const
+        {
+            return frontPatchI_;
+        }
+
+        label backPatchI() const
+        {
+            return backPatchI_;
+        }
+
 };
 
 
diff --git a/applications/utilities/mesh/generation/extrude2DMesh/extrude2DMesh/patchToPoly2DMesh/patchToPoly2DMesh.C b/applications/utilities/mesh/generation/extrude2DMesh/extrude2DMesh/patchToPoly2DMesh/patchToPoly2DMesh.C
new file mode 100644
index 0000000000000000000000000000000000000000..30c7a0334afb1ff5e6499e32458a56575fa7ce1c
--- /dev/null
+++ b/applications/utilities/mesh/generation/extrude2DMesh/extrude2DMesh/patchToPoly2DMesh/patchToPoly2DMesh.C
@@ -0,0 +1,333 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
+     \\/     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 "patchToPoly2DMesh.H"
+#include "PatchTools.H"
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+
+// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
+
+
+// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
+
+void Foam::patchToPoly2DMesh::flipFaceOrder()
+{
+    const edgeList& edges = patch_.edges();
+    const faceList& localFaces = patch_.localFaces();
+    const labelList& meshPoints = patch_.meshPoints();
+
+    Info<< "Flipping face order if necessary." << endl;
+    forAll(edges, edgeI)
+    {
+        const edge& e = edges[edgeI];
+
+        faces_[edgeI].setSize(2);
+
+        label edgeOwner = owner_[edgeI];
+
+        const face& f = localFaces[edgeOwner];
+
+        label fp = findIndex(f, e[0]);
+
+        if (f.nextLabel(fp) != e[1])
+        {
+            Info<< "Flipping face " << faces_[edgeI] << endl;
+            faces_[edgeI][0] = meshPoints[e[1]];
+            faces_[edgeI][1] = meshPoints[e[0]];
+        }
+        else
+        {
+            faces_[edgeI][0] = meshPoints[e[0]];
+            faces_[edgeI][1] = meshPoints[e[1]];
+        }
+    }
+}
+
+
+void Foam::patchToPoly2DMesh::createNeighbours()
+{
+    const edgeList& edges = patch_.edges();
+    const labelListList& edgeFaces = patch_.edgeFaces();
+
+    Info<< "Calculating neighbours." << endl;
+    forAll(edges, edgeI)
+    {
+        const labelList& eFaces = edgeFaces[edgeI];
+        if (eFaces.size() == 2)
+        {
+            if (owner_[edgeI] == eFaces[0])
+            {
+                neighbour_[edgeI] = eFaces[1];
+            }
+            else
+            {
+                neighbour_[edgeI] = eFaces[0];
+            }
+        }
+        else if (eFaces.size() == 1)
+        {
+            continue;
+        }
+        else
+        {
+            FatalErrorIn("polyMesh neighbour construction")
+                << abort(FatalError);
+        }
+    }
+}
+
+
+Foam::labelList Foam::patchToPoly2DMesh::internalFaceOrder()
+{
+    const labelListList& cellFaces = patch_.faceEdges();
+
+    labelList oldToNew(owner_.size(), -1);
+
+    label newFaceI = 0;
+
+    forAll(cellFaces, cellI)
+    {
+        const labelList& cFaces = cellFaces[cellI];
+        // Neighbouring cells
+        SortableList<label> nbr(cFaces.size(), -1);
+
+        forAll(cFaces, cfI)
+        {
+            if (cFaces[cfI] < neighbour_.size())
+            {
+                label nbrFaceI = neighbour_[cFaces[cfI]];
+
+                // Internal face. Get cell on other side.
+                if (nbrFaceI == cellI)
+                {
+                    nbrFaceI = owner_[cellI];
+                }
+
+                if (cellI < nbrFaceI)
+                {
+                    // CellI is master
+                    nbr[cfI] = nbrFaceI;
+                }
+            }
+        }
+
+        nbr.sort();
+
+        forAll(nbr, i)
+        {
+            if (nbr[i] != -1)
+            {
+                oldToNew[cFaces[nbr.indices()[i]]] = newFaceI++;
+            }
+        }
+    }
+
+    return oldToNew;
+}
+
+
+void Foam::patchToPoly2DMesh::addPatchFacesToFaces()
+{
+    const labelList& meshPoints = patch_.meshPoints();
+
+    label offset = patch_.nInternalEdges();
+    face f(2);
+
+    forAll(patchNames_, patchI)
+    {
+        forAllConstIter(EdgeMap<label>, mapEdgesRegion_, eIter)
+        {
+            if (eIter() == patchI)
+            {
+                f[0] = meshPoints[eIter.key().start()];
+                f[1] = meshPoints[eIter.key().end()];
+                faces_[offset++] = f;
+            }
+        }
+    }
+
+    f.clear();
+}
+
+
+void Foam::patchToPoly2DMesh::addPatchFacesToOwner()
+{
+    const label nInternalEdges = patch_.nInternalEdges();
+    const faceList& faces = patch_.faces();
+    const label nExternalEdges = patch_.edges().size() - nInternalEdges;
+    const labelList& meshPoints = patch_.meshPoints();
+
+    // Reorder patch faces on owner list.
+    labelList newOwner = owner_;
+
+    label nMatched = 0;
+
+    for
+    (
+        label bFaceI = nInternalEdges;
+        bFaceI < faces_.size();
+        ++bFaceI
+    )
+    {
+        const face& e = faces_[bFaceI];
+
+        bool matched = false;
+
+        for
+        (
+            label bEdgeI = nInternalEdges;
+            bEdgeI < faces_.size();
+            ++bEdgeI
+        )
+        {
+            if
+            (
+                e[0] == meshPoints[patch_.edges()[bEdgeI][0]]
+             && e[1] == meshPoints[patch_.edges()[bEdgeI][1]]
+            )
+            {
+                const face& f = faces[owner_[bEdgeI]];
+
+                label fp = findIndex(f, e[0]);
+
+                newOwner[bFaceI] = owner_[bEdgeI];
+
+                if (f.nextLabel(fp) != e[1])
+                {
+                    Info<< "Flipping" << endl;
+
+                    faces_[bFaceI][0] = e[1];
+                    faces_[bFaceI][1] = e[0];
+                }
+
+                nMatched++;
+
+                matched = true;
+            }
+            else if
+            (
+                e[0] == meshPoints[patch_.edges()[bEdgeI][1]]
+             && e[1] == meshPoints[patch_.edges()[bEdgeI][0]]
+            )
+            {
+                Info<< "Warning: Wrong orientation." << endl;
+                nMatched++;
+                matched = true;
+            }
+        }
+        if (!matched)
+        {
+            Info<< "No match for edge." << endl;
+        }
+    }
+
+    if (nMatched != nExternalEdges)
+    {
+        Info<< "Number of matched edges, " << nMatched
+            << ", does not match number of external edges, "
+            << nExternalEdges << endl;
+    }
+
+    owner_ = newOwner.xfer();
+}
+
+
+void Foam::patchToPoly2DMesh::createPolyMeshComponents()
+{
+    flipFaceOrder();
+
+    createNeighbours();
+
+    // New function for returning a map of old faces to new faces.
+    labelList oldToNew = internalFaceOrder();
+
+    inplaceReorder(oldToNew, faces_);
+    inplaceReorder(oldToNew, owner_);
+    inplaceReorder(oldToNew, neighbour_);
+
+    // Add patches.
+    addPatchFacesToFaces();
+
+    addPatchFacesToOwner();
+}
+
+// * * * * * * * * * * * * Protected Member Functions  * * * * * * * * * * * //
+
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+//- Construct from a primitivePatch
+Foam::patchToPoly2DMesh::patchToPoly2DMesh
+(
+    const MeshedSurface<face>& patch,
+    const wordList& patchNames,
+    const labelList& patchSizes,
+    const EdgeMap<label>& mapEdgesRegion
+)
+:
+    patch_(patch),
+    patchNames_(patchNames),
+    patchSizes_(patchSizes),
+    patchStarts_(patchNames.size(), 0),
+    mapEdgesRegion_(mapEdgesRegion),
+    points_(patch.points()),
+    faces_(patch.nEdges()),
+    owner_(PatchTools::edgeOwner(patch)),
+    neighbour_(patch.nInternalEdges())
+{}
+
+
+// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
+
+Foam::patchToPoly2DMesh::~patchToPoly2DMesh()
+{}
+
+
+// * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * * //
+
+void Foam::patchToPoly2DMesh::createMesh()
+{
+    createPolyMeshComponents();
+
+    label startFace = patch_.nInternalEdges();
+    forAll(patchNames_, patchI)
+    {
+        patchStarts_[patchI] = startFace;
+        startFace += patchSizes_[patchI];
+    }
+}
+
+// * * * * * * * * * * * * * * Member Operators  * * * * * * * * * * * * * * //
+
+
+// * * * * * * * * * * * * * * Friend Functions  * * * * * * * * * * * * * * //
+
+
+// * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * * //
+
+
+// ************************************************************************* // 
diff --git a/applications/utilities/mesh/generation/extrude2DMesh/extrude2DMesh/patchToPoly2DMesh/patchToPoly2DMesh.H b/applications/utilities/mesh/generation/extrude2DMesh/extrude2DMesh/patchToPoly2DMesh/patchToPoly2DMesh.H
new file mode 100644
index 0000000000000000000000000000000000000000..a07f73f0d4b8dfd0bea1dfac851cb748bbce0618
--- /dev/null
+++ b/applications/utilities/mesh/generation/extrude2DMesh/extrude2DMesh/patchToPoly2DMesh/patchToPoly2DMesh.H
@@ -0,0 +1,165 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2011-2011 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::patchToPoly2DMesh
+
+Description
+    Convert a primitivePatch into a 2D polyMesh.
+
+SourceFiles
+    patchToPoly2DMesh.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef patchToPoly2DMesh_H
+#define patchToPoly2DMesh_H
+
+#include "EdgeMap.H"
+#include "MeshedSurface.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+/*---------------------------------------------------------------------------*\
+                     Class patchToPoly2DMesh Declaration
+\*---------------------------------------------------------------------------*/
+
+class patchToPoly2DMesh
+{
+    // Private data
+
+        const MeshedSurface<face>& patch_;
+
+        const wordList& patchNames_;
+
+        const labelList& patchSizes_;
+
+        labelList patchStarts_;
+
+        const EdgeMap<label>& mapEdgesRegion_;
+
+        pointField points_;
+        faceList faces_;
+        labelList owner_;
+        labelList neighbour_;
+
+        //- Description of data_
+        void flipFaceOrder();
+
+        void createNeighbours();
+
+        labelList internalFaceOrder();
+
+        void addPatchFacesToFaces();
+
+        void addPatchFacesToOwner();
+
+        void createPolyMeshComponents();
+
+
+    // Private Member Functions
+
+        //- Disallow default bitwise copy construct
+        patchToPoly2DMesh(const patchToPoly2DMesh&);
+
+        //- Disallow default bitwise assignment
+        void operator=(const patchToPoly2DMesh&);
+
+
+public:
+
+    // Constructors
+
+        //- Construct from a primitivePatch
+        patchToPoly2DMesh
+        (
+            const MeshedSurface<face>& patch,
+            const wordList& patchNames,
+            const labelList& patchSizes,
+            const EdgeMap<label>& mapEdgesRegion
+        );
+
+
+    //- Destructor
+    ~patchToPoly2DMesh();
+
+
+    // Member Functions
+
+        // Access
+        pointField& points()
+        {
+            return points_;
+        }
+
+        faceList& faces()
+        {
+            return faces_;
+        }
+
+        labelList& owner()
+        {
+            return owner_;
+        }
+
+        labelList& neighbour()
+        {
+            return neighbour_;
+        }
+
+        const wordList& patchNames() const
+        {
+            return patchNames_;
+        }
+
+        const labelList& patchSizes() const
+        {
+            return patchSizes_;
+        }
+
+        const labelList& patchStarts() const
+        {
+            return patchStarts_;
+        }
+        // Check
+
+        // Edit
+        void createMesh();
+
+        // Write
+
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* // 
diff --git a/applications/utilities/mesh/generation/extrude2DMesh/extrude2DMeshApp.C b/applications/utilities/mesh/generation/extrude2DMesh/extrude2DMeshApp.C
index 364ee98b79d64ff93448fd8e69ca1aaa36596b9c..4bb6b97b1616b5d11b86c5ee99e878d423efcfe3 100644
--- a/applications/utilities/mesh/generation/extrude2DMesh/extrude2DMeshApp.C
+++ b/applications/utilities/mesh/generation/extrude2DMesh/extrude2DMeshApp.C
@@ -28,13 +28,6 @@ Description
     Takes 2D mesh (all faces 2 points only, no front and back faces) and
     creates a 3D mesh by extruding with specified thickness.
 
-Usage
-
-    - extrude2DMesh thickness
-
-    \param thickness \n
-    Thickness (in metre) of slab.
-
 Note
     Not sure about the walking of the faces to create the front and back faces.
 
@@ -43,155 +36,261 @@ Note
 #include "argList.H"
 #include "Time.H"
 #include "polyMesh.H"
-#include "polyTopoChange.H"
 #include "extrude2DMesh.H"
-#include "emptyPolyPatch.H"
+#include "extrudeModel.H"
+#include "polyTopoChange.H"
+#include "MeshedSurface.H"
+#include "edgeCollapser.H"
+#include "addPatchCellLayer.H"
+#include "patchToPoly2DMesh.H"
 
 using namespace Foam;
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
-// Main program:
+enum ExtrudeMode
+{
+    POLYMESH2D,
+    MESHEDSURFACE
+};
 
-int main(int argc, char *argv[])
+namespace Foam
 {
-#   include "addOverwriteOption.H"
-    argList::validArgs.append("thickness");
+    template<>
+    const char* NamedEnum<ExtrudeMode, 2>::names[] =
+    {
+        "polyMesh2D",
+        "MeshedSurface"
+    };
+}
 
-#   include "setRootCase.H"
-#   include "createTime.H"
-    runTime.functionObjects().off();
-#   include "createPolyMesh.H"
-    const word oldInstance = mesh.pointsInstance();
+static const NamedEnum<ExtrudeMode, 2> ExtrudeModeNames;
 
-    const scalar thickness = args.argRead<scalar>(1);
-    const bool overwrite   = args.optionFound("overwrite");
 
+//pointField moveInitialPoints
+//(
+//    primitiveFacePatch& fMesh,
+//    const extrudeModel& model
+//)
+//{
+//    pointField layer0Points(fMesh.nPoints());
+//    pointField layer1Points(fMesh.nPoints());
+//    pointField displacement(fMesh.nPoints());
 
-    // Check that mesh is 2D
-    // ~~~~~~~~~~~~~~~~~~~~~
+//    forAll(layer0Points, pointI)
+//    {
+//        const labelList& meshPoints = fMesh.meshPoints();
+//        label meshPointI = meshPoints[pointI];
 
-    const faceList& faces = mesh.faces();
-    forAll(faces, faceI)
-    {
-        if (faces[faceI].size() != 2)
-        {
-            FatalErrorIn(args.executable())
-                << "Face " << faceI << " size " << faces[faceI].size()
-                << " is not of size 2 so mesh is not proper two-dimensional."
-                << exit(FatalError);
-        }
-    }
+//        layer0Points[meshPointI] = model
+//        (
+//            fMesh.points()[meshPointI],
+//            fMesh.pointNormals()[pointI],
+//            0
+//        );
 
+//        layer1Points[meshPointI] = model
+//        (
+//            fMesh.points()[meshPointI],
+//            fMesh.pointNormals()[pointI],
+//            1
+//        );
 
-    // Find extrude direction
-    // ~~~~~~~~~~~~~~~~~~~~~~
+//        displacement[pointI] =
+//            layer1Points[meshPointI]
+//          - layer0Points[meshPointI];
+//    }
 
-    scalar minRange = GREAT;
-    direction extrudeDir = 4;   //illegal value.
+//    fMesh.movePoints(layer0Points);
 
-    for (direction dir = 0; dir < 3; dir++)
-    {
-        scalarField cmpts(mesh.points().component(dir));
+//    return displacement;
+//}
 
-        scalar range = max(cmpts)-min(cmpts);
 
-        Info<< "Direction:" << dir << " range:" << range << endl;
+// Main program:
 
-        if (range < minRange)
-        {
-            minRange = range;
-            extrudeDir = dir;
-        }
-    }
+int main(int argc, char *argv[])
+{
+    argList::validArgs.append("surfaceFormat");
 
-    Info<< "Extruding in direction " << extrudeDir
-        << " with thickness " << thickness << nl
-        << endl;
+    #include "setRootCase.H"
 
+    Info<< "Create time\n" << endl;
 
+    Time runTimeExtruded
+    (
+        Time::controlDictName,
+        args.rootPath(),
+        args.caseName()
+    );
 
-    const polyBoundaryMesh& patches = mesh.boundaryMesh();
+    runTimeExtruded.functionObjects().off();
 
+    const ExtrudeMode surfaceFormat = ExtrudeModeNames[args[1]];
 
-    // Add front and back patch
-    // ~~~~~~~~~~~~~~~~~~~~~~~~
+    Info<< "Extruding from " << ExtrudeModeNames[surfaceFormat]
+        << " at time " << runTimeExtruded.timeName() << endl;
 
-    label frontPatchI = patches.findPatchID("frontAndBack");
+    IOdictionary extrude2DMeshDict
+    (
+        IOobject
+        (
+            "extrude2DMeshDict",
+            runTimeExtruded.system(),
+            runTimeExtruded,
+            IOobject::MUST_READ,
+            IOobject::NO_WRITE,
+            false
+        )
+    );
 
-    if (frontPatchI == -1)
+    // Point generator
+    autoPtr<extrudeModel> model(extrudeModel::New(extrude2DMeshDict));
+
+    autoPtr<MeshedSurface<face> > fMesh;
+
+    autoPtr<polyMesh> mesh;
+
+    autoPtr<polyTopoChange> meshMod;
+
+    labelListList extrudeEdgePatches;
+
+    if (surfaceFormat == MESHEDSURFACE)
     {
-        // Add patch.
-        List<polyPatch*> newPatches(patches.size()+1);
+        fMesh.set(new MeshedSurface<face>("MeshedSurface.obj"));
 
-        forAll(patches, patchI)
-        {
-            const polyPatch& pp = patches[patchI];
+        EdgeMap<label> edgeRegionMap;
+        wordList patchNames(1, "default");
+        labelList patchSizes(1, fMesh().nEdges() - fMesh().nInternalEdges());
 
-            newPatches[patchI] = pp.clone
-            (
-                patches,
-                newPatches.size(),
-                pp.size(),
-                pp.start()
-            ).ptr();
+        const edgeList& edges = fMesh().edges();
+        forAll(edges, edgeI)
+        {
+            if (!fMesh().isInternalEdge(edgeI))
+            {
+                edgeRegionMap.insert(edges[edgeI], 0);
+            }
         }
 
-        frontPatchI = patches.size();
-
-        newPatches[frontPatchI] = new emptyPolyPatch
+        patchToPoly2DMesh poly2DMesh
         (
-            "frontAndBack",
-            0,
-            mesh.nFaces(),
-            frontPatchI,
-            patches
+            fMesh(),
+            patchNames,
+            patchSizes,
+            edgeRegionMap
         );
 
-        Info<< "Adding empty patch " << newPatches[frontPatchI]->name()
-            << " at index " << frontPatchI
-            << " for front and back faces." << nl << endl;
+        poly2DMesh.createMesh();
 
-        mesh.removeBoundary();
-        mesh.addPatches(newPatches);
-    }
+        mesh.set
+        (
+            new polyMesh
+            (
+                IOobject
+                (
+                    polyMesh::defaultRegion,
+                    runTimeExtruded.constant(),
+                    runTimeExtruded,
+                    IOobject::NO_READ,
+                    IOobject::NO_WRITE,
+                    false
+                ),
+                xferMove(poly2DMesh.points()),
+                xferMove(poly2DMesh.faces()),
+                xferMove(poly2DMesh.owner()),
+                xferMove(poly2DMesh.neighbour())
+            )
+        );
 
+        Info<< "Constructing patches." << endl;
+        List<polyPatch*> patches(poly2DMesh.patchNames().size());
 
+        forAll(patches, patchI)
+        {
+            patches[patchI] = new polyPatch
+            (
+                poly2DMesh.patchNames()[patchI],
+                poly2DMesh.patchSizes()[patchI],
+                poly2DMesh.patchStarts()[patchI],
+                patchI,
+                mesh().boundaryMesh()
+            );
+        }
 
-    // Topo changes container. Initialise with number of patches.
-    polyTopoChange meshMod(mesh.boundaryMesh().size());
+        mesh().addPatches(patches);
+    }
+    else if (surfaceFormat == POLYMESH2D)
+    {
+        mesh.set
+        (
+            new polyMesh
+            (
+                Foam::IOobject
+                (
+                    Foam::polyMesh::defaultRegion,
+                    runTimeExtruded.timeName(),
+                    runTimeExtruded,
+                    Foam::IOobject::MUST_READ
+                )
+            )
+        );
+    }
 
     // Engine to extrude mesh
-    extrude2DMesh extruder(mesh);
+    extrude2DMesh extruder(mesh(), extrude2DMeshDict, model());
 
-    // Insert changes into meshMod
-    extruder.setRefinement
-    (
-        extrudeDir,
-        thickness,
-        frontPatchI,
-        meshMod
-    );
+    extruder.addFrontBackPatches();
+
+    meshMod.set(new polyTopoChange(mesh().boundaryMesh().size()));
+
+    extruder.setRefinement(meshMod());
 
     // Create a mesh from topo changes.
-    autoPtr<mapPolyMesh> morphMap = meshMod.changeMesh(mesh, false);
+    autoPtr<mapPolyMesh> morphMap = meshMod().changeMesh(mesh(), false);
 
-    mesh.updateMesh(morphMap);
+    mesh().updateMesh(morphMap);
 
-    if (!overwrite)
-    {
-        runTime++;
-    }
-    else
     {
-        mesh.setInstance(oldInstance);
+        edgeCollapser collapser(mesh());
+
+        const edgeList& edges = mesh().edges();
+        const pointField& points = mesh().points();
+
+        const boundBox& bb = mesh().bounds();
+        const scalar mergeDim = 1E-4 * bb.minDim();
+
+        forAll(edges, edgeI)
+        {
+            const edge& e = edges[edgeI];
+
+            scalar d = e.mag(points);
+
+            if (d < mergeDim)
+            {
+                Info<< "Merging edge " << e << " since length " << d
+                    << " << " << mergeDim << nl;
+
+                // Collapse edge to e[0]
+                collapser.collapseEdge(edgeI, e[0]);
+            }
+        }
+
+        polyTopoChange meshModCollapse(mesh());
+
+        collapser.setRefinement(meshModCollapse);
+
+        // Create a mesh from topo changes.
+        autoPtr<mapPolyMesh> morphMap
+            = meshModCollapse.changeMesh(mesh(), false);
+
+        mesh().updateMesh(morphMap);
     }
 
     // Take over refinement levels and write to new time directory.
-    Pout<< "Writing extruded mesh to time " << runTime.timeName() << nl
-        << endl;
+    Pout<< "\nWriting extruded mesh to time = " << runTimeExtruded.timeName()
+        << nl << endl;
 
-    mesh.write();
+    mesh().write();
 
     Pout<< "End\n" << endl;
 
diff --git a/applications/utilities/mesh/generation/extrude2DMesh/extrude2DMeshDict b/applications/utilities/mesh/generation/extrude2DMesh/extrude2DMeshDict
new file mode 100644
index 0000000000000000000000000000000000000000..5e53c29c886fa05b2158b0d032d85b5f6ed148b7
--- /dev/null
+++ b/applications/utilities/mesh/generation/extrude2DMesh/extrude2DMeshDict
@@ -0,0 +1,46 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  dev                                   |
+|   \\  /    A nd           | Web:      www.OpenFOAM.org                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+
+FoamFile
+{
+    version         2.0;
+    format          ascii;
+
+    root            "";
+    case            "";
+    instance        "";
+    local           "";
+
+    class           dictionary;
+    object          extrude2DMeshDict;
+}
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+extrudeModel        linearDirection;
+//extrudeModel        wedge;
+
+patchType           empty;
+//patchType           wedge;
+
+nLayers             1;
+
+expansionRatio      1.0;
+
+linearDirectionCoeffs
+{
+    direction       (0 0 1);
+    thickness       0.1;
+}
+
+wedgeCoeffs
+{
+    axisPt      (0 0 0);
+    axis        (1 0 0);
+    angle       10;
+}
diff --git a/applications/utilities/mesh/manipulation/polyDualMesh/meshDualiser.C b/applications/utilities/mesh/manipulation/polyDualMesh/meshDualiser.C
index ea88cf6198bfa5de24ce1f6b1a419591a29b23f9..9ef58b47e40934bcf8a0a2cc5c14953b333769f4 100644
--- a/applications/utilities/mesh/manipulation/polyDualMesh/meshDualiser.C
+++ b/applications/utilities/mesh/manipulation/polyDualMesh/meshDualiser.C
@@ -49,19 +49,17 @@ void Foam::meshDualiser::checkPolyTopoChange(const polyTopoChange& meshMod)
     }
 
     labelList oldToNew;
-    pointField newPoints;
-    bool hasMerged = mergePoints
+    label nUnique = mergePoints
     (
         points,
         1E-6,
         false,
-        oldToNew,
-        newPoints
+        oldToNew
     );
 
-    if (hasMerged)
+    if (nUnique < points.size())
     {
-        labelListList newToOld(invertOneToMany(newPoints.size(), oldToNew));
+        labelListList newToOld(invertOneToMany(nUnique, oldToNew));
 
         forAll(newToOld, newI)
         {
@@ -225,17 +223,15 @@ Foam::label Foam::meshDualiser::addInternalFace
         pointField facePoints(meshMod.points(), newFace);
 
         labelList oldToNew;
-        pointField newPoints;
-        bool hasMerged = mergePoints
+        label nUnique = mergePoints
         (
             facePoints,
             1E-6,
             false,
-            oldToNew,
-            newPoints
+            oldToNew
         );
 
-        if (hasMerged)
+        if (nUnique < facePoints.size())
         {
             FatalErrorIn("addInternalFace(..)")
                 << "verts:" << verts << " newFace:" << newFace
diff --git a/applications/utilities/mesh/manipulation/renumberMesh/Make/options b/applications/utilities/mesh/manipulation/renumberMesh/Make/options
index b5e293282a48fcc11891c2222ad3a6b75ee23d2f..2981cf30bea351bd387501cbaa5c65443ae6b769 100644
--- a/applications/utilities/mesh/manipulation/renumberMesh/Make/options
+++ b/applications/utilities/mesh/manipulation/renumberMesh/Make/options
@@ -2,6 +2,7 @@ EXE_INC = \
     -I$(LIB_SRC)/meshTools/lnInclude \
     -I$(LIB_SRC)/dynamicMesh/lnInclude \
     -I$(LIB_SRC)/finiteVolume/lnInclude \
+    -I$(LIB_SRC)/renumberMethods/lnInclude \
     -I$(LIB_SRC)/parallel/decompose/decompositionMethods/lnInclude
 
 EXE_LIBS = \
@@ -9,4 +10,5 @@ EXE_LIBS = \
     -ldynamicMesh \
     -lfiniteVolume \
     -lgenericPatchFields \
+    -lrenumberMethods \
     -ldecompositionMethods
diff --git a/applications/utilities/mesh/manipulation/renumberMesh/renumberMesh.C b/applications/utilities/mesh/manipulation/renumberMesh/renumberMesh.C
index 8d9b0c91ebab1b0c35cb032be821c1c711c7292a..791f68cf98b971857449ff053c754adb0e8e2350 100644
--- a/applications/utilities/mesh/manipulation/renumberMesh/renumberMesh.C
+++ b/applications/utilities/mesh/manipulation/renumberMesh/renumberMesh.C
@@ -28,6 +28,9 @@ Description
     Renumbers the cell list in order to reduce the bandwidth, reading and
     renumbering all fields from all the time directories.
 
+    By default uses bandCompression (CuthillMcKee) but will
+    read system/renumberMeshDict if present and use the method from there.
+
 \*---------------------------------------------------------------------------*/
 
 #include "argList.H"
@@ -37,16 +40,52 @@ Description
 #include "ReadFields.H"
 #include "volFields.H"
 #include "surfaceFields.H"
-#include "bandCompression.H"
-#include "faceSet.H"
 #include "SortableList.H"
 #include "decompositionMethod.H"
-#include "fvMeshSubset.H"
+#include "renumberMethod.H"
 #include "zeroGradientFvPatchFields.H"
+#include "CuthillMcKeeRenumber.H"
 
 using namespace Foam;
 
 
+// Create named field from labelList for postprocessing
+tmp<volScalarField> createScalarField
+(
+    const fvMesh& mesh,
+    const word& name,
+    const labelList& elems
+)
+{
+    tmp<volScalarField> tfld
+    (
+        new volScalarField
+        (
+            IOobject
+            (
+                name,
+                mesh.time().timeName(),
+                mesh,
+                IOobject::NO_READ,
+                IOobject::AUTO_WRITE,
+                false
+            ),
+            mesh,
+            dimensionedScalar("zero", dimless, 0),
+            zeroGradientFvPatchScalarField::typeName
+        )
+    );
+    volScalarField& fld = tfld();
+
+    forAll(fld, cellI)
+    {
+       fld[cellI] = elems[cellI];
+    }
+
+    return tfld;
+}
+
+
 // Calculate band of matrix
 label getBand(const labelList& owner, const labelList& neighbour)
 {
@@ -65,56 +104,111 @@ label getBand(const labelList& owner, const labelList& neighbour)
 }
 
 
-// Return new to old cell numbering
-labelList regionBandCompression
+// Determine upper-triangular face order
+labelList getFaceOrder
 (
-    const fvMesh& mesh,
-    const labelList& cellToRegion
+    const primitiveMesh& mesh,
+    const labelList& cellOrder      // new to old cell
 )
 {
-    Pout<< "Determining cell order:" << endl;
-
-    labelList cellOrder(cellToRegion.size());
+    labelList reverseCellOrder(invert(cellOrder.size(), cellOrder));
 
-    label nRegions = max(cellToRegion)+1;
+    labelList oldToNewFace(mesh.nFaces(), -1);
 
-    labelListList regionToCells(invertOneToMany(nRegions, cellToRegion));
+    label newFaceI = 0;
 
-    label cellI = 0;
+    labelList nbr;
+    labelList order;
 
-    forAll(regionToCells, regionI)
+    forAll(cellOrder, newCellI)
     {
-        Pout<< "    region " << regionI << " starts at " << cellI << endl;
+        label oldCellI = cellOrder[newCellI];
+
+        const cell& cFaces = mesh.cells()[oldCellI];
+
+        // Neighbouring cells
+        nbr.setSize(cFaces.size());
+
+        forAll(cFaces, i)
+        {
+            label faceI = cFaces[i];
+
+            if (mesh.isInternalFace(faceI))
+            {
+                // Internal face. Get cell on other side.
+                label nbrCellI = reverseCellOrder[mesh.faceNeighbour()[faceI]];
+                if (nbrCellI == newCellI)
+                {
+                    nbrCellI = reverseCellOrder[mesh.faceOwner()[faceI]];
+                }
 
-        // Per region do a reordering.
-        fvMeshSubset subsetter(mesh);
-        subsetter.setLargeCellSubset(cellToRegion, regionI);
-        const fvMesh& subMesh = subsetter.subMesh();
-        labelList subCellOrder(bandCompression(subMesh.cellCells()));
+                if (newCellI < nbrCellI)
+                {
+                    // CellI is master
+                    nbr[i] = nbrCellI;
+                }
+                else
+                {
+                    // nbrCell is master. Let it handle this face.
+                    nbr[i] = -1;
+                }
+            }
+            else
+            {
+                // External face. Do later.
+                nbr[i] = -1;
+            }
+        }
 
-        const labelList& cellMap = subsetter.cellMap();
+        order.setSize(nbr.size());
+        sortedOrder(nbr, order);
 
-        forAll(subCellOrder, i)
+        forAll(order, i)
         {
-            cellOrder[cellI++] = cellMap[subCellOrder[i]];
+            label index = order[i];
+            if (nbr[index] != -1)
+            {
+                oldToNewFace[cFaces[index]] = newFaceI++;
+            }
         }
     }
-    Pout<< endl;
 
-    return cellOrder;
+    // Leave patch faces intact.
+    for (label faceI = newFaceI; faceI < mesh.nFaces(); faceI++)
+    {
+        oldToNewFace[faceI] = faceI;
+    }
+
+
+    // Check done all faces.
+    forAll(oldToNewFace, faceI)
+    {
+        if (oldToNewFace[faceI] == -1)
+        {
+            FatalErrorIn
+            (
+                "getFaceOrder"
+                "(const primitiveMesh&, const labelList&, const labelList&)"
+            )   << "Did not determine new position"
+                << " for face " << faceI
+                << abort(FatalError);
+        }
+    }
+
+    return invert(mesh.nFaces(), oldToNewFace);
 }
 
 
 // Determine face order such that inside region faces are sorted
 // upper-triangular but inbetween region faces are handled like boundary faces.
-labelList regionFaceOrder
+labelList getRegionFaceOrder
 (
     const primitiveMesh& mesh,
     const labelList& cellOrder,     // new to old cell
     const labelList& cellToRegion   // old cell to region
 )
 {
-    Pout<< "Determining face order:" << endl;
+    //Pout<< "Determining face order:" << endl;
 
     labelList reverseCellOrder(invert(cellOrder.size(), cellOrder));
 
@@ -131,8 +225,8 @@ labelList regionFaceOrder
         if (cellToRegion[oldCellI] != prevRegion)
         {
             prevRegion = cellToRegion[oldCellI];
-            Pout<< "    region " << prevRegion << " internal faces start at "
-                << newFaceI << endl;
+            //Pout<< "    region " << prevRegion << " internal faces start at "
+            //    << newFaceI << endl;
         }
 
         const cell& cFaces = mesh.cells()[oldCellI];
@@ -219,9 +313,9 @@ labelList regionFaceOrder
 
             if (prevKey != key)
             {
-                Pout<< "    faces inbetween region " << key/nRegions
-                    << " and " << key%nRegions
-                    << " start at " << newFaceI << endl;
+                //Pout<< "    faces inbetween region " << key/nRegions
+                //    << " and " << key%nRegions
+                //    << " start at " << newFaceI << endl;
                 prevKey = key;
             }
 
@@ -243,14 +337,14 @@ labelList regionFaceOrder
         {
             FatalErrorIn
             (
-                "polyDualMesh::getFaceOrder"
-                "(const labelList&, const labelList&, const label) const"
+                "getRegionFaceOrder"
+                "(const primitveMesh&, const labelList&, const labelList&)"
             )   << "Did not determine new position"
                 << " for face " << faceI
                 << abort(FatalError);
         }
     }
-    Pout<< endl;
+    //Pout<< endl;
 
     return invert(mesh.nFaces(), oldToNewFace);
 }
@@ -365,10 +459,11 @@ autoPtr<mapPolyMesh> reorderMesh
 
 int main(int argc, char *argv[])
 {
-    argList::addBoolOption
+    argList::addOption
     (
-        "blockOrder",
-        "order cells into regions (using decomposition)"
+        "blockSize",
+        "block size",
+        "order cells into blocks (using decomposition) before ordering"
     );
     argList::addBoolOption
     (
@@ -400,12 +495,23 @@ int main(int argc, char *argv[])
 #   include "createNamedMesh.H"
     const word oldInstance = mesh.pointsInstance();
 
-    const bool blockOrder = args.optionFound("blockOrder");
-    if (blockOrder)
+    label blockSize = 0;
+    args.optionReadIfPresent("blockSize", blockSize, 0);
+
+    if (blockSize > 0)
     {
-        Info<< "Ordering cells into regions (using decomposition);"
+        Info<< "Ordering cells into regions of size " << blockSize
+            << " (using decomposition);"
             << " ordering faces into region-internal and region-external." << nl
             << endl;
+
+        if (blockSize < 0 || blockSize >= mesh.nCells())
+        {
+            FatalErrorIn(args.executable())
+                << "Block size " << blockSize << " should be positive integer"
+                << " and less than the number of cells in the mesh."
+                << exit(FatalError);
+        }
     }
 
     const bool orderPoints = args.optionFound("orderPoints");
@@ -432,6 +538,37 @@ int main(int argc, char *argv[])
         << returnReduce(band, maxOp<label>()) << nl << endl;
 
 
+    // Construct renumberMethod
+    IOobject io
+    (
+        "renumberMeshDict",
+        runTime.system(),
+        mesh,
+        IOobject::MUST_READ_IF_MODIFIED,
+        IOobject::NO_WRITE
+    );
+
+    autoPtr<renumberMethod> renumberPtr;
+
+    if (io.headerOk())
+    {
+        Info<< "Detected local " << runTime.system()/io.name() << "." << nl
+            << "Using this to select renumberMethod." << nl << endl;
+        renumberPtr = renumberMethod::New(IOdictionary(io));
+    }
+    else
+    {
+        Info<< "No local " << runTime.system()/io.name()
+            << " dictionary found. Using default renumberMethod." << nl
+            << endl;
+        dictionary renumberDict;
+        renumberPtr.reset(new CuthillMcKeeRenumber(renumberDict));
+    }
+
+    Info<< "Selecting renumberMethod " << renumberPtr().type() << nl << endl;
+
+
+
     // Read parallel reconstruct maps
     labelIOList cellProcAddressing
     (
@@ -521,14 +658,21 @@ int main(int argc, char *argv[])
     PtrList<surfaceTensorField> stFlds;
     ReadFields(mesh, objects, stFlds);
 
+    Info<< endl;
 
-    autoPtr<mapPolyMesh> map;
+    // From renumbering:
+    // - from new cell/face back to original cell/face
+    labelList cellOrder;
+    labelList faceOrder;
 
-    if (blockOrder)
+    if (blockSize > 0)
     {
         // Renumbering in two phases. Should be done in one so mapping of
         // fields is done correctly!
 
+        label nBlocks = mesh.nCells() / blockSize;
+        Info<< "nBlocks = " << nBlocks << endl;
+
         // Read decomposePar dictionary
         IOdictionary decomposeDict
         (
@@ -541,6 +685,8 @@ int main(int argc, char *argv[])
                 IOobject::NO_WRITE
             )
         );
+        decomposeDict.set("numberOfSubdomains", nBlocks);
+
         autoPtr<decompositionMethod> decomposePtr = decompositionMethod::New
         (
             decomposeDict
@@ -556,80 +702,99 @@ int main(int argc, char *argv[])
         );
 
         // For debugging: write out region
-        {
-            volScalarField cellDist
-            (
-                IOobject
-                (
-                    "cellDist",
-                    runTime.timeName(),
-                    mesh,
-                    IOobject::NO_READ,
-                    IOobject::NO_WRITE,
-                    false
-                ),
-                mesh,
-                dimensionedScalar("cellDist", dimless, 0),
-                zeroGradientFvPatchScalarField::typeName
-            );
+        createScalarField
+        (
+            mesh,
+            "cellDist",
+            cellToRegion
+        )().write();
 
-            forAll(cellToRegion, cellI)
-            {
-               cellDist[cellI] = cellToRegion[cellI];
-            }
+        Info<< nl << "Written decomposition as volScalarField to "
+            << "cellDist for use in postprocessing."
+            << nl << endl;
 
-            cellDist.write();
 
-            Info<< nl << "Written decomposition as volScalarField to "
-                << cellDist.name() << " for use in postprocessing."
-                << nl << endl;
+        // Find point per region
+        pointField regionPoints(nBlocks, vector::zero);
+        forAll(cellToRegion, cellI)
+        {
+            regionPoints[cellToRegion[cellI]] = mesh.cellCentres()[cellI];
         }
 
         // Use block based renumbering.
-        //labelList cellOrder(bandCompression(mesh.cellCells()));
-        labelList cellOrder(regionBandCompression(mesh, cellToRegion));
+        // Detemines old to new cell ordering
+        labelList reverseCellOrder = renumberPtr().renumber
+        (
+            mesh,
+            cellToRegion,
+            regionPoints
+        );
+
+        cellOrder = invert(mesh.nCells(), reverseCellOrder);
 
         // Determine new to old face order with new cell numbering
-        labelList faceOrder
+        faceOrder = getRegionFaceOrder
         (
-            regionFaceOrder
-            (
-                mesh,
-                cellOrder,
-                cellToRegion
-            )
+            mesh,
+            cellOrder,
+            cellToRegion
+        );
+    }
+    else
+    {
+        // Detemines old to new cell ordering
+        labelList reverseCellOrder = renumberPtr().renumber
+        (
+            mesh,
+            mesh.cellCentres()
         );
 
-        if (!overwrite)
-        {
-            runTime++;
-        }
+        cellOrder = invert(mesh.nCells(), reverseCellOrder);
 
-        // Change the mesh.
-        map = reorderMesh(mesh, cellOrder, faceOrder);
+        // Determine new to old face order with new cell numbering
+        faceOrder = getFaceOrder
+        (
+            mesh,
+            cellOrder      // new to old cell
+        );
     }
-    else
+
+
+    if (!overwrite)
     {
-        // Use built-in renumbering.
+        runTime++;
+    }
 
-        polyTopoChange meshMod(mesh);
 
-        if (!overwrite)
-        {
-            runTime++;
-        }
+    // Change the mesh.
+    autoPtr<mapPolyMesh> map = reorderMesh(mesh, cellOrder, faceOrder);
 
-        // Change the mesh.
-        map = meshMod.changeMesh
+
+    if (orderPoints)
+    {
+        polyTopoChange meshMod(mesh);
+        autoPtr<mapPolyMesh> pointOrderMap = meshMod.changeMesh
         (
             mesh,
-            false,      // inflate
-            true,       // parallel sync
-            true,       // cell ordering
-            orderPoints // point ordering
+            false,      //inflate
+            true,       //syncParallel
+            false,      //orderCells
+            orderPoints //orderPoints
+        );
+        // Combine point reordering into map.
+        const_cast<labelList&>(map().pointMap()) = UIndirectList<label>
+        (
+            map().pointMap(),
+            pointOrderMap().pointMap()
+        )();
+        inplaceRenumber
+        (
+            pointOrderMap().reversePointMap(),
+            const_cast<labelList&>(map().reversePointMap())
         );
     }
 
+
     // Update fields
     mesh.updateMesh(map);
 
@@ -767,6 +932,24 @@ int main(int argc, char *argv[])
 
     if (writeMaps)
     {
+        // For debugging: write out region
+        createScalarField
+        (
+            mesh,
+            "origCellID",
+            map().cellMap()
+        )().write();
+        createScalarField
+        (
+            mesh,
+            "cellID",
+            identity(mesh.nCells())
+        )().write();
+        Info<< nl << "Written current cellID and origCellID as volScalarField"
+            << " for use in postprocessing."
+            << nl << endl;
+
+
         labelIOList
         (
             IOobject
diff --git a/applications/utilities/mesh/manipulation/renumberMesh/renumberMeshDict b/applications/utilities/mesh/manipulation/renumberMesh/renumberMeshDict
new file mode 100644
index 0000000000000000000000000000000000000000..7ff33fc530ed8f5303ed060a89fd3dfe9094f0f3
--- /dev/null
+++ b/applications/utilities/mesh/manipulation/renumberMesh/renumberMeshDict
@@ -0,0 +1,51 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  dev                                   |
+|   \\  /    A nd           | Web:      www.OpenFOAM.org                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    note        "mesh renumbering dictionary";
+    object      renumberMeshDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+method          CuthillMcKee;
+//method          manual;
+//method          random;
+//method          spring;
+
+CuthillMcKeeCoeffs
+{
+    // Reverse CuthillMcKee (RCM) or plain
+    reverse true;
+}
+
+
+manualCoeffs
+{
+    // In system directory: old to new labelIOList
+    dataFile "cellMap";
+}
+
+
+springCoeffs
+{
+    // Maximum jump of cell indices. Is fraction of number of cells
+    maxCo 0.01;
+
+    // Limit the amount of movement; the fraction maxCo gets decreased
+    // with every iteration
+    freezeFraction 0.999;
+
+    // Maximum number of iterations
+    maxIter 1000;
+}
+
+
+// ************************************************************************* //
diff --git a/applications/utilities/surface/surfaceConvert/surfaceConvert.C b/applications/utilities/surface/surfaceConvert/surfaceConvert.C
index 504262012c0abf14e2f781b51441bd1616c3071d..66af664ad7d844c9e979563e6d82a537c3a3f076 100644
--- a/applications/utilities/surface/surfaceConvert/surfaceConvert.C
+++ b/applications/utilities/surface/surfaceConvert/surfaceConvert.C
@@ -49,6 +49,7 @@ Note
 #include "triSurface.H"
 #include "OFstream.H"
 #include "OSspecific.H"
+#include "Time.H"
 
 using namespace Foam;
 
@@ -83,9 +84,25 @@ int main(int argc, char *argv[])
         "factor",
         "geometry scaling factor - default is 1"
     );
+    argList::addOption
+    (
+        "writePrecision",
+        "label",
+        "write to output with the specified precision"
+    );
 
     argList args(argc, argv);
 
+    if (args.optionFound("writePrecision"))
+    {
+        label writePrecision = args.optionRead<label>("writePrecision");
+
+        IOstream::defaultPrecision(writePrecision);
+        Sout.precision(writePrecision);
+
+        Info<< "Output write precision set to " << writePrecision << endl;
+    }
+
     const fileName importName = args[1];
     const fileName exportName = args[2];
 
diff --git a/applications/utilities/surface/surfaceFeatureExtract/surfaceFeatureExtract.C b/applications/utilities/surface/surfaceFeatureExtract/surfaceFeatureExtract.C
index d98b3fb8370a17bcf4f22ca9ce573ceff0aed772..5f6ee05fb1202f8f801d16f9498287de8e309aeb 100644
--- a/applications/utilities/surface/surfaceFeatureExtract/surfaceFeatureExtract.C
+++ b/applications/utilities/surface/surfaceFeatureExtract/surfaceFeatureExtract.C
@@ -44,6 +44,7 @@ Description
 #include "indexedOctree.H"
 #include "treeDataEdge.H"
 #include "unitConversion.H"
+#include "plane.H"
 
 using namespace Foam;
 
@@ -94,6 +95,56 @@ void deleteBox
 }
 
 
+bool onLine(const point& p, const linePointRef& line)
+{
+    const point& a = line.start();
+    const point& b = line.end();
+
+    if
+    (
+        ( p.x() < min(a.x(), b.x()) || p.x() > max(a.x(), b.x()) )
+     || ( p.y() < min(a.y(), b.y()) || p.y() > max(a.y(), b.y()) )
+     || ( p.z() < min(a.z(), b.z()) || p.z() > max(a.z(), b.z()) )
+    )
+    {
+        return false;
+    }
+
+    return true;
+}
+
+
+// Deletes all edges inside/outside bounding box from set.
+void deleteEdges
+(
+    const triSurface& surf,
+    const plane& cutPlane,
+    List<surfaceFeatures::edgeStatus>& edgeStat
+)
+{
+    const pointField& points = surf.points();
+    const labelList& meshPoints = surf.meshPoints();
+
+    forAll(edgeStat, edgeI)
+    {
+        const edge& e = surf.edges()[edgeI];
+        const point& p0 = points[meshPoints[e.start()]];
+        const point& p1 = points[meshPoints[e.end()]];
+        const linePointRef line(p0, p1);
+
+        // If edge does not intersect the plane, delete.
+        scalar intersect = cutPlane.lineIntersect(line);
+
+        point featPoint = intersect * (p1 - p0) + p0;
+
+        if (!onLine(featPoint, line))
+        {
+            edgeStat[edgeI] = surfaceFeatures::NONE;
+        }
+    }
+}
+
+
 void drawHitProblem
 (
     label fI,
@@ -270,6 +321,12 @@ int main(int argc, char *argv[])
         "manifoldEdgesOnly",
         "remove any non-manifold (open or more than two connected faces) edges"
     );
+    argList::addOption
+    (
+        "plane",
+        "(nx ny nz)(z0 y0 z0)",
+        "use a plane to create feature edges for 2D meshing"
+    );
 
 #   ifdef ENABLE_CURVATURE
     argList::addBoolOption
@@ -454,6 +511,21 @@ int main(int argc, char *argv[])
         }
     }
 
+    if (args.optionFound("plane"))
+    {
+        plane cutPlane(args.optionLookup("plane")());
+
+        deleteEdges
+        (
+            surf,
+            cutPlane,
+            edgeStat
+        );
+
+        Info<< "Only edges that intersect the plane with normal "
+            << cutPlane.normal() << " and base point " << cutPlane.refPoint()
+            << " will be included as feature edges."<< endl;
+    }
 
     surfaceFeatures newSet(surf);
     newSet.setFromStatus(edgeStat);
@@ -475,7 +547,6 @@ int main(int argc, char *argv[])
         << endl;
 
     // Extracting and writing a extendedFeatureEdgeMesh
-
     extendedFeatureEdgeMesh feMesh
     (
         newSet,
diff --git a/src/OpenFOAM/Make/files b/src/OpenFOAM/Make/files
index da569b2e2113f39cd7b1c4401847cc2938f3e715..cbd98885739d0a9f300d2630dc591c273cf59ffd 100644
--- a/src/OpenFOAM/Make/files
+++ b/src/OpenFOAM/Make/files
@@ -45,6 +45,7 @@ primitives/Tensor/lists/symmTensorList.C
 primitives/Tensor/lists/tensorList.C
 
 primitives/Vector/complexVector/complexVector.C
+primitives/Vector/floatVector/floatVector.C
 primitives/Vector/labelVector/labelVector.C
 primitives/Vector/vector/vector.C
 primitives/Vector/lists/vectorList.C
@@ -501,7 +502,6 @@ meshes/treeBoundBox/treeBoundBox.C
 
 meshTools = meshes/meshTools
 $(meshTools)/matchPoints.C
-$(meshTools)/mergePoints.C
 
 fields/UniformDimensionedFields/uniformDimensionedFields.C
 fields/cloud/cloud.C
diff --git a/src/OpenFOAM/meshes/bandCompression/bandCompression.C b/src/OpenFOAM/meshes/bandCompression/bandCompression.C
index 5c31a2121d6128cadff0512f4c4a2cb05b0353db..cec9dc9c6c717f30db9d84c8dd5366302411b6a8 100644
--- a/src/OpenFOAM/meshes/bandCompression/bandCompression.C
+++ b/src/OpenFOAM/meshes/bandCompression/bandCompression.C
@@ -26,6 +26,7 @@ Description
     matrix is reduced. The algorithm uses a simple search through the
     neighbour list
 
+    See http://en.wikipedia.org/wiki/Cuthill-McKee_algorithm
 
 \*---------------------------------------------------------------------------*/
 
diff --git a/src/OpenFOAM/meshes/bandCompression/bandCompression.H b/src/OpenFOAM/meshes/bandCompression/bandCompression.H
index 25e863fd472f0b1c3f7b681efb5fe7408780ad14..8cbad9fbded857b79d60fa7927a5e44ca9466a4a 100644
--- a/src/OpenFOAM/meshes/bandCompression/bandCompression.H
+++ b/src/OpenFOAM/meshes/bandCompression/bandCompression.H
@@ -46,6 +46,8 @@ namespace Foam
 
 //- Renumbers the addressing to reduce the band of the matrix.
 //  The algorithm uses a simple search through the neighbour list
+//  Returns the order in which the cells need to be visited (i.e. ordered to
+//  original)
 labelList bandCompression(const labelListList& addressing);
 
 } // End namespace Foam
diff --git a/src/OpenFOAM/meshes/meshTools/mergePoints.C b/src/OpenFOAM/meshes/meshTools/mergePoints.C
index 6ecb53352722bd0cd5af54832b3d4c6a2917bdc6..954c6aa86e9bb73d3557358ed7c0fc186da567ec 100644
--- a/src/OpenFOAM/meshes/meshTools/mergePoints.C
+++ b/src/OpenFOAM/meshes/meshTools/mergePoints.C
@@ -23,25 +23,25 @@ License
 
 \*---------------------------------------------------------------------------*/
 
-#include "mergePoints.H"
-#include "SortableList.H"
 #include "ListOps.H"
+#include "point.H"
+#include "Field.H"
 
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
-bool Foam::mergePoints
+template<class Type>
+Foam::label Foam::mergePoints
 (
-    const UList<point>& points,
+    const UList<Type>& points,
     const scalar mergeTol,
     const bool verbose,
     labelList& pointMap,
-    List<point>& newPoints,
-    const point& origin
+    const Type& origin
 )
 {
-    point compareOrigin = origin;
+    Type compareOrigin = origin;
 
-    if (origin == point(VGREAT, VGREAT, VGREAT))
+    if (origin == Type::max)
     {
         if (points.size())
         {
@@ -53,12 +53,9 @@ bool Foam::mergePoints
     pointMap.setSize(points.size());
     pointMap = -1;
 
-    // Storage for merged points
-    newPoints.setSize(points.size());
-
     if (points.empty())
     {
-        return false;
+        return points.size();
     }
 
     // We're comparing distance squared to origin first.
@@ -70,33 +67,56 @@ bool Foam::mergePoints
     //     x^2+y^2+z^2 + 2*mergeTol*(x+z+y) + mergeTol^2*...
     // so the difference will be 2*mergeTol*(x+y+z)
 
-    const scalar mergeTolSqr = sqr(mergeTol);
+    const scalar mergeTolSqr = Foam::sqr(scalar(mergeTol));
 
     // Sort points by magSqr
-    const pointField d(points - compareOrigin);
-    SortableList<scalar> sortedMagSqr(magSqr(d));
-    scalarField sortedTol(points.size());
-    forAll(sortedMagSqr.indices(), sortI)
+    const Field<Type> d(points - compareOrigin);
+
+    List<scalar> magSqrD(d.size());
+    forAll(d, pointI)
     {
-        const point& pt = d[sortedMagSqr.indices()[sortI]];
-        sortedTol[sortI] = 2*mergeTol*(mag(pt.x())+mag(pt.y())+mag(pt.z()));
+        magSqrD[pointI] = magSqr(d[pointI]);
     }
+    labelList order;
+    sortedOrder(magSqrD, order);
+
+
+    Field<scalar> sortedTol(points.size());
+    forAll(order, sortI)
+    {
+        label pointI = order[sortI];
 
-    bool hasMerged = false;
+        // Convert to scalar precision
+        const point pt
+        (
+            scalar(d[pointI].x()),
+            scalar(d[pointI].y()),
+            scalar(d[pointI].z())
+        );
+        sortedTol[sortI] = 2*mergeTol*(mag(pt.x())+mag(pt.y())+mag(pt.z()));
+    }
 
     label newPointI = 0;
 
 
     // Handle 0th point separately (is always unique)
-    label pointI = sortedMagSqr.indices()[0];
-    pointMap[pointI] = newPointI;
-    newPoints[newPointI++] = points[pointI];
+    label pointI = order[0];
+    pointMap[pointI] = newPointI++;
 
 
-    for (label sortI = 1; sortI < sortedMagSqr.size(); sortI++)
+    for (label sortI = 1; sortI < order.size(); sortI++)
     {
         // Get original point index
-        label pointI = sortedMagSqr.indices()[sortI];
+        label pointI = order[sortI];
+        const scalar mag2 = magSqrD[order[sortI]];
+        // Convert to scalar precision
+        const point pt
+        (
+            scalar(points[pointI].x()),
+            scalar(points[pointI].y()),
+            scalar(points[pointI].z())
+        );
+
 
         // Compare to previous points to find equal one.
         label equalPointI = -1;
@@ -105,17 +125,19 @@ bool Foam::mergePoints
         (
             label prevSortI = sortI - 1;
             prevSortI >= 0
-         && mag
-            (
-                sortedMagSqr[prevSortI]
-             -  sortedMagSqr[sortI]
-            ) <= sortedTol[sortI];
+         && (mag(magSqrD[order[prevSortI]] - mag2) <= sortedTol[sortI]);
             prevSortI--
         )
         {
-            label prevPointI = sortedMagSqr.indices()[prevSortI];
+            label prevPointI = order[prevSortI];
+            const point prevPt
+            (
+                scalar(points[prevPointI].x()),
+                scalar(points[prevPointI].y()),
+                scalar(points[prevPointI].z())
+            );
 
-            if (magSqr(points[pointI] - points[prevPointI]) <= mergeTolSqr)
+            if (magSqr(pt - prevPt) <= mergeTolSqr)
             {
                 // Found match.
                 equalPointI = prevPointI;
@@ -130,8 +152,6 @@ bool Foam::mergePoints
             // Same coordinate as equalPointI. Map to same new point.
             pointMap[pointI] = pointMap[equalPointI];
 
-            hasMerged = true;
-
             if (verbose)
             {
                 Pout<< "Foam::mergePoints : Merging points "
@@ -144,14 +164,41 @@ bool Foam::mergePoints
         else
         {
             // Differs. Store new point.
-            pointMap[pointI] = newPointI;
-            newPoints[newPointI++] = points[pointI];
+            pointMap[pointI] = newPointI++;
         }
     }
 
-    newPoints.setSize(newPointI);
+    return newPointI;
+}
+
+
+template<class Type>
+bool Foam::mergePoints
+(
+    const UList<Type>& points,
+    const scalar mergeTol,
+    const bool verbose,
+    labelList& pointMap,
+    List<Type>& newPoints,
+    const Type& origin = Type::zero
+)
+{
+    label nUnique = mergePoints
+    (
+        points,
+        mergeTol,
+        verbose,
+        pointMap,
+        origin
+    );
+
+    newPoints.setSize(nUnique);
+    forAll(pointMap, pointI)
+    {
+        newPoints[pointMap[pointI]] = points[pointI];
+    }
 
-    return hasMerged;
+    return (nUnique != points.size());
 }
 
 
diff --git a/src/OpenFOAM/meshes/meshTools/mergePoints.H b/src/OpenFOAM/meshes/meshTools/mergePoints.H
index d6a1bb17369e933e1d1e9607c5454ed61a99a765..92f1f1071f3eea0c7ef134b1ba8180cac66a0364 100644
--- a/src/OpenFOAM/meshes/meshTools/mergePoints.H
+++ b/src/OpenFOAM/meshes/meshTools/mergePoints.H
@@ -32,8 +32,8 @@ SourceFiles
 #ifndef mergePoints_H
 #define mergePoints_H
 
-#include "scalarField.H"
-#include "pointField.H"
+#include "scalar.H"
+#include "labelList.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
@@ -44,23 +44,41 @@ namespace Foam
                            Function mergePoints Declaration
 \*---------------------------------------------------------------------------*/
 
-//- Sort & merge points. All points closer than/equal mergeTol get merged.
-//  Outputs the new unique points and a map from old to new. Returns
-//  true if anything merged, false otherwise.
+//- Sorts and merges points. All points closer than/equal mergeTol get merged.
+//  Returns the number of unique points and a map from old to new.
+template<class Type>
+label mergePoints
+(
+    const UList<Type>& points,
+    const scalar mergeTol,
+    const bool verbose,
+    labelList& pointMap,
+    const Type& origin = Type::zero
+);
+
+//- Sorts and merges points. Determines new points. Returns true if anything
+//  merged (though newPoints still sorted even if not merged).
+template<class Type>
 bool mergePoints
 (
-    const UList<point>& points,
+    const UList<Type>& points,
     const scalar mergeTol,
     const bool verbose,
     labelList& pointMap,
-    List<point>& newPoints,
-    const point& origin = point::zero
+    List<Type>& newPoints,
+    const Type& origin = Type::zero
 );
 
 } // End namespace Foam
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
+#ifdef NoRepository
+#   include "mergePoints.C"
+#endif
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
 #endif
 
 // ************************************************************************* //
diff --git a/src/OpenFOAM/meshes/polyMesh/globalMeshData/globalIndex.C b/src/OpenFOAM/meshes/polyMesh/globalMeshData/globalIndex.C
index a432ae889b3d8427593eca6e618b3ee26fb9ef4b..8ecd6ab8f98cee3891b2794f87d663528b0230b3 100644
--- a/src/OpenFOAM/meshes/polyMesh/globalMeshData/globalIndex.C
+++ b/src/OpenFOAM/meshes/polyMesh/globalMeshData/globalIndex.C
@@ -27,14 +27,22 @@ License
 
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
-Foam::globalIndex::globalIndex(const label localSize, const int tag)
+Foam::globalIndex::globalIndex
+(
+    const label localSize,
+    const int tag,
+    const bool parallel
+)
 :
     offsets_(Pstream::nProcs()+1)
 {
-    labelList localSizes(Pstream::nProcs());
+    labelList localSizes(Pstream::nProcs(), 0);
     localSizes[Pstream::myProcNo()] = localSize;
-    Pstream::gatherList(localSizes, tag);
-    Pstream::scatterList(localSizes, tag);
+    if (parallel)
+    {
+        Pstream::gatherList(localSizes, tag);
+        Pstream::scatterList(localSizes, tag);
+    }
 
     label offset = 0;
     offsets_[0] = 0;
diff --git a/src/OpenFOAM/meshes/polyMesh/globalMeshData/globalIndex.H b/src/OpenFOAM/meshes/polyMesh/globalMeshData/globalIndex.H
index 1bd83470508c40cb5283167a266612c01c7eacba..c712066f4a18218ec320e7c0b33c5acbd1449371 100644
--- a/src/OpenFOAM/meshes/polyMesh/globalMeshData/globalIndex.H
+++ b/src/OpenFOAM/meshes/polyMesh/globalMeshData/globalIndex.H
@@ -72,7 +72,12 @@ public:
     // Constructors
 
         //- Construct from local max size
-        globalIndex(const label localSize, const int tag = Pstream::msgType());
+        globalIndex
+        (
+            const label localSize,
+            const int tag = Pstream::msgType(),
+            const bool parallel = true              // use parallel comms
+        );
 
         //- Construct from Istream
         globalIndex(Istream& is);
diff --git a/src/OpenFOAM/meshes/polyMesh/polyBoundaryMesh/polyBoundaryMesh.H b/src/OpenFOAM/meshes/polyMesh/polyBoundaryMesh/polyBoundaryMesh.H
index 211d9148e941d6a6a799f149265dcecaadea0dae..62d6f4a5e1e8b6d2013dcc459cc3c657caf61c61 100644
--- a/src/OpenFOAM/meshes/polyMesh/polyBoundaryMesh/polyBoundaryMesh.H
+++ b/src/OpenFOAM/meshes/polyMesh/polyBoundaryMesh/polyBoundaryMesh.H
@@ -159,7 +159,7 @@ public:
         labelList findIndices
         (
             const keyType&,
-            const bool usePatchGroups = false
+            const bool usePatchGroups = true
         ) const;
 
         //- Return patch index for the first match, return -1 if not found
@@ -184,7 +184,7 @@ public:
         (
             const UList<wordRe>& patchNames,
             const bool warnNotFound = true,
-            const bool usePatchGroups = false
+            const bool usePatchGroups = true
         ) const;
 
         //- Check whether all procs have all patches and in same order. Return
diff --git a/src/OpenFOAM/primitives/Vector/floatVector/floatVector.C b/src/OpenFOAM/primitives/Vector/floatVector/floatVector.C
new file mode 100644
index 0000000000000000000000000000000000000000..d88ac70f1f4afc6e25a6a7694155a671d48f7c66
--- /dev/null
+++ b/src/OpenFOAM/primitives/Vector/floatVector/floatVector.C
@@ -0,0 +1,70 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
+     \\/     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/>.
+
+Description
+    Vector of floats.
+
+\*---------------------------------------------------------------------------*/
+
+#include "floatVector.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+template<>
+const char* const floatVector::typeName = "floatVector";
+
+template<>
+const char* floatVector::componentNames[] = {"x", "y", "z"};
+
+template<>
+const floatVector floatVector::zero(0, 0, 0);
+
+template<>
+const floatVector floatVector::one(1, 1, 1);
+
+template<>
+const floatVector floatVector::max
+(
+    floatScalarVGREAT,
+    floatScalarVGREAT,
+    floatScalarVGREAT
+);
+
+template<>
+const floatVector floatVector::min
+(
+    -floatScalarVGREAT,
+    -floatScalarVGREAT,
+    -floatScalarVGREAT
+);
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/primitives/Vector/floatVector/floatVector.H b/src/OpenFOAM/primitives/Vector/floatVector/floatVector.H
new file mode 100644
index 0000000000000000000000000000000000000000..438adc17765c911b1a1c4a233a0ddc0d436d8538
--- /dev/null
+++ b/src/OpenFOAM/primitives/Vector/floatVector/floatVector.H
@@ -0,0 +1,64 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
+     \\/     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/>.
+
+Typedef
+    Foam::floatVector
+
+Description
+    A float version of vector
+
+SourceFiles
+    floatVector.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef floatVector_H
+#define floatVector_H
+
+#include "Vector.H"
+#include "contiguous.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+typedef Vector<float> floatVector;
+
+
+//- Data associated with floatVector type are contiguous
+template<>
+inline bool contiguous<floatVector>() {return true;}
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/dynamicMesh/fvMeshDistribute/fvMeshDistribute.C b/src/dynamicMesh/fvMeshDistribute/fvMeshDistribute.C
index 10ac331363c8f4217b4b382b075ac2f722b846e7..3ce3d4a51bda1f701dbd9270588e6cdaadcd8095 100644
--- a/src/dynamicMesh/fvMeshDistribute/fvMeshDistribute.C
+++ b/src/dynamicMesh/fvMeshDistribute/fvMeshDistribute.C
@@ -36,7 +36,6 @@ License
 #include "removeCells.H"
 #include "polyModifyFace.H"
 #include "polyRemovePoint.H"
-#include "mergePoints.H"
 #include "mapDistributePolyMesh.H"
 #include "surfaceFields.H"
 #include "syncTools.H"
diff --git a/src/dynamicMesh/polyMeshAdder/polyMeshAdder.C b/src/dynamicMesh/polyMeshAdder/polyMeshAdder.C
index c2cde770f2e5807024066cf86c6b75af1f9b98f2..348f61db2bf8f7d09514e0d70fe3f5cad5ac42cb 100644
--- a/src/dynamicMesh/polyMeshAdder/polyMeshAdder.C
+++ b/src/dynamicMesh/polyMeshAdder/polyMeshAdder.C
@@ -1859,24 +1859,22 @@ Foam::Map<Foam::label> Foam::polyMeshAdder::findSharedPoints
             );
 
             labelList toMergedPoints;
-            pointField mergedPoints;
-            bool hasMerged = Foam::mergePoints
+            label nUnique = Foam::mergePoints
             (
                 connectedPoints,
                 mergeDist,
                 false,
-                toMergedPoints,
-                mergedPoints
+                toMergedPoints
             );
 
-            if (hasMerged)
+            if (nUnique < connectedPoints.size())
             {
                 // Invert toMergedPoints
                 const labelListList mergeSets
                 (
                     invertOneToMany
                     (
-                        mergedPoints.size(),
+                        nUnique,
                         toMergedPoints
                     )
                 );
@@ -1919,8 +1917,7 @@ Foam::Map<Foam::label> Foam::polyMeshAdder::findSharedPoints
 
     //- Old: geometric merging. Causes problems for two close shared points.
     //labelList sharedToMerged;
-    //pointField mergedPoints;
-    //bool hasMerged = Foam::mergePoints
+    //label nUnique = Foam::mergePoints
     //(
     //    pointField
     //    (
@@ -1929,8 +1926,7 @@ Foam::Map<Foam::label> Foam::polyMeshAdder::findSharedPoints
     //    ),
     //    mergeDist,
     //    false,
-    //    sharedToMerged,
-    //    mergedPoints
+    //    sharedToMerged
     //);
     //
     //// Find out which sets of points get merged and create a map from
@@ -1938,7 +1934,7 @@ Foam::Map<Foam::label> Foam::polyMeshAdder::findSharedPoints
     //
     //Map<label> pointToMaster(10*sharedToMerged.size());
     //
-    //if (hasMerged)
+    //if (nUnique < sharedPointLabels.size())
     //{
     //    labelListList mergeSets
     //    (
diff --git a/src/dynamicMesh/polyTopoChange/polyTopoChange/addPatchCellLayer.C b/src/dynamicMesh/polyTopoChange/polyTopoChange/addPatchCellLayer.C
index 01e8c984ec0497a34495ae2e87e1eb0adb7c050b..7f11fb638d1dfcea7b7181169a528bb557c73e3c 100644
--- a/src/dynamicMesh/polyTopoChange/polyTopoChange/addPatchCellLayer.C
+++ b/src/dynamicMesh/polyTopoChange/polyTopoChange/addPatchCellLayer.C
@@ -34,7 +34,6 @@ License
 #include "polyModifyFace.H"
 #include "polyAddCell.H"
 #include "globalIndex.H"
-#include "dummyTransform.H"
 
 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
 
diff --git a/src/finiteVolume/fields/fvPatchFields/derived/codedMixed/codedMixedFvPatchField.H b/src/finiteVolume/fields/fvPatchFields/derived/codedMixed/codedMixedFvPatchField.H
index 40038efeed18ae3d528e3d53f8c2816760fd8cd2..2b7c97478ecfbe204648d2d5ee897740797f0b8c 100644
--- a/src/finiteVolume/fields/fvPatchFields/derived/codedMixed/codedMixedFvPatchField.H
+++ b/src/finiteVolume/fields/fvPatchFields/derived/codedMixed/codedMixedFvPatchField.H
@@ -38,7 +38,9 @@ Description
 
             code
             #{
-                operator==(min(10, 0.1*this->db().time().value()));
+                this->refValue() = min(10, 0.1*this->db().time().value());
+                this->refGrad() = vector::zero;
+                this->valueFraction() = 1.0;
             #};
 
             //codeInclude
@@ -58,13 +60,15 @@ Description
     which would have a corresponding entry
 
     \verbatim
-    rampedMixed
-    {
-        code
-        #{
-            operator==(min(10, 0.1*this->db().time().value()));
-        #};
-    }
+        rampedMixed
+        {
+            code
+            #{
+                this->refValue() = min(10, 0.1*this->db().time().value());
+                this->refGrad() = vector::zero;
+                this->valueFraction() = 1.0;
+            #};
+        }
     \endverbatim
 
 SeeAlso
diff --git a/src/mesh/autoMesh/autoHexMesh/autoHexMeshDriver/autoLayerDriver.C b/src/mesh/autoMesh/autoHexMesh/autoHexMeshDriver/autoLayerDriver.C
index f442f72827f435ebd68e977fea872bf4c5fd6ce2..67d4fec174ed7203a3ba8735cb68a387d71289e8 100644
--- a/src/mesh/autoMesh/autoHexMesh/autoHexMeshDriver/autoLayerDriver.C
+++ b/src/mesh/autoMesh/autoHexMesh/autoHexMeshDriver/autoLayerDriver.C
@@ -47,6 +47,7 @@ Description
 #include "IOmanip.H"
 #include "globalIndex.H"
 #include "DynamicField.H"
+#include "PatchTools.H"
 
 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
 
@@ -369,7 +370,16 @@ void Foam::autoLayerDriver::handleFeatureAngle
         autoPtr<OFstream> str;
         if (debug)
         {
-            str.reset(new OFstream(mesh.time().path()/"featureEdges.obj"));
+            str.reset
+            (
+                new OFstream
+                (
+                    mesh.time().path()
+                  / "featureEdges_"
+                  + meshRefiner_.timeName()
+                  + ".obj"
+                )
+            );
             Info<< "Writing feature edges to " << str().name() << endl;
         }
 
@@ -1220,49 +1230,19 @@ void Foam::autoLayerDriver::getPatchDisplacement
     const vectorField& faceNormals = pp.faceNormals();
     const labelListList& pointFaces = pp.pointFaces();
     const pointField& localPoints = pp.localPoints();
-    const labelList& meshPoints = pp.meshPoints();
 
     // Determine pointNormal
     // ~~~~~~~~~~~~~~~~~~~~~
 
-    pointField pointNormals(pp.nPoints(), vector::zero);
-    {
-        labelList nPointFaces(pp.nPoints(), 0);
-
-        forAll(faceNormals, faceI)
-        {
-            const face& f = pp.localFaces()[faceI];
-
-            forAll(f, fp)
-            {
-                pointNormals[f[fp]] += faceNormals[faceI];
-                nPointFaces[f[fp]] ++;
-            }
-        }
-
-        syncTools::syncPointList
-        (
-            mesh,
-            meshPoints,
-            pointNormals,
-            plusEqOp<vector>(),
-            vector::zero        // null value
-        );
-
-        syncTools::syncPointList
+    pointField pointNormals
+    (
+        PatchTools::pointNormals
         (
             mesh,
-            meshPoints,
-            nPointFaces,
-            plusEqOp<label>(),
-            label(0)            // null value
-        );
-
-        forAll(pointNormals, i)
-        {
-            pointNormals[i] /= nPointFaces[i];
-        }
-    }
+            pp,
+            pp.addressing()
+        )
+    );
 
 
     // Determine local length scale on patch
@@ -2266,7 +2246,11 @@ void Foam::autoLayerDriver::addLayers
     {
         const_cast<Time&>(mesh.time())++;
         Info<< "Writing baffled mesh to " << meshRefiner_.timeName() << endl;
-        mesh.write();
+        meshRefiner_.write
+        (
+            debug,
+            mesh.time().path()/meshRefiner_.timeName()
+        );
     }
 
 
@@ -2732,7 +2716,7 @@ void Foam::autoLayerDriver::addLayers
         {
             dumpDisplacement
             (
-                mesh.time().path()/"layer",
+                mesh.time().path()/"layer_" + meshRefiner_.timeName(),
                 pp(),
                 patchDisp,
                 extrudeStatus
@@ -2744,7 +2728,11 @@ void Foam::autoLayerDriver::addLayers
             // See comment in autoSnapDriver why we should not remove meshPhi
             // using mesh.clearPout().
 
-            mesh.write();
+            meshRefiner_.write
+            (
+                debug,
+                mesh.time().path()/meshRefiner_.timeName()
+            );
         }
 
 
diff --git a/src/mesh/autoMesh/autoHexMesh/autoHexMeshDriver/autoLayerDriverShrink.C b/src/mesh/autoMesh/autoHexMesh/autoHexMeshDriver/autoLayerDriverShrink.C
index 614fd204b3c3b78aaed0aa917b6b08c37d133f81..5731562575b50d515d75b641459f4f1ddf200cab 100644
--- a/src/mesh/autoMesh/autoHexMesh/autoHexMeshDriver/autoLayerDriverShrink.C
+++ b/src/mesh/autoMesh/autoHexMesh/autoHexMeshDriver/autoLayerDriverShrink.C
@@ -33,6 +33,9 @@ Description
 #include "motionSmoother.H"
 #include "pointData.H"
 #include "PointEdgeWave.H"
+#include "OFstream.H"
+#include "meshTools.H"
+#include "PatchTools.H"
 
 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
 
@@ -334,11 +337,25 @@ bool Foam::autoLayerDriver::isMaxEdge
         return false;
     }
 
-    v0 /= magV0;
-    v1 /= magV1;
 
-    // Test angle.
-    if ((v0 & v1) < minCos)
+    //- Detect based on vector to nearest point differing for both endpoints
+    //v0 /= magV0;
+    //v1 /= magV1;
+    //
+    //// Test angle.
+    //if ((v0 & v1) < minCos)
+    //{
+    //    return true;
+    //}
+    //else
+    //{
+    //    return false;
+    //}
+
+    //- Detect based on extrusion vector differing for both endpoints
+    //  the idea is that e.g. a sawtooth wall can still be extruded
+    //  successfully as long as it is done all to the same direction.
+    if ((pointWallDist[e[0]].v() & pointWallDist[e[1]].v()) < minCos)
     {
         return true;
     }
@@ -670,7 +687,6 @@ void Foam::autoLayerDriver::medialAxisSmoothingInfo
     const pointField& points = mesh.points();
 
     const indirectPrimitivePatch& pp = meshMover.patch();
-    const vectorField& faceNormals = pp.faceNormals();
     const labelList& meshPoints = pp.meshPoints();
 
     // Predetermine mesh edges
@@ -700,44 +716,15 @@ void Foam::autoLayerDriver::medialAxisSmoothingInfo
     // Determine pointNormal
     // ~~~~~~~~~~~~~~~~~~~~~
 
-    pointField pointNormals(pp.nPoints(), vector::zero);
-    {
-        labelList nPointFaces(pp.nPoints(), 0);
-
-        forAll(faceNormals, faceI)
-        {
-            const face& f = pp.localFaces()[faceI];
-
-            forAll(f, fp)
-            {
-                pointNormals[f[fp]] += faceNormals[faceI];
-                nPointFaces[f[fp]] ++;
-            }
-        }
-
-        syncTools::syncPointList
-        (
-            mesh,
-            meshPoints,
-            pointNormals,
-            plusEqOp<vector>(),
-            vector::zero        // null value
-        );
-
-        syncTools::syncPointList
+    pointField pointNormals
+    (
+        PatchTools::pointNormals
         (
             mesh,
-            meshPoints,
-            nPointFaces,
-            plusEqOp<label>(),
-            label(0)            // null value
-        );
-
-        forAll(pointNormals, i)
-        {
-            pointNormals[i] /= nPointFaces[i];
-        }
-    }
+            pp,
+            pp.addressing()
+        )
+    );
 
     // Smooth patch normal vectors
     smoothPatchNormals
@@ -1012,6 +999,26 @@ void Foam::autoLayerDriver::shrinkMeshMedialDistance
     label numThicknessRatioExclude = 0;
 
     // reduce thickness where thickness/medial axis distance large
+    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    autoPtr<OFstream> str;
+    label vertI = 0;
+    if (debug)
+    {
+        str.reset
+        (
+            new OFstream
+            (
+                mesh.time().path()
+              / "thicknessRatioExcludePoints_"
+              + meshRefiner_.timeName()
+              + ".obj"
+            )
+        );
+        Info<< "Writing points with too large a extrusion distance to "
+            << str().name() << endl;
+    }
+
     forAll(meshPoints, patchPointI)
     {
         if (extrudeStatus[patchPointI] != NOEXTRUDE)
@@ -1025,6 +1032,20 @@ void Foam::autoLayerDriver::shrinkMeshMedialDistance
             if (thicknessRatio > maxThicknessToMedialRatio)
             {
                 // Truncate thickness.
+                if (debug)
+                {
+                    Pout<< "truncating displacement at "
+                        << mesh.points()[pointI]
+                        << " from " << thickness[patchPointI]
+                        << " to "
+                        <<  0.5
+                           *(
+                                minThickness[patchPointI]
+                               +thickness[patchPointI]
+                            )
+                        << endl;
+                }
+
                 thickness[patchPointI] =
                     0.5*(minThickness[patchPointI]+thickness[patchPointI]);
 
@@ -1033,6 +1054,16 @@ void Foam::autoLayerDriver::shrinkMeshMedialDistance
                   * patchDisp[patchPointI]
                   / (mag(patchDisp[patchPointI]) + VSMALL);
                 numThicknessRatioExclude++;
+
+                if (str.valid())
+                {
+                    const point& pt = mesh.points()[pointI];
+                    meshTools::writeOBJ(str(), pt);
+                    vertI++;
+                    meshTools::writeOBJ(str(), pt+patchDisp[patchPointI]);
+                    vertI++;
+                    str()<< "l " << vertI-1 << ' ' << vertI << nl;
+                }
             }
         }
     }
@@ -1121,6 +1152,31 @@ void Foam::autoLayerDriver::shrinkMeshMedialDistance
             *dispVec[pointI];
     }
 
+    if (debug)
+    {
+        const_cast<Time&>(mesh.time())++;
+        Info<< "Writing wanted-displacement mesh (possibly illegal) to "
+            << meshRefiner_.timeName() << endl;
+        pointField oldPoints(mesh.points());
+        meshMover.movePoints
+        (
+            (
+                mesh.points()
+         +      (
+                    meshMover.scale().internalField()
+                  * displacement.internalField()
+                )
+            )()
+        );
+        meshRefiner_.write
+        (
+            debug,
+            mesh.time().path()/meshRefiner_.timeName()
+        );
+        meshMover.movePoints(oldPoints);
+    }
+
+
     // Current faces to check. Gets modified in meshMover.scaleMesh
     labelList checkFaces(identity(mesh.nFaces()));
 
diff --git a/src/mesh/autoMesh/autoHexMesh/autoHexMeshDriver/autoSnapDriver.C b/src/mesh/autoMesh/autoHexMesh/autoHexMeshDriver/autoSnapDriver.C
index dcb2c6cca5dc9d4af4b7aa0786b5aa7c6c650698..ea29efbb8454bcc368960ac1887ec7648eb9937b 100644
--- a/src/mesh/autoMesh/autoHexMesh/autoHexMeshDriver/autoSnapDriver.C
+++ b/src/mesh/autoMesh/autoHexMesh/autoHexMeshDriver/autoSnapDriver.C
@@ -63,27 +63,26 @@ Foam::label Foam::autoSnapDriver::getCollocatedPoints
 )
 {
     labelList pointMap;
-    pointField newPoints;
-    bool hasMerged = mergePoints
+    label nUnique = mergePoints
     (
         points,                         // points
         tol,                            // mergeTol
         false,                          // verbose
-        pointMap,
-        newPoints
+        pointMap
     );
+    bool hasMerged = (nUnique < points.size());
 
     if (!returnReduce(hasMerged, orOp<bool>()))
     {
         return 0;
     }
 
-    // Determine which newPoints are referenced more than once
+    // Determine which merged points are referenced more than once
     label nCollocated = 0;
 
     // Per old point the newPoint. Or -1 (not set yet) or -2 (already seen
     // twice)
-    labelList firstOldPoint(newPoints.size(), -1);
+    labelList firstOldPoint(nUnique, -1);
     forAll(pointMap, oldPointI)
     {
         label newPointI = pointMap[oldPointI];
diff --git a/src/mesh/autoMesh/autoHexMesh/meshRefinement/meshRefinementProblemCells.C b/src/mesh/autoMesh/autoHexMesh/meshRefinement/meshRefinementProblemCells.C
index 1b1b3ba39677b50031986c50821e3ac9a26001ec..296029b7d517b2ad61c66988672bd58ca0be66f8 100644
--- a/src/mesh/autoMesh/autoHexMesh/meshRefinement/meshRefinementProblemCells.C
+++ b/src/mesh/autoMesh/autoHexMesh/meshRefinement/meshRefinementProblemCells.C
@@ -31,7 +31,6 @@ License
 #include "pointSet.H"
 #include "faceSet.H"
 #include "indirectPrimitivePatch.H"
-#include "OFstream.H"
 #include "cellSet.H"
 #include "searchableSurfaces.H"
 #include "polyMeshGeometry.H"
diff --git a/src/meshTools/triSurface/triSurfaceTools/triSurfaceTools.C b/src/meshTools/triSurface/triSurfaceTools/triSurfaceTools.C
index 451d00c03d56060f2bfee18f77529cfad4e9580b..022d6fb8218149404dcc72e150693fc36de1de53 100644
--- a/src/meshTools/triSurface/triSurfaceTools/triSurfaceTools.C
+++ b/src/meshTools/triSurface/triSurfaceTools/triSurfaceTools.C
@@ -2096,7 +2096,8 @@ Foam::triSurface Foam::triSurfaceTools::mergePoints
         (
             newTriangles,
             surf.patches(),
-            newPoints
+            newPoints,
+            true                //reuse storage
         );
     }
     else
diff --git a/src/parallel/decompose/decompositionMethods/decompositionMethod/decompositionMethod.C b/src/parallel/decompose/decompositionMethods/decompositionMethod/decompositionMethod.C
index 1808fc84ab5b554a0af4aca1008d712de3586cb0..363000bad676bb4b17168ab4056093b6264ee71c 100644
--- a/src/parallel/decompose/decompositionMethods/decompositionMethod/decompositionMethod.C
+++ b/src/parallel/decompose/decompositionMethods/decompositionMethod/decompositionMethod.C
@@ -96,6 +96,7 @@ Foam::labelList Foam::decompositionMethod::decompose
         mesh,
         fineToCoarse,
         coarsePoints.size(),
+        true,                       // use global cell labels
         coarseCellCells
     );
 
@@ -158,6 +159,7 @@ void Foam::decompositionMethod::calcCellCells
     const polyMesh& mesh,
     const labelList& agglom,
     const label nCoarse,
+    const bool parallel,
     CompactListList<label>& cellCells
 )
 {
@@ -169,7 +171,7 @@ void Foam::decompositionMethod::calcCellCells
     // Create global cell numbers
     // ~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-    globalIndex globalAgglom(nCoarse);
+    globalIndex globalAgglom(nCoarse, Pstream::msgType(), parallel);
 
 
     // Get agglomerate owner on other side of coupled faces
@@ -181,7 +183,7 @@ void Foam::decompositionMethod::calcCellCells
     {
         const polyPatch& pp = patches[patchI];
 
-        if (pp.coupled())
+        if (pp.coupled() && (parallel || !isA<processorPolyPatch>(pp)))
         {
             label faceI = pp.start();
             label bFaceI = pp.start() - mesh.nInternalFaces();
@@ -203,77 +205,6 @@ void Foam::decompositionMethod::calcCellCells
     syncTools::swapBoundaryFaceList(mesh, globalNeighbour);
 
 
-
-    //// Determine the cellCells (in agglomeration numbering) on coupled faces
-    //// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-    //
-    //labelListList globalCellCells(mesh.nFaces()-mesh.nInternalFaces());
-    //
-    //// Current set of face neighbours for the current cell
-    //labelHashSet cCells;
-    //
-    //forAll(patches, patchI)
-    //{
-    //    const polyPatch& pp = patches[patchI];
-    //
-    //    if (pp.coupled())
-    //    {
-    //        label faceI = pp.start();
-    //        label bFaceI = pp.start() - mesh.nInternalFaces();
-    //
-    //        forAll(pp, i)
-    //        {
-    //            label cellI = faceOwner[faceI];
-    //            label globalCellI = globalAgglom.toGlobal(agglom[cellI]);
-    //
-    //            // First check if agglomerated across coupled patches at all
-    //            // so we don't use memory if not needed
-    //            if (globalNeighbour[bFaceI] == globalCellI)
-    //            {
-    //                cCells.clear();
-    //
-    //                const cell& cFaces = mesh.cells()[cellI];
-    //
-    //                forAll(cFaces, i)
-    //                {
-    //                    if (mesh.isInternalFace(cFaces[i]))
-    //                    {
-    //                        label otherCellI = faceOwner[cFaces[i]];
-    //                        if (otherCellI == cellI)
-    //                        {
-    //                            otherCellI = faceNeighbour[cFaces[i]];
-    //                        }
-    //
-    //                        cCells.insert
-    //                        (
-    //                            globalAgglom.toGlobal
-    //                            (
-    //                                agglom[otherCellI]
-    //                            )
-    //                        );
-    //                    }
-    //                }
-    //                globalCellCells[bFaceI] = cCells.toc();
-    //            }
-    //
-    //            bFaceI++;
-    //            faceI++;
-    //        }
-    //    }
-    //}
-    //
-    //// Get the cell on the other side of coupled patches
-    //syncTools::syncBoundaryFaceList
-    //(
-    //    mesh,
-    //    globalCellCells,
-    //    eqOp<labelList>(),
-    //    dummyTransform()
-    //);
-
-
-
-
     // Count number of faces (internal + coupled)
     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -293,7 +224,7 @@ void Foam::decompositionMethod::calcCellCells
     {
         const polyPatch& pp = patches[patchI];
 
-        if (pp.coupled())
+        if (pp.coupled() && (parallel || !isA<processorPolyPatch>(pp)))
         {
             label faceI = pp.start();
             label bFaceI = pp.start()-mesh.nInternalFaces();
@@ -302,18 +233,6 @@ void Foam::decompositionMethod::calcCellCells
             {
                 label own = agglom[faceOwner[faceI]];
 
-                //const labelList& cCells = globalCellCells[bFaceI];
-                //
-                //forAll(cCells, i)
-                //{
-                //    label globalNei = cCells[i];
-                //
-                //    // Allow only processor-local agglomeration
-                //    if (globalAgglom.isLocal(globalNei))
-                //    {
-                //        nFacesPerCell[own]++;
-                //    }
-                //}
                 label globalNei = globalNeighbour[bFaceI];
                 if
                 (
@@ -365,18 +284,6 @@ void Foam::decompositionMethod::calcCellCells
             {
                 label own = agglom[faceOwner[faceI]];
 
-                //const labelList& cCells = globalCellCells[bFaceI];
-                //
-                //forAll(cCells, i)
-                //{
-                //    label globalNei = cCells[i];
-                //
-                //    // Allow only processor-local agglomeration
-                //    if (globalAgglom.isLocal(globalNei))
-                //    {
-                //        m[offsets[own] + nFacesPerCell[own]++] = globalNei;
-                //    }
-                //}
                 label globalNei = globalNeighbour[bFaceI];
                 if
                 (
diff --git a/src/parallel/decompose/decompositionMethods/decompositionMethod/decompositionMethod.H b/src/parallel/decompose/decompositionMethods/decompositionMethod/decompositionMethod.H
index b81119fb0b204b2d8e23c697788c59819d37c83e..9e58cd5ddc9015f5f07a54da1557aef596181c79 100644
--- a/src/parallel/decompose/decompositionMethods/decompositionMethod/decompositionMethod.H
+++ b/src/parallel/decompose/decompositionMethods/decompositionMethod/decompositionMethod.H
@@ -57,15 +57,6 @@ protected:
         label nProcessors_;
 
 
-        //- Helper: determine (global) cellCells from mesh agglomeration.
-        static void calcCellCells
-        (
-            const polyMesh& mesh,
-            const labelList& agglom,
-            const label nCoarse,
-            CompactListList<label>& cellCells
-        );
-
 private:
 
     // Private Member Functions
@@ -224,6 +215,24 @@ public:
                 const pointField& cc
             );
 
+
+        // Other
+
+            //- Helper: determine (local or global) cellCells from mesh
+            //  agglomeration.
+            //  local  : connections are in local indices. Coupled across
+            //           cyclics but not processor patches.
+            //  global : connections are in global indices. Coupled across
+            //            cyclics and processor patches.
+            static void calcCellCells
+            (
+                const polyMesh& mesh,
+                const labelList& agglom,
+                const label nCoarse,
+                const bool global,
+                CompactListList<label>& cellCells
+            );
+
 };
 
 
diff --git a/src/parallel/decompose/decompositionMethods/multiLevelDecomp/multiLevelDecomp.C b/src/parallel/decompose/decompositionMethods/multiLevelDecomp/multiLevelDecomp.C
index 19ae049335608c0fce09323ed46b6f0e84b89e56..927df123abfbb74e6067087a2af4fcbed7aaa14e 100644
--- a/src/parallel/decompose/decompositionMethods/multiLevelDecomp/multiLevelDecomp.C
+++ b/src/parallel/decompose/decompositionMethods/multiLevelDecomp/multiLevelDecomp.C
@@ -383,7 +383,7 @@ Foam::labelList Foam::multiLevelDecomp::decompose
 )
 {
     CompactListList<label> cellCells;
-    calcCellCells(mesh, identity(cc.size()), cc.size(), cellCells);
+    calcCellCells(mesh, identity(cc.size()), cc.size(), true, cellCells);
 
     labelField finalDecomp(cc.size(), 0);
     labelList cellMap(identity(cc.size()));
diff --git a/src/parallel/decompose/ptscotchDecomp/ptscotchDecomp.C b/src/parallel/decompose/ptscotchDecomp/ptscotchDecomp.C
index b27b011e841004a7c799018c5f4be20749d092bb..54be6ad834a93dd7299f28079dde493ac349e213 100644
--- a/src/parallel/decompose/ptscotchDecomp/ptscotchDecomp.C
+++ b/src/parallel/decompose/ptscotchDecomp/ptscotchDecomp.C
@@ -755,7 +755,14 @@ Foam::labelList Foam::ptscotchDecomp::decompose
 
 
     CompactListList<label> cellCells;
-    calcCellCells(mesh, identity(mesh.nCells()), mesh.nCells(), cellCells);
+    calcCellCells
+    (
+        mesh,
+        identity(mesh.nCells()),
+        mesh.nCells(),
+        true,
+        cellCells
+    );
 
     // Decompose using default weights
     List<int> finalDecomp;
@@ -807,7 +814,14 @@ Foam::labelList Foam::ptscotchDecomp::decompose
     //   adjncy      : contains neighbours (= edges in graph)
     //   xadj(celli) : start of information in adjncy for celli
     CompactListList<label> cellCells;
-    calcCellCells(mesh, agglom, agglomPoints.size(), cellCells);
+    calcCellCells
+    (
+        mesh,
+        agglom,
+        agglomPoints.size(),
+        true,
+        cellCells
+    );
 
     // Decompose using weights
     List<int> finalDecomp;
diff --git a/src/parallel/decompose/scotchDecomp/scotchDecomp.C b/src/parallel/decompose/scotchDecomp/scotchDecomp.C
index ecfde107023300a8f7cf9d564dcd9d149e9e0670..d81af37b00a4acfb6471dfd3acd16637c59da1ec 100644
--- a/src/parallel/decompose/scotchDecomp/scotchDecomp.C
+++ b/src/parallel/decompose/scotchDecomp/scotchDecomp.C
@@ -589,7 +589,14 @@ Foam::labelList Foam::scotchDecomp::decompose
 
     // Calculate local or global (if Pstream::parRun()) connectivity
     CompactListList<label> cellCells;
-    calcCellCells(mesh, identity(mesh.nCells()), mesh.nCells(), cellCells);
+    calcCellCells
+    (
+        mesh,
+        identity(mesh.nCells()),
+        mesh.nCells(),
+        true,
+        cellCells
+    );
 
     // Decompose using default weights
     List<int> finalDecomp;
@@ -634,7 +641,14 @@ Foam::labelList Foam::scotchDecomp::decompose
 
     // Calculate local or global (if Pstream::parRun()) connectivity
     CompactListList<label> cellCells;
-    calcCellCells(mesh, agglom, agglomPoints.size(), cellCells);
+    calcCellCells
+    (
+        mesh,
+        agglom,
+        agglomPoints.size(),
+        true,
+        cellCells
+    );
 
     // Decompose using weights
     List<int> finalDecomp;
diff --git a/src/renumberMethods/CuthillMcKeeRenumber/CuthillMcKeeRenumber.C b/src/renumberMethods/CuthillMcKeeRenumber/CuthillMcKeeRenumber.C
new file mode 100644
index 0000000000000000000000000000000000000000..e1ec010335a749f08f2869a1f0c5ea8ff992b6d6
--- /dev/null
+++ b/src/renumberMethods/CuthillMcKeeRenumber/CuthillMcKeeRenumber.C
@@ -0,0 +1,112 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
+     \\/     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 "CuthillMcKeeRenumber.H"
+#include "addToRunTimeSelectionTable.H"
+#include "bandCompression.H"
+#include "decompositionMethod.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+    defineTypeNameAndDebug(CuthillMcKeeRenumber, 0);
+
+    addToRunTimeSelectionTable
+    (
+        renumberMethod,
+        CuthillMcKeeRenumber,
+        dictionary
+    );
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::CuthillMcKeeRenumber::CuthillMcKeeRenumber(const dictionary& renumberDict)
+:
+    renumberMethod(renumberDict),
+    reverse_
+    (
+        renumberDict.found(typeName + "Coeffs")
+      ? Switch(renumberDict.subDict(typeName + "Coeffs").lookup("reverse"))
+      : Switch(false)
+    )
+{}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+Foam::labelList Foam::CuthillMcKeeRenumber::renumber
+(
+    const polyMesh& mesh,
+    const pointField& points
+)
+{
+    CompactListList<label> cellCells;
+    decompositionMethod::calcCellCells
+    (
+        mesh,
+        identity(mesh.nCells()),
+        mesh.nCells(),
+        false,                      // local only
+        cellCells
+    );
+
+    labelList orderedToOld = bandCompression(cellCells());
+
+    if (reverse_)
+    {
+        for (label i = 0; i < orderedToOld.size()/2; i++)
+        {
+            Swap(orderedToOld[i], orderedToOld[orderedToOld.size()-i-1]);
+        }
+    }
+
+    return invert(orderedToOld.size(), orderedToOld);
+}
+
+
+Foam::labelList Foam::CuthillMcKeeRenumber::renumber
+(
+    const labelListList& cellCells,
+    const pointField& points
+)
+{
+    labelList orderedToOld = bandCompression(cellCells);
+
+    if (reverse_)
+    {
+        for (label i = 0; i < orderedToOld.size()/2; i++)
+        {
+            Swap(orderedToOld[i], orderedToOld[orderedToOld.size()-i-1]);
+        }
+    }
+
+    return invert(orderedToOld.size(), orderedToOld);
+}
+
+
+// ************************************************************************* //
diff --git a/src/renumberMethods/CuthillMcKeeRenumber/CuthillMcKeeRenumber.H b/src/renumberMethods/CuthillMcKeeRenumber/CuthillMcKeeRenumber.H
new file mode 100644
index 0000000000000000000000000000000000000000..90a81692e02108cf90e4bb3484afd8d0c28e1b1d
--- /dev/null
+++ b/src/renumberMethods/CuthillMcKeeRenumber/CuthillMcKeeRenumber.H
@@ -0,0 +1,118 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
+     \\/     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::CuthillMcKeeRenumber
+
+Description
+    Cuthill-McKee renumbering
+
+SourceFiles
+    CuthillMcKeeRenumber.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef CuthillMcKeeRenumber_H
+#define CuthillMcKeeRenumber_H
+
+#include "renumberMethod.H"
+#include "Switch.H"
+
+namespace Foam
+{
+
+/*---------------------------------------------------------------------------*\
+                           Class CuthillMcKeeRenumber Declaration
+\*---------------------------------------------------------------------------*/
+
+class CuthillMcKeeRenumber
+:
+    public renumberMethod
+{
+    // Private data
+
+        const Switch reverse_;
+
+
+    // Private Member Functions
+
+        //- Disallow default bitwise copy construct and assignment
+        void operator=(const CuthillMcKeeRenumber&);
+        CuthillMcKeeRenumber(const CuthillMcKeeRenumber&);
+
+
+public:
+
+    //- Runtime type information
+    TypeName("CuthillMcKee");
+
+
+    // Constructors
+
+        //- Construct given the renumber dictionary
+        CuthillMcKeeRenumber(const dictionary& renumberDict);
+
+    //- Destructor
+    virtual ~CuthillMcKeeRenumber()
+    {}
+
+
+    // Member Functions
+
+        //- Return for every coordinate the wanted processor number.
+        //  We need a polyMesh (to be able to load the file)
+        virtual labelList renumber(const pointField&)
+        {
+            notImplemented("CuthillMcKeeRenumber::renumber(const pointField&)");
+            return labelList(0);
+        }
+
+        //- Return for every coordinate the wanted processor number. Use the
+        //  mesh connectivity (if needed)
+        virtual labelList renumber
+        (
+            const polyMesh& mesh,
+            const pointField& cc
+        );
+
+        //- Return for every cell the new cell label.
+        //  The connectivity is equal to mesh.cellCells() except
+        //  - the connections are across coupled patches
+        virtual labelList renumber
+        (
+            const labelListList& cellCells,
+            const pointField& cc
+        );
+
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/renumberMethods/Make/files b/src/renumberMethods/Make/files
new file mode 100644
index 0000000000000000000000000000000000000000..fb366f73c4d994bf2f23c7b452731b2599933ccb
--- /dev/null
+++ b/src/renumberMethods/Make/files
@@ -0,0 +1,7 @@
+renumberMethod/renumberMethod.C
+manualRenumber/manualRenumber.C
+CuthillMcKeeRenumber/CuthillMcKeeRenumber.C
+randomRenumber/randomRenumber.C
+springRenumber/springRenumber.C
+
+LIB = $(FOAM_LIBBIN)/librenumberMethods
diff --git a/src/renumberMethods/Make/options b/src/renumberMethods/Make/options
new file mode 100644
index 0000000000000000000000000000000000000000..03cb68d94683cbf98c9e3f9a0426943c7365dd6b
--- /dev/null
+++ b/src/renumberMethods/Make/options
@@ -0,0 +1,7 @@
+EXE_INC = \
+    -I$(LIB_SRC)/parallel/decompose/decompositionMethods/lnInclude \
+    -I$(LIB_SRC)/meshTools/lnInclude
+
+LIB_LIBS = \
+    -ldecompositionMethods \
+    -lmeshTools
diff --git a/src/renumberMethods/manualRenumber/manualRenumber.C b/src/renumberMethods/manualRenumber/manualRenumber.C
new file mode 100644
index 0000000000000000000000000000000000000000..40989264b5032e3caef7202dafa747db6e773ab3
--- /dev/null
+++ b/src/renumberMethods/manualRenumber/manualRenumber.C
@@ -0,0 +1,137 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
+     \\/     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 "manualRenumber.H"
+#include "addToRunTimeSelectionTable.H"
+#include "IFstream.H"
+#include "labelIOList.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+    defineTypeNameAndDebug(manualRenumber, 0);
+
+    addToRunTimeSelectionTable
+    (
+        renumberMethod,
+        manualRenumber,
+        dictionary
+    );
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::manualRenumber::manualRenumber(const dictionary& renumberDict)
+:
+    renumberMethod(renumberDict),
+    dataFile_
+    (
+        renumberDict.subDict(typeName+"Coeffs").lookup("dataFile")
+    )
+{}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+Foam::labelList Foam::manualRenumber::renumber
+(
+    const polyMesh& mesh,
+    const pointField& points
+)
+{
+    labelIOList oldToNew
+    (
+        IOobject
+        (
+            dataFile_,
+            mesh.facesInstance(),
+            mesh,
+            IOobject::MUST_READ,
+            IOobject::AUTO_WRITE,
+            false
+        )
+    );
+
+    // check if the final renumbering is OK
+
+    if (oldToNew.size() != points.size())
+    {
+        FatalErrorIn
+        (
+            "manualRenumber::renumber(const pointField&, const scalarField&)"
+        )   << "Size of renumber list does not correspond "
+            << "to the number of points.  Size: "
+            << oldToNew.size() << " Number of points: "
+            << points.size()
+            << ".\n" << "Manual renumbering data read from file "
+            << dataFile_ << "." << endl
+            << exit(FatalError);
+    }
+
+    // Invert to see if one to one
+    labelList newToOld(points.size(), -1);
+    forAll(oldToNew, i)
+    {
+        label newI = oldToNew[i];
+
+        if (newI < 0 || newI >= oldToNew.size())
+        {
+            FatalErrorIn
+            (
+                "manualRenumber::renumber(const pointField&"
+                ", const scalarField&)"
+            )   << "Renumbering is not one-to-one. Index "
+                << i << " maps onto " << newI
+                << ".\n" << "Manual renumbering data read from file "
+                << dataFile_ << "." << endl
+                << exit(FatalError);
+        }
+
+        if (newToOld[newI] == -1)
+        {
+            newToOld[newI] = i;
+        }
+        else
+        {
+            FatalErrorIn
+            (
+                "manualRenumber::renumber(const pointField&"
+                ", const scalarField&)"
+            )   << "Renumbering is not one-to-one. Both index "
+                << newToOld[newI]
+                << " and " << i << " map onto " << newI
+                << ".\n" << "Manual renumbering data read from file "
+                << dataFile_ << "." << endl
+                << exit(FatalError);
+        }
+    }
+
+    return oldToNew;
+}
+
+
+// ************************************************************************* //
diff --git a/src/renumberMethods/manualRenumber/manualRenumber.H b/src/renumberMethods/manualRenumber/manualRenumber.H
new file mode 100644
index 0000000000000000000000000000000000000000..9aa0d76c065bb44cb4fb02eab3c666bf05c76cee
--- /dev/null
+++ b/src/renumberMethods/manualRenumber/manualRenumber.H
@@ -0,0 +1,125 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
+     \\/     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::manualRenumber
+
+Description
+    Renumber given a cell-to-new cell association in a file
+
+SourceFiles
+    manualRenumber.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef manualRenumber_H
+#define manualRenumber_H
+
+#include "renumberMethod.H"
+
+namespace Foam
+{
+
+/*---------------------------------------------------------------------------*\
+                           Class manualRenumber Declaration
+\*---------------------------------------------------------------------------*/
+
+class manualRenumber
+:
+    public renumberMethod
+{
+    // Private data
+
+        const fileName dataFile_;
+
+
+    // Private Member Functions
+
+        //- Disallow default bitwise copy construct and assignment
+        void operator=(const manualRenumber&);
+        manualRenumber(const manualRenumber&);
+
+
+public:
+
+    //- Runtime type information
+    TypeName("manual");
+
+
+    // Constructors
+
+        //- Construct given the renumber dictionary
+        manualRenumber(const dictionary& renumberDict);
+
+    //- Destructor
+    virtual ~manualRenumber()
+    {}
+
+
+    // Member Functions
+
+        //- Return for every coordinate the wanted processor number.
+        //  We need a polyMesh (to be able to load the file)
+        virtual labelList renumber(const pointField&)
+        {
+            notImplemented("manualRenumber::renumber(const pointField&)");
+            return labelList(0);
+        }
+
+        //- Return for every coordinate the wanted processor number. Use the
+        //  mesh connectivity (if needed)
+        virtual labelList renumber
+        (
+            const polyMesh& mesh,
+            const pointField& cc
+        );
+
+        //- Return for every cell the new cell label.
+        //  The connectivity is equal to mesh.cellCells() except
+        //  - the connections are across coupled patches
+        virtual labelList renumber
+        (
+            const labelListList& cellCells,
+            const pointField& cc
+        )
+        {
+            notImplemented
+            (
+                "manualRenumber::renumber"
+                "(const labelListList&, const pointField&)"
+            );
+            return labelList(0);
+        }
+
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/renumberMethods/randomRenumber/randomRenumber.C b/src/renumberMethods/randomRenumber/randomRenumber.C
new file mode 100644
index 0000000000000000000000000000000000000000..27ddc29c3f2cdda7c90d157cc5a220ca65da4c98
--- /dev/null
+++ b/src/renumberMethods/randomRenumber/randomRenumber.C
@@ -0,0 +1,96 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
+     \\/     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 "randomRenumber.H"
+#include "addToRunTimeSelectionTable.H"
+#include "Random.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+    defineTypeNameAndDebug(randomRenumber, 0);
+
+    addToRunTimeSelectionTable
+    (
+        renumberMethod,
+        randomRenumber,
+        dictionary
+    );
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::randomRenumber::randomRenumber(const dictionary& renumberDict)
+:
+    renumberMethod(renumberDict)
+{}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+Foam::labelList Foam::randomRenumber::renumber
+(
+    const pointField& points
+)
+{
+    Random rndGen(0);
+
+    labelList oldToNew(identity(points.size()));
+
+    for (label iter = 0; iter < 10; iter++)
+    {
+        forAll(oldToNew, i)
+        {
+            label j = rndGen.integer(0, oldToNew.size()-1);
+            Swap(oldToNew[i], oldToNew[j]);
+        }
+    }
+    return oldToNew;
+}
+
+
+Foam::labelList Foam::randomRenumber::renumber
+(
+    const polyMesh& mesh,
+    const pointField& points
+)
+{
+    return renumber(points);
+}
+
+
+Foam::labelList Foam::randomRenumber::renumber
+(
+    const labelListList& cellCells,
+    const pointField& points
+)
+{
+    return renumber(points);
+}
+
+
+// ************************************************************************* //
diff --git a/src/renumberMethods/randomRenumber/randomRenumber.H b/src/renumberMethods/randomRenumber/randomRenumber.H
new file mode 100644
index 0000000000000000000000000000000000000000..54d63d2835e046cb3a7305d21d6872d47d95b2ff
--- /dev/null
+++ b/src/renumberMethods/randomRenumber/randomRenumber.H
@@ -0,0 +1,107 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
+     \\/     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::randomRenumber
+
+Description
+    Random renumber. Just to see effect of renumbering.
+
+SourceFiles
+    randomRenumber.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef randomRenumber_H
+#define randomRenumber_H
+
+#include "renumberMethod.H"
+
+namespace Foam
+{
+
+/*---------------------------------------------------------------------------*\
+                           Class randomRenumber Declaration
+\*---------------------------------------------------------------------------*/
+
+class randomRenumber
+:
+    public renumberMethod
+{
+    // Private Member Functions
+
+        //- Disallow default bitwise copy construct and assignment
+        void operator=(const randomRenumber&);
+        randomRenumber(const randomRenumber&);
+
+
+public:
+
+    //- Runtime type information
+    TypeName("random");
+
+
+    // Constructors
+
+        //- Construct given the renumber dictionary
+        randomRenumber(const dictionary& renumberDict);
+
+    //- Destructor
+    virtual ~randomRenumber()
+    {}
+
+
+    // Member Functions
+
+        //- Return for every coordinate the wanted processor number.
+        //  We need a polyMesh (to be able to load the file)
+        virtual labelList renumber(const pointField&);
+
+        //- Return for every coordinate the wanted processor number. Use the
+        //  mesh connectivity (if needed)
+        virtual labelList renumber
+        (
+            const polyMesh& mesh,
+            const pointField& cc
+        );
+
+        //- Return for every cell the new cell label.
+        //  The connectivity is equal to mesh.cellCells() except
+        //  - the connections are across coupled patches
+        virtual labelList renumber
+        (
+            const labelListList& cellCells,
+            const pointField& cc
+        );
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/renumberMethods/renumberMethod/renumberMethod.C b/src/renumberMethods/renumberMethod/renumberMethod.C
new file mode 100644
index 0000000000000000000000000000000000000000..53138673b834b98567b79141014bd20821ead9f7
--- /dev/null
+++ b/src/renumberMethods/renumberMethod/renumberMethod.C
@@ -0,0 +1,131 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
+     \\/     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/>.
+
+InClass
+    renumberMethod
+
+\*---------------------------------------------------------------------------*/
+
+#include "renumberMethod.H"
+#include "decompositionMethod.H"
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+namespace Foam
+{
+    defineTypeNameAndDebug(renumberMethod, 0);
+    defineRunTimeSelectionTable(renumberMethod, dictionary);
+}
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+Foam::autoPtr<Foam::renumberMethod> Foam::renumberMethod::New
+(
+    const dictionary& renumberDict
+)
+{
+    const word methodType(renumberDict.lookup("method"));
+
+    //Info<< "Selecting renumberMethod " << methodType << endl;
+
+    dictionaryConstructorTable::iterator cstrIter =
+        dictionaryConstructorTablePtr_->find(methodType);
+
+    if (cstrIter == dictionaryConstructorTablePtr_->end())
+    {
+        FatalErrorIn
+        (
+            "renumberMethod::New"
+            "(const dictionary& renumberDict)"
+        )   << "Unknown renumberMethod "
+            << methodType << nl << nl
+            << "Valid renumberMethods are : " << endl
+            << dictionaryConstructorTablePtr_->sortedToc()
+            << exit(FatalError);
+    }
+
+    return autoPtr<renumberMethod>(cstrIter()(renumberDict));
+}
+
+
+Foam::labelList Foam::renumberMethod::renumber
+(
+    const polyMesh& mesh,
+    const pointField& points
+)
+{
+    CompactListList<label> cellCells;
+    decompositionMethod::calcCellCells
+    (
+        mesh,
+        identity(mesh.nCells()),
+        mesh.nCells(),
+        false,                      // local only
+        cellCells
+    );
+
+    // Renumber based on agglomerated points
+    return renumber(cellCells(), points);
+}
+
+
+Foam::labelList Foam::renumberMethod::renumber
+(
+    const polyMesh& mesh,
+    const labelList& fineToCoarse,
+    const pointField& coarsePoints
+)
+{
+    CompactListList<label> coarseCellCells;
+    decompositionMethod::calcCellCells
+    (
+        mesh,
+        fineToCoarse,
+        coarsePoints.size(),
+        false,                      // local only
+        coarseCellCells
+    );
+
+    // Renumber based on agglomerated points
+    labelList coarseDistribution
+    (
+        renumber
+        (
+            coarseCellCells(),
+            coarsePoints
+        )
+    );
+
+    // Rework back into renumbering for original mesh_
+    labelList fineDistribution(fineToCoarse.size());
+
+    forAll(fineDistribution, i)
+    {
+        fineDistribution[i] = coarseDistribution[fineToCoarse[i]];
+    }
+
+    return fineDistribution;
+}
+
+
+// ************************************************************************* //
diff --git a/src/renumberMethods/renumberMethod/renumberMethod.H b/src/renumberMethods/renumberMethod/renumberMethod.H
new file mode 100644
index 0000000000000000000000000000000000000000..b4b6e89f220be61a890d156559feb49d7edd6d2a
--- /dev/null
+++ b/src/renumberMethods/renumberMethod/renumberMethod.H
@@ -0,0 +1,161 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
+     \\/     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::renumberMethod
+
+Description
+    Abstract base class for renumbering
+
+SourceFiles
+    renumberMethod.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef renumberMethod_H
+#define renumberMethod_H
+
+#include "polyMesh.H"
+#include "pointField.H"
+#include "CompactListList.H"
+
+namespace Foam
+{
+
+/*---------------------------------------------------------------------------*\
+                           Class renumberMethod Declaration
+\*---------------------------------------------------------------------------*/
+
+class renumberMethod
+{
+
+protected:
+
+    // Protected data
+
+        const dictionary& renumberDict_;
+
+private:
+
+    // Private Member Functions
+
+        //- Disallow default bitwise copy construct and assignment
+        renumberMethod(const renumberMethod&);
+        void operator=(const renumberMethod&);
+
+
+public:
+
+    //- Runtime type information
+    TypeName("renumberMethod");
+
+
+    // Declare run-time constructor selection tables
+
+        declareRunTimeSelectionTable
+        (
+            autoPtr,
+            renumberMethod,
+            dictionary,
+            (
+                const dictionary& renumberDict
+            ),
+            (renumberDict)
+        );
+
+
+    // Selectors
+
+        //- Return a reference to the selected renumbering method
+        static autoPtr<renumberMethod> New
+        (
+            const dictionary& renumberDict
+        );
+
+
+    // Constructors
+
+        //- Construct given the renumber dictionary
+        renumberMethod(const dictionary& renumberDict)
+        :
+            renumberDict_(renumberDict)
+        {}
+
+
+    //- Destructor
+    virtual ~renumberMethod()
+    {}
+
+
+    // Member Functions
+
+        //- Return for every cell the new cell label.
+        //  This is only defined for geometric renumberMethods.
+        virtual labelList renumber(const pointField&)
+        {
+            notImplemented
+            (
+                "renumberMethod:renumber(const pointField&)"
+            );
+            return labelList(0);
+        }
+
+        //- Return for every cell the new cell label. Use the
+        //  mesh connectivity (if needed)
+        virtual labelList renumber(const polyMesh&, const pointField&);
+
+        //- Return for every cell the new cell label. Gets
+        //  passed agglomeration map (from fine to coarse cells) and coarse
+        //  cell
+        //  location. Can be overridden by renumberMethods that provide this
+        //  functionality natively. Coarse cells are local to the processor
+        //  (if in parallel). If you want to have coarse cells spanning
+        //  processors use the globalCellCells instead.
+        virtual labelList renumber
+        (
+            const polyMesh& mesh,
+            const labelList& cellToRegion,
+            const pointField& regionPoints
+        );
+
+        //- Return for every cell the new cell label.
+        //  The connectivity is equal to mesh.cellCells() except
+        //  - the connections are across coupled patches
+        virtual labelList renumber
+        (
+            const labelListList& cellCells,
+            const pointField& cc
+        ) = 0;
+
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/renumberMethods/springRenumber/springRenumber.C b/src/renumberMethods/springRenumber/springRenumber.C
new file mode 100644
index 0000000000000000000000000000000000000000..5c6fa49350b6b3e7e0fbe2ff1516df590910f933
--- /dev/null
+++ b/src/renumberMethods/springRenumber/springRenumber.C
@@ -0,0 +1,172 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
+     \\/     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 "springRenumber.H"
+#include "addToRunTimeSelectionTable.H"
+#include "decompositionMethod.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+    defineTypeNameAndDebug(springRenumber, 0);
+
+    addToRunTimeSelectionTable
+    (
+        renumberMethod,
+        springRenumber,
+        dictionary
+    );
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::springRenumber::springRenumber(const dictionary& renumberDict)
+:
+    renumberMethod(renumberDict),
+    dict_(renumberDict.subDict(typeName+"Coeffs")),
+    maxCo_(readScalar(dict_.lookup("maxCo"))),
+    maxIter_(readLabel(dict_.lookup("maxIter"))),
+    freezeFraction_(readScalar(dict_.lookup("freezeFraction")))
+{}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+Foam::labelList Foam::springRenumber::renumber
+(
+    const polyMesh& mesh,
+    const pointField& points
+)
+{
+    CompactListList<label> cellCells;
+    decompositionMethod::calcCellCells
+    (
+        mesh,
+        identity(mesh.nCells()),
+        mesh.nCells(),
+        false,                      // local only
+        cellCells
+    );
+
+    return renumber(cellCells(), points);
+}
+
+
+Foam::labelList Foam::springRenumber::renumber
+(
+    const labelListList& cellCells,
+    const pointField& points
+)
+{
+    // Look at cell index as a 1D position parameter.
+    // Move cells to the average 'position' of their neighbour.
+
+    scalarField position(cellCells.size());
+    forAll(position, cellI)
+    {
+        position[cellI] = cellI;
+    }
+
+    labelList oldToNew(identity(cellCells.size()));
+
+    scalar maxCo = maxCo_ * cellCells.size();
+
+    for (label iter = 0; iter < maxIter_; iter++)
+    {
+        //Pout<< "Iteration : " << iter << nl
+        //    << "------------"
+        //    << endl;
+
+        //Pout<< "Position :" << nl
+        //    << "    min : " << min(position) << nl
+        //    << "    max : " << max(position) << nl
+        //    << "    avg : " << average(position) << nl
+        //    << endl;
+
+        // Sum force per cell.
+        scalarField sumForce(cellCells.size(), 0.0);
+        forAll(cellCells, oldCellI)
+        {
+            const labelList& cCells = cellCells[oldCellI];
+            label cellI = oldToNew[oldCellI];
+
+            forAll(cCells, i)
+            {
+                label nbrCellI = oldToNew[cCells[i]];
+
+                sumForce[cellI] += (position[nbrCellI]-position[cellI]);
+            }
+        }
+
+        //Pout<< "Force :" << nl
+        //    << "    min    : " << min(sumForce) << nl
+        //    << "    max    : " << max(sumForce) << nl
+        //    << "    avgMag : " << average(mag(sumForce)) << nl
+        //    << "DeltaT : " << deltaT << nl
+        //    << endl;
+
+        // Limit displacement
+        scalar deltaT = maxCo / max(mag(sumForce));
+
+        Info<< "Iter:" << iter
+            << "  maxCo:" << maxCo
+            << "  deltaT:" << deltaT
+            << "  average force:" << average(mag(sumForce)) << endl;
+
+        // Determine displacement.
+        scalarField displacement = deltaT*sumForce;
+
+        //Pout<< "Displacement :" << nl
+        //    << "    min    : " << min(displacement) << nl
+        //    << "    max    : " << max(displacement) << nl
+        //    << "    avgMag : " << average(mag(displacement)) << nl
+        //    << endl;
+
+        // Calculate new position and scale to be within original range
+        // (0..nCells-1) for ease of postprocessing.
+        position += displacement;
+        position -= min(position);
+        position *= (position.size()-1)/max(position);
+
+        // Slowly freeze.
+        maxCo *= freezeFraction_;
+    }
+
+    //writeOBJ("endPosition.obj", cellCells, position);
+
+    // Move cells to new position
+    labelList shuffle;
+    sortedOrder(position, shuffle);
+
+    // Reorder oldToNew
+    inplaceReorder(shuffle, oldToNew);
+
+    return oldToNew;
+}
+
+
+// ************************************************************************* //
diff --git a/src/renumberMethods/springRenumber/springRenumber.H b/src/renumberMethods/springRenumber/springRenumber.H
new file mode 100644
index 0000000000000000000000000000000000000000..d6ee7f00c1172a417095821915fd9d2c16c52248
--- /dev/null
+++ b/src/renumberMethods/springRenumber/springRenumber.H
@@ -0,0 +1,132 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
+     \\/     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::springRenumber
+
+Description
+    Use spring analogy - attract neighbouring cells according to the distance
+    of their cell indices.
+
+    // Maximum jump of cell indices. Is fraction of number of cells
+    maxCo 0.1;
+
+    // Limit the amount of movement; the fraction maxCo gets decreased
+    // with every iteration.
+    freezeFraction 0.9;
+
+    // Maximum number of iterations
+    maxIter 1000;
+
+SourceFiles
+    springRenumber.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef springRenumber_H
+#define springRenumber_H
+
+#include "renumberMethod.H"
+
+namespace Foam
+{
+
+/*---------------------------------------------------------------------------*\
+                           Class springRenumber Declaration
+\*---------------------------------------------------------------------------*/
+
+class springRenumber
+:
+    public renumberMethod
+{
+    // Private data
+
+        const dictionary& dict_;
+
+        const scalar maxCo_;
+
+        const label maxIter_;
+
+        const scalar freezeFraction_;
+
+    // Private Member Functions
+
+        //- Disallow default bitwise copy construct and assignment
+        void operator=(const springRenumber&);
+        springRenumber(const springRenumber&);
+
+
+public:
+
+    //- Runtime type information
+    TypeName("spring");
+
+
+    // Constructors
+
+        //- Construct given the renumber dictionary
+        springRenumber(const dictionary& renumberDict);
+
+    //- Destructor
+    virtual ~springRenumber()
+    {}
+
+
+    // Member Functions
+
+        //- Return for every coordinate the wanted processor number.
+        virtual labelList renumber(const pointField&)
+        {
+            notImplemented("springRenumber::renumber(const pointField&)");
+            return labelList(0);
+        }
+
+        //- Return for every coordinate the wanted processor number. Use the
+        //  mesh connectivity (if needed)
+        virtual labelList renumber
+        (
+            const polyMesh& mesh,
+            const pointField& cc
+        );
+
+        //- Return for every cell the new cell label.
+        //  The connectivity is equal to mesh.cellCells() except
+        //  - the connections are across coupled patches
+        virtual labelList renumber
+        (
+            const labelListList& cellCells,
+            const pointField& cc
+        );
+
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/triSurface/triSurface/interfaces/STL/readSTLASCII.L b/src/triSurface/triSurface/interfaces/STL/readSTLASCII.L
index 393104a7b5324bb1af0fd712502747f3ac35efc4..ddefb95a8542ba170526c11a022e23bf3bc5def3 100644
--- a/src/triSurface/triSurface/interfaces/STL/readSTLASCII.L
+++ b/src/triSurface/triSurface/interfaces/STL/readSTLASCII.L
@@ -33,8 +33,10 @@ License
 
 #include "IFstream.H"
 #include "triSurface.H"
-#include "STLpoint.H"
+#include "floatVector.H"
 #include "OSspecific.H"
+#include "mergePoints.H"
+//#include "memInfo.H"
 
 using namespace Foam;
 
@@ -77,8 +79,8 @@ class STLLexer
         label lineNo_;
         word startError_;
 
-        DynamicList<STLpoint> STLpoints_;
-        //DynamicList<STLpoint> STLnormals_;
+        DynamicList<floatVector> STLpoints_;
+        //DynamicList<floatVector > STLnormals_;
         DynamicList<label> STLlabels_;
         HashTable<label, word> STLsolidNames_;
 
@@ -103,12 +105,12 @@ public:
             return nTriangles_;
         }
 
-        DynamicList<STLpoint>& STLpoints()
+        DynamicList<floatVector>& STLpoints()
         {
             return STLpoints_;
         }
 
-        //DynamicList<STLpoint>& STLnormals()
+        //DynamicList<floatVector>& STLnormals()
         //{
         //    return STLnormals_;
         //}
@@ -202,8 +204,8 @@ endsolid              {space}("endsolid"|"ENDSOLID")({some_space}{word})*
     // End of read character pointer returned by strtof
     // char* endPtr;
 
-    STLpoint normal;
-    STLpoint vertex;
+    floatVector normal;
+    floatVector vertex;
     label cmpt = 0;   // component index used for reading vertex
 
     static const char* stateNames[7] =
@@ -387,16 +389,25 @@ bool triSurface::readSTLASCII(const fileName& STLfileName)
             << exit(FatalError);
     }
 
+    //memInfo memStat;
+
+    //memStat.update();
+    //Pout<< "At start:" << memStat.rss() << endl;
+
     // Create the lexer obtaining the approximate number of vertices in the STL
     // from the file size
     STLLexer lexer(&STLstream.stdStream(), Foam::fileSize(STLfileName)/400);
     while (lexer.lex() != 0)
     {}
 
-    DynamicList<STLpoint>& STLpoints = lexer.STLpoints();
+    //memStat.update();
+    //Pout<< "After lexing:" << memStat.rss() << endl;
+
+    DynamicList<floatVector>& STLpoints = lexer.STLpoints();
+    DynamicList<label>& STLlabels = lexer.STLlabels();
 
     /*
-    DynamicList<STLpoint>& STLnormals = lexer.STLnormals();
+    DynamicList<floatVector>& STLnormals = lexer.STLnormals();
 
     if (STLpoints.size() != 3*STLnormals.size())
     {
@@ -410,35 +421,51 @@ bool triSurface::readSTLASCII(const fileName& STLfileName)
     }
     */
 
-    pointField rawPoints(STLpoints.size());
+    labelList pointMap;
+    label nUniquePoints = mergePoints
+    (
+        STLpoints,
+        100*SMALL,              // merge distance
+        false,                  // verbose
+        pointMap
+    );
 
-    forAll(rawPoints, i)
-    {
-        rawPoints[i] = STLpoints[i];
-    }
+    //memStat.update();
+    //Pout<< "After merging:" << memStat.rss() << endl;
 
-    STLpoints.clear();
+
+    pointField& sp = storedPoints();
 
     setSize(lexer.nTriangles());
-    DynamicList<label>& STLlabels = lexer.STLlabels();
+    sp.setSize(nUniquePoints);
+    forAll(STLpoints, pointI)
+    {
+        const floatVector& pt = STLpoints[pointI];
+        sp[pointMap[pointI]] = vector
+        (
+            scalar(pt.x()),
+            scalar(pt.y()),
+            scalar(pt.z())
+        );
+    }
 
     // Assign triangles
-    label pointi = 0;
+    label pointI = 0;
     forAll(*this, i)
     {
-        operator[](i)[0] = pointi++;
-        operator[](i)[1] = pointi++;
-        operator[](i)[2] = pointi++;
+        operator[](i)[0] = pointMap[pointI++];
+        operator[](i)[1] = pointMap[pointI++];
+        operator[](i)[2] = pointMap[pointI++];
         operator[](i).region() = STLlabels[i];
     }
 
-    STLlabels.clear();
+    //memStat.update();
+    //Pout<< "After assigning:" << memStat.rss() << endl;
 
-    // Assign coordinates
-    storedPoints().transfer(rawPoints);
 
-    // Stitch all points within SMALL meters.
-    stitchTriangles();
+    STLpoints.clear();
+    STLlabels.clear();
+
 
     // Convert solidNames into regionNames
     patches_.setSize(lexer.STLsolidNames().size());
@@ -457,6 +484,9 @@ bool triSurface::readSTLASCII(const fileName& STLfileName)
     // Fill in the missing information in the patches
     setDefaultPatches();
 
+    //memStat.update();
+    //Pout<< "After patchifying:" << memStat.rss() << endl;
+
     return true;
 }
 
diff --git a/src/triSurface/triSurface/interfaces/STL/readSTLBINARY.C b/src/triSurface/triSurface/interfaces/STL/readSTLBINARY.C
index bf5d032b7ec226d3b438021cfd23f24d6dd0c28f..624aa1ada0af42ce97e93c08d4ad696bf2892abe 100644
--- a/src/triSurface/triSurface/interfaces/STL/readSTLBINARY.C
+++ b/src/triSurface/triSurface/interfaces/STL/readSTLBINARY.C
@@ -28,7 +28,8 @@ License
 #include "IFstream.H"
 #include "OSspecific.H"
 #include "gzstream.h"
-
+#include "floatVector.H"
+#include "mergePoints.H"
 
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
@@ -94,40 +95,55 @@ bool Foam::triSurface::readSTLBINARY(const fileName& STLfileName)
     // Everything OK so go ahead and read the triangles.
 
     // Allocate storage for raw points
-    pointField rawPoints(3*nTris);
-
-    // Allocate storage for triangles
+    List<floatVector> STLpoints(3*nTris);
     setSize(nTris);
 
-    label rawPointI = 0;
+    label pointI = 0;
 
-    // Read the triangles
-    forAll(*this, i)
+    for (label i = 0; i < nTris; i++)
     {
         // Read an STL triangle
         STLtriangle stlTri(STLfile);
 
-        // Set the rawPoints to the vertices of the STL triangle
-        // and set the point labels of the labelledTri
-        rawPoints[rawPointI] = stlTri.a();
-        operator[](i)[0] = rawPointI++;
-
-        rawPoints[rawPointI] = stlTri.b();
-        operator[](i)[1] = rawPointI++;
-
-        rawPoints[rawPointI] = stlTri.c();
-        operator[](i)[2] = rawPointI++;
-
+        // Set the STLpoints to the vertices of the STL triangle
+        STLpoints[pointI++] = stlTri.a();
+        STLpoints[pointI++] = stlTri.b();
+        STLpoints[pointI++] = stlTri.c();
         operator[](i).region() = stlTri.region();
     }
 
-    //STLfile.close();
+    // Stitch points
+    labelList pointMap;
+    label nUniquePoints = mergePoints
+    (
+        STLpoints,
+        10*SMALL,               // merge distance
+        false,                  // verbose
+        pointMap                // old to new
+    );
+
+    pointField& sp = storedPoints();
 
-    // Assign coordinates
-    storedPoints().transfer(rawPoints);
+    sp.setSize(nUniquePoints);
+    forAll(STLpoints, pointI)
+    {
+        const floatVector& pt = STLpoints[pointI];
+        sp[pointMap[pointI]] = vector
+        (
+            scalar(pt.x()),
+            scalar(pt.y()),
+            scalar(pt.z())
+        );
+    }
 
-    // Stitch all points within SMALL meters.
-    stitchTriangles();
+    // Assign triangles
+    pointI = 0;
+    forAll(*this, i)
+    {
+        operator[](i)[0] = pointMap[pointI++];
+        operator[](i)[1] = pointMap[pointI++];
+        operator[](i)[2] = pointMap[pointI++];
+    }
 
     return true;
 }
diff --git a/wmake/rules/General/CGAL b/wmake/rules/General/CGAL
index 126640dc0cf2f7e1c4dd84814e5fbe5526fd0add..3586a1de38517b79974e6337c72de4db4e56e028 100644
--- a/wmake/rules/General/CGAL
+++ b/wmake/rules/General/CGAL
@@ -9,4 +9,5 @@ CGAL_LIBS = \
     -L$(MPFR_ARCH_PATH)/lib \
     -L$(BOOST_ARCH_PATH)/lib \
     -lmpfr \
-    -lboost_thread
+    -I/usr/lib64 \
+    -lboost_thread-mt